Python中subprocess.run调用含awk的SSH远程命令报错排查
解决subprocess执行带awk的SSH远程命令报错问题
问题根源
你的run函数依赖shlex.split(cmd)拆分命令字符串,但原命令中存在嵌套引号结构(外层双引号包裹SSH远程命令,远程命令内部又用单引号包裹awk脚本),shlex.split会错误拆分这些嵌套引号,导致传到远程服务器的awk命令被截断,触发awk: line 2: missing } near end of file语法错误。
比如原命令字符串:
"ssh myserver \"tail -10 server.log | awk '{print $7}'\""
被shlex.split拆分后,awk部分会被拆成'{print和$7}'两个独立参数,远程执行时就变成了不完整的awk脚本,自然报错。
而含grep的命令能正常运行,是因为grep对引号的语法容忍度更高,即便拆分后参数略有异常,仍能解析执行,但awk的脚本必须完整包裹在引号内,所以直接暴露了问题。
解决方案
方案1:改用shell=True执行命令
如果你的命令是可控的(不存在注入风险),可以直接去掉shlex.split,启用shell=True让系统shell完整解析命令字符串:
修改后的run函数:
import subprocess from pprint import pprint def run(cmd = ""): sp = subprocess.run(cmd, shell=True, capture_output=True) pprint(sp) print(sp.stdout.decode("utf-8", 'ignore'))
调用方式保持不变:
run(cmd = "ssh myserver \"tail -10 server.log | awk '{print $7}'\"")
方案2:手动构造命令列表(避免shell=True)
如果不想依赖系统shell,可以手动构造subprocess的命令参数列表,将SSH的远程命令作为一个完整的参数传递,绕开shlex.split的错误拆分:
修改后的run函数:
import subprocess from pprint import pprint def run(cmd_list): sp = subprocess.run(cmd_list, shell=False, capture_output=True) pprint(sp) print(sp.stdout.decode("utf-8", 'ignore'))
调用时直接传入参数列表:
run(cmd_list = ["ssh", "myserver", "tail -10 server.log | awk '{print $7}'"])
这种方式更安全,也能保证远程命令的完整性,避免传输GB级日志的问题。
内容的提问来源于stack exchange,提问作者RatDon
相关产品推荐
相关产品推荐

