如何从subprocess.call()的多列输出中提取kubectl的ADDRESS列IP?
Hey there! Let's break this down for you first—you might have noticed a small gotcha with subprocess.call(): it returns the exit status code of the command (0 for success, non-zero for errors), not the actual output of kubectl. That's why when you print test, you're seeing a number instead of the ingress details you expected.
To get the IP from the ADDRESS column, we need to first capture the command's output, then parse it. Here are two solid approaches:
1. Parse the plain text output (quick, but less robust)
This works if you're sure the output format won't change, but keep in mind that column spacing can shift if longer values are present.
import subprocess # Capture the command output instead of just the exit code cmd_result = subprocess.run( "kubectl get ingress -o wide", shell=True, capture_output=True, text=True # Automatically decode bytes to string ) if cmd_result.returncode == 0: # Split output into lines, strip extra whitespace output_lines = cmd_result.stdout.strip().split("\n") # Extract headers to find the index of the ADDRESS column headers = output_lines[0].split() address_col_index = headers.index("ADDRESS") # Get the data line (assuming only one ingress here; loop if multiple) data_fields = output_lines[1].split() ip_address = data_fields[address_col_index] print(f"Extracted IP: {ip_address}") else: print(f"Command failed with error: {cmd_result.stderr}")
2. Use Kubernetes JSON output (more robust, recommended)
Kubectl supports structured output formats like JSON, which avoids parsing headaches from variable column spacing. This is the better approach for production code.
import subprocess import json cmd_result = subprocess.run( "kubectl get ingress -o json", shell=True, capture_output=True, text=True ) if cmd_result.returncode == 0: # Load the JSON output into a Python dictionary ingress_json = json.loads(cmd_result.stdout) # Loop through all ingress resources (adjust if you only need one) for ingress in ingress_json["items"]: ingress_name = ingress["metadata"]["name"] # Extract the load balancer IP ip_address = ingress["status"]["loadBalancer"]["ingress"][0]["ip"] print(f"Ingress '{ingress_name}' IP: {ip_address}") else: print(f"Command failed with error: {cmd_result.stderr}")
A quick security note
If you're working in an environment where shell injection is a concern, avoid using shell=True and pass the command as a list instead:
# Example for the JSON approach cmd_result = subprocess.run( ["kubectl", "get", "ingress", "-o", "json"], capture_output=True, text=True )
This way, the command is executed directly without shell interpretation, which is safer.
内容的提问来源于stack exchange,提问作者Abdul Rehman

