在我的桌面上,以下shell命令列出远程服务器上根/aa/*/bb/
的目录
ssh my_server 'echo /aa/*/bb/'
但是,当我从python子进程调用它时,它报告错误
CalledProcessError:Command' [' ssh',' my_server',' echo / aa / * / bb /']'返回非零退出状态255
,代码在这里
subprocess.check_output(['ssh', 'my_server', 'echo /aa/*/bb/'], shell=True)
但是,如果我登录到远程服务器,并运行
subprocess.check_output('echo /aa/*/bb/', shell=True)
有效。
我做错了什么?非常感谢您的帮助。
答案 0 :(得分:4)
您的shell=True
会阻止传递参数。那是因为:
subprocess.check_output(['ssh', 'my_server', 'echo /*/'], shell=True)
...运行代码:
# /- from shell=True
# | ^ /- your first argument, becomes the script "sh -c" runs
# | | | /- your second argument, becomes $0 to that script
# | | | | /- your third argument, becomes $1 to that script
# | | | | |
sh -c ssh my_server 'echo /*/'
所以,你传递了你的shell脚本(只是确切的字符串ssh
)参数$ 0和$ 1,但它根本没有读取它们
如果您希望将其与shell=True
一起使用,则可以将其更改为:
# script $0 $1 $2
subprocess.check_output(['ssh "$@"', '_', 'my_server', 'echo /*/'], shell=True)
但更好的是将这个论点抛弃:
subprocess.check_output(['ssh', 'my_server', 'echo /*/'])
答案 1 :(得分:1)
我建议您根据文档中的此部分将参数更改为字符串而不是列表:
在带有
shell=True
的Unix上,shell默认为/ bin / sh。如果args是一个字符串,则该字符串指定要通过shell执行的命令。这意味着字符串的格式必须与在shell提示符下输入的格式完全相同。如果args是一个序列,则第一个项指定命令字符串,并且任何其他项将被视为shell本身的附加参数。也就是说,Popen相当于:Popen(['/bin/sh', '-c', args[0], args[1], ...])
这将手动执行命令(在子shell中):
subprocess.check_output('ssh my_server "echo /*/"', shell=True)
另一方面,当使用序列作为参数时,每个项目需要是列表中的单个项目,就像那样
subprocess.check_output(['ssh', 'my_server', 'echo', '/aa/*/bb/'], shell=True)