如何传输“以进行远程执行?

How to transport " for remote execution?

我正在开发一些 python 工具来配置远程系统。 一个配置步骤需要替换文本文件中的值。 我想做一个简单的

ssh whatever@where.ever sed -i -e s/property=\"true\"/property=\"false\"/g the.remote.file

但是,它不起作用。

我尝试了 shlex + subprocess,我尝试了 pxssh(无论如何我想避免,因为它比通过 subprocess 的 ssh 调用慢得多)。似乎无论我尝试什么,true/false 周围的引号都在某种程度上被删除了。但是引号在远程系统上的那个文件中;所以如果引号没有出现在远程系统上执行的调用中,sed 将不执行任何操作。

直接从我的 bash 调用 ssh 时我可以让它工作;但是从 python 内部……没有机会。最后,我将该字符串放入文件中;使用 scp 将该文件复制到远程系统;然后我 运行 从那里再次使用 ssh。

但仍然想知道 - 是否有一种干净、直接的方法来做到这一点 "just using python"?

(注意:我正在寻找开箱即用的解决方案;不需要我的用户安装其他 "third party" 模块,例如 paramiko。)

更新:

这……太疯狂了。我只是 运行 这段代码(我认为它看起来与答案中给出的代码完全一样——我后来添加了 .format() 以便轻松地从发布的文本中隐藏 username/ip):

cmd_str= 'ssh {} "cat ~/prop"'.format(target)
subprocess.call(cmd_str, shell=True)

cmd_str= 'ssh {} "sed -i -e s/property=\"true\"/property=\"false\"/g ~/prop"'.format(target)
subprocess.call(cmd_str, shell=True)

cmd_str= 'ssh {} "cat ~/prop"'.format(target)
subprocess.call(cmd_str, shell=True)`

我得到:

property="true"
property="true"

这是否取决于远程系统上 sshd 的配置?

对我来说一切正常,我试过这个:

In [1]: import subprocess
In [2]: cmd = 'ssh ubuntu@192.168.56.101 "sed -i -e s/property=\"true\"/property=\"false\"/g ~/cfg.cfg"'
In [3]: subprocess.call(cmd, shell=True)
Out[3]: 0

并且 shell=True 可能不安全我也试过这个:

In [4]: parts = ['ssh', 'ubuntu@192.168.56.101', '`sed -i -e s/property=\"true\"/property=\"false\"/g ~/cfg.cfg`']
In [5]: subprocess.call(parts)
Out[5]: 0

在这两种情况下,我的文件都被更改了。

更新: shlex 输出

In [27]: shlex.split(cmd)
Out[27]: 
['ssh',
 'ubuntu@192.168.56.101',
 'sed -i -e s/property=true/property=false/g ~/cfg.cfg']

另请注意,在第一种情况下,我对远程命令使用双引号,但在第二种情况下,我对命令使用反引号。

更新 2:

In [9]: subprocess.call(['ssh', 'ubuntu@192.168.56.101', 'cat ~/cfg.cfg'])
property="true"
Out[9]: 0
In [10]: subprocess.call(['ssh', 'ubuntu@192.168.56.101', '`sed -i -e s/property=\"true\"/property=\"false\"/g ~/cfg.cfg`'])
Out[10]: 0
In [11]: subprocess.call(['ssh', 'ubuntu@192.168.56.101', 'cat ~/cfg.cfg'])
property="false"
Out[11]: 0

更新 3:

In [22]: cmd = 'ssh ubuntu@192.168.56.101 \'`sed -i -e s/property=\"true\"/property=\"false\"/g ~/cfg.cfg`\''
In [23]: subprocess.call(['ssh', 'ubuntu@192.168.56.101', 'cat ~/cfg.cfg'])
property="true"
Out[23]: 0
In [24]: subprocess.call(cmd, shell=True)
Out[24]: 0
In [25]: subprocess.call(['ssh', 'ubuntu@192.168.56.101', 'cat ~/cfg.cfg'])
property="false"
Out[25]: 0
In [26]: shlex.split(cmd)
Out[26]: 
['ssh',
 'ubuntu@192.168.56.101',
 '`sed -i -e s/property=\"true\"/property=\"false\"/g ~/cfg.cfg`']