python-3.x - 如何引用 subprocess.run 列表的一部分?
问题描述
我需要引用 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 .
解决方案
事实证明,诀窍是不要试图引用它。
我删除了以下行,它无需进一步修改即可工作:
ssh_cmd = f'"{ssh_cmd}"'
我已经阅读了很多文档并且在提出问题之前一直错过它。墨菲。
重读帖子“ How not to quote argument in subprocess? ”并最终理解 Greg Hewgill 所说的对我有帮助。我责怪睡眠不足。
“如果您在 shell 命令行上使用引号,则将整个内容放在args
(不带引号)的一个元素中。...” - Greg Hewgill
推荐阅读
- c++ - 使用 OpenCV 和 C++ 从 mp4 视频中提取所有视频帧
- sql - SQL:在注册过程中获取最后一个引用和发布引用页面
- r - :: NA/NaN 参数中的错误
- sql - 统计 SQL 中的所有值,如果没有任何计数则返回 0
- python - Matplotlib 中的可编辑表格:如何在表格单元格上叠加 TextBox 小部件?
- jquery - 如何重置光滑的幻灯片位置?
- ruby-on-rails - 找不到如何链接到 user_post
- gradle - gradle jacoco 与 integrationTest 和排除
- angularjs - 将多个附件从angularjs传递到spring控制器时,spring控制器中的列表为空
- javascript - 从 iframe 的文档元素中删除事件