首页 > 解决方案 > 在python的选项中运行带有空格的子进程

问题描述

我试图寻找答案一段时间,但到目前为止我没有找到任何适合我的具体案例的东西。我想在 python 中运行命令:

ssh -o ConnectTimeout=3 -o ProxyCommand="ssh -q -W %h:%p bastion.host.com" host.com  "screen -dmS TEST /bin/bash --login -c 'yes | script.sh --option-1 value1 -option2 value2 2>&1 | tee output.log'"

这是我的代码:

import subprocess

server_command = "screen -dmS TEST /bin/bash --login -c 'yes | script.sh --option-1 value1 -option2 value2 2>&1 | tee output.log'"
command = ['ssh', '-o', 'ConnectTimeout=3', 'ProxyCommand="ssh -q -W %h:%p bastion.host.com"', 'host.com', server_command]
    
p = subprocess.Popen(command, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
stdout, stderr = p.communicate(input=None)

一切正常(屏幕是在脚本运行时生成的),直到我添加了带空格的选项:ProxyCommand="ssh -q -W %h:%p bastion.host.com"

之后我得到错误:

>>> print(stderr)
b'ssh: Could not resolve hostname ProxyCommand="ssh -q -W %h:%p bastion.host.com": Name or service not known\r\n'

我怎样才能将此选项传递给我的命令?

标签: pythonsshsubprocess

解决方案


您的 SSH 命令包含无效参数:ProxyCommand是一个选项-o,因此它需要ConnectTimeout以壳):

server_command = 'screen -dmS TEST /bin/bash --login -c \'yes | script.sh --option-1 value1 -option2 value2 2>&1 | tee output.log\''
command = ['ssh', '-o', 'ConnectTimeout=3', '-o', 'ProxyCommand=ssh -q -W %h:%p bastion.host.com', 'host.com', server_command]

通常,当您的命令行包含空格和/或引号并传递给另一个命令时,可能需要对其进行 shell-quote。Python 函数shlex.quote自动执行此操作。在您的情况下,这不是必需的,因为您(正确地)手动引用了您传递给screeninside的命令server_command。或者,您可以编写以下内容:

script_command = 'yes | script.sh --option-1 value1 -option2 value2 2>&1 | tee output.log'
server_command = f'screen -dmS TEST /bin/bash --login -c {shlex.quote(script_command)}'

— 请注意 shell 命令行中没有手动引号。与手动引用相比的优势在于,这也适用于嵌套级别的 shell 引用,例如在嵌套命令调用时。


推荐阅读