Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中使用选项中的空格运行子流程_Python_Ssh_Subprocess - Fatal编程技术网

在python中使用选项中的空格运行子流程

在python中使用选项中的空格运行子流程,python,ssh,subprocess,Python,Ssh,Subprocess,我试图寻找一个答案有一段时间,但我没有找到任何东西,到目前为止,我的具体情况。我想在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>

我试图寻找一个答案有一段时间,但我没有找到任何东西,到目前为止,我的具体情况。我想在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'

如何将此选项传递给我的命令?

您的SSH命令包含无效参数:
ProxyCommand
是一个选项,因此它前面需要加上
-o
,与
ConnectTimeout
(而且,正如Charles Duffy所指出的,该选项字符串中的冗余引号需要删除,因为命令没有传递给shell):

通常,当命令行包含空格和/或引号并传递给另一个命令时,可能需要对其进行shell引号。Python函数会自动执行此操作。在您的情况下,不需要这样做,因为您(正确地)手动引用传递到
屏幕
中的
服务器\u命令
中的命令。或者,您可以编写以下内容:

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引用,例如,在嵌套命令调用时。

“在…之前,一切都正常工作。”请用您的问题描述该更改发生的情况。包括您得到的任何错误或异常。您在原始shell命令的语法位置添加文字引号。只需将它们去掉。也就是说:在bash(或任何其他POSIX shell)中,
ProxyCommand之间没有任何区别=“ssh-q-W%h:%p bastion.host.com”
“ProxyCommand=ssh-q-W%h:%p bastion.host.com"
'ProxyCommand=ssh-q-W%h:%p bastion.host.com'
--它们都作为完全相同的C字符串传递给ssh;应用程序甚至无法知道有什么不同。感谢您的回复。字符串而不是列表是我开始尝试所有操作后出现的另一个错误。我修复了它并更新了问题更多信息发生了什么(shlex.quote没有帮助:()@rainmaker啊,是的,当然。我应该注意到这一点-请参阅更新的答案。这段代码真的有效吗?当我运行
ssh-o'ProxyCommand=“ssh-q-W%h:%p a-host-I-can-access”'other-host-i-can-access
——使用文字引号而不是语法引号,就像您这里的Python代码正在创建的那样——我得到了我预期的错误:
/bin/sh:exec:ssh-q-W a-host-i-can-access:22 other-host-i-can-access:not found
…也就是说,我非常确定保留OP的原始引号shell命令(在该命令中它们被视为shell语法)并将它们复制到Python代码中(在该代码中它们被视为文本),这是错误的。@CharlesDuffy不,您的注释/答案是正确的;我错过了这些引号。这强化了我的信念,即shell引号永远不应该手动完成。
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)}'