CentOS7下subprocess.Popen调用awk、grep命令执行结果与预期不符如何解决
错误原因分析
- 带管道的grep命令报错原因:当你设置
shell=True时,subprocess要求你将完整命令作为单个字符串传入,而非字符串列表。你传入列表时,第一个元素会被识别为shell命令,后续元素会被当作shell本身的参数而非grep的入参,同时你参数里额外加的单引号也是多余的,终端里的单引号是用来给shell识别参数边界的,不需要直接传给命令本身。 - awk命令报错原因:
- 不设置
shell=True时,你给awk的参数带了多余的单引号,awk收到参数后会把单引号当成脚本内容的一部分,自然识别为无效字符。 - 设置
shell=True时你依然传入了列表参数,不符合shell=True的传参规则,所以awk报用法错误。
- 不设置
解决方法
方案1:使用shell=True(适合无用户可控输入的简单场景)
直接把终端可运行的完整命令作为单个字符串传入即可,不需要拆分列表:
import subprocess # grep管道实现 cmd = "grep 'average load:' cpuload | sed -n 's/.*load: //p' | tail -n1" test = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, encoding='utf-8') stdout, stderr = test.communicate() if test.returncode == 0: print("提取的负载值:", stdout.strip()) # awk实现 cmd = "awk 'NR > 2 && /average load:/ {print $3}' cpuload" test = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, encoding='utf-8') stdout, stderr = test.communicate() if test.returncode == 0: print("提取的负载值:", stdout.strip())
方案2:不使用shell=True(更安全,避免命令注入风险)
手动拆分管道逻辑,连接上下游命令的输入输出,同时去掉参数里多余的单引号:
import subprocess # 拆分管道实现 p1 = subprocess.Popen(["grep", "average load:", "cpuload"], stdout=subprocess.PIPE) p2 = subprocess.Popen(["sed", "-n", "s/.*load: //p"], stdin=p1.stdout, stdout=subprocess.PIPE) p3 = subprocess.Popen(["tail", "-n1"], stdin=p2.stdout, stdout=subprocess.PIPE, encoding='utf-8') p1.stdout.close() p2.stdout.close() stdout, _ = p3.communicate() print("提取的负载值:", stdout.strip()) # 直接调用awk实现 cmd = ["awk", "NR > 2 && /average load:/ {print $3}", "cpuload"] test = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8') stdout, _ = test.communicate() print("提取的负载值:", stdout.strip())
方案3:纯Python实现(无需依赖外部命令,性能更高更易维护)
直接读取文件处理即可,不需要调用shell工具:
with open("cpuload", "r", encoding='utf-8') as f: lines = f.readlines() # 倒序找最后一个average load对应的行 for line in reversed(lines): if "average load:" in line: load_val = line.strip().split("average load:")[-1].strip() print("提取的负载值:", load_val) break
内容的提问来源于stack exchange,提问作者Lotusmeristem
相关产品推荐
相关产品推荐

