如何引用subprocess.run列表的一部分?

时间:2019-11-07 13:09:43

标签: python-3.x linux ssh subprocess rsync

我需要引用subprocess.run使用的包含ssh参数的rsync行的一部分,不幸的是,到目前为止我还没有尝试过。

有人可以建议我用正确的方式引用ssh参数,以便它在rsync下运行。

起初,我有一个传递给subprocess.run的列表的列表,但失败了:

Traceback (most recent call last):
  File "./tmp.py", line 20, in <module>
    process = subprocess.run(rsync_cmd, stderr=subprocess.PIPE)
  File "/usr/lib/python3.6/subprocess.py", line 423, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.6/subprocess.py", line 729, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.6/subprocess.py", line 1295, in _execute_child
    restore_signals, start_new_session, preexec_fn)
TypeError: expected str, bytes or os.PathLike object, not list

将其平铺到普通列表中

Unexpected remote arg: example.com:/var/log/maillog
rsync error: syntax or usage error (code 1) at main.c(1361) [sender=3.1.2]

这很有意义,因为rsync的命令行部分需要用引号引起来。

所以我尝试引用它:

rsync: Failed to exec /usr/bin/ssh -F /home/rspencer/.ssh/config -o PreferredAuthentications=publickey -o StrictHostKeyChecking=accept-new -o TCPKeepAlive=yes -o ServerAliveInterval=5 -o ServerAliveCountMax=24 -o ConnectTimeout=30 -o ExitOnForwardFailure=yes -o ControlMaster=autoask -o ControlPath=/run/user/1000/foo-ssh-master-%C -l root -p 234 -o Compression=yes: No such file or directory (2)
rsync error: error in IPC code (code 14) at pipe.c(85) [Receiver=3.1.2]
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in IPC code (code 14) at io.c(235) [Receiver=3.1.2]

我希望这是由于它是字符串而不是列表。尽管我在猜测,但这对我来说并不完全。

我上次尝试的摘要代码:

#!/usr/bin/python3

import subprocess

ssh_args = [
    "-F",
    "/home/rspencer/.ssh/config",
    "-o",
    "PreferredAuthentications=publickey",
    "-o",
    "StrictHostKeyChecking=accept-new",
    "-o",
    "TCPKeepAlive=yes",
    "-o",
    "ServerAliveInterval=5",
    "-o",
    "ServerAliveCountMax=24",
    "-o",
    "ConnectTimeout=30",
    "-o",
    "ExitOnForwardFailure=yes",
    "-o",
    "ControlMaster=autoask",
    "-o",
    "ControlPath=/run/user/1000/foo-ssh-master-%C",
    "-l",
    "root",
    "-p",
    "234",
]
rsync_params = []
src = "example.com:/var/log/maillog"
dest = "."

# Build SSH command
ssh_cmd = ["/usr/bin/ssh"] + ssh_args

# Use basic compression
ssh_cmd.extend(["-o", "Compression=yes"])

ssh_cmd = " ".join(ssh_cmd)
ssh_cmd = f'"{ssh_cmd}"'

# Build rsync command
rsync_cmd = ["/usr/bin/rsync", "-vP", "-e", ssh_cmd] + rsync_params + [src, dest]

# Run rsync
process = subprocess.run(rsync_cmd, stderr=subprocess.PIPE)

if process.returncode != 0:
    print(process.stderr.decode("UTF-8").strip())

正确的命令在命令行上是什么样的:

/usr/bin/rsync -vP -e "/usr/bin/ssh -F /home/rspencer/.ssh/config -o \
PreferredAuthentications=publickey -o StrictHostKeyChecking=accept-new -o \
TCPKeepAlive=yes -o ServerAliveInterval=5 -o ServerAliveCountMax=24 -o \
ConnectTimeout=30 -o ExitOnForwardFailure=yes -o ControlMaster=autoask \
-o ControlPath=/run/user/1000/foo-ssh-master-%C -l root -p 234 -o \
Compression=yes" example.com:/var/log/maillog .

1 个答案:

答案 0 :(得分:0)

原来的诀窍是不要尝试引用它。

我删除了以下行,并且无需进一步修改即可正常工作:

ssh_cmd = f'"{ssh_cmd}"'

我已经读了太多文档,直到提出问题之前都错过了。墨菲。

重新阅读文章“ How not to quote argument in subprocess?”并最终了解Greg Hewgill所说的内容对我有帮助。我归咎于睡眠不足。

“如果在shell命令行上使用引号,则将全部内容放在args的一个元素中(不带引号)。”-Greg Hewgill