【问题标题】:How to quote part of a subprocess.run list? [duplicate]如何引用 subprocess.run 列表的一部分?
【发布时间】:2020-03-04 01:52:36
【问题描述】:

我需要引用 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 .

【问题讨论】:

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


    【解决方案1】:

    事实证明,诀窍是不要试图引用它。

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

    ssh_cmd = f'"{ssh_cmd}"'
    

    我已经阅读了很多文档并且在提出问题之前一直错过它。墨菲。

    重读帖子“How not to quote argument in subprocess?”并最终理解 Greg Hewgill 所说的对我有帮助。我责怪睡眠不足。

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

    【讨论】:

      猜你喜欢
      • 2010-12-19
      • 2014-12-17
      • 2018-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-03
      • 2013-10-14
      相关资源
      最近更新 更多