在 python 中从 Popen 中执行时 rsync 找不到文件

rsync cannot find file when executed from within Popen in python

我正在尝试编写一个函数,它将接受两个参数 - sourceoutput 并调用 rsync 以将源文件复制到输出文件夹。这是该函数的主要部分:

# Run rsync
try:
    command = ['/usr/bin/rsync', "-avz", "-e", '"ssh -i rsync-key"', source, dest]
    p = Popen(command, stdout=PIPE, stderr=PIPE)
    stdo, stde = p.communicate()
    if p.returncode != 0:
        raise Exception("Failed to run rsync command {} with return code of {}. {}".format(' '.join(command), p.returncode, stde))
    else:
        logging.info("Done running rsync command {} with return code of {}. {}".format(' '.join(command), p.returncode, stdo))
except Exception as ex:
    raise Exception("Failed to run rsync command {}. {}".format(' '.join(command), ex))

rsync-key 是与 python 脚本位于同一目录中的 ssh 私钥(权限为 700),我在 authorized_keys 文件中有 public 密钥在我的服务器上(为了测试我的脚本,我试图从同一台服务器复制文件)。

我正在使用源文件 USERNAME@localhost:/home/USERNAME/.vimrc 和输出文件夹 tmp/ 测试脚本。这两个位置都存在。

如果我 运行 使用本地路径(而不是 USERNAME@localhost:...)它也 运行 就好了。

当我 运行 这个 python 程序时,我得到以下输出

CRITICAL $(asctime)-15s Error with rsync: Failed to run rsync command /usr/bin/rsync -avz -e "ssh -i rsync-key" USERNAME@localhost:/home/USERNAME/.vimrc tmp/. 
Failed to run rsync command /usr/bin/rsync -avz -e "ssh -i rsync-key" USERNAME@localhost:/home/USERNAME/.vimrc tmp/ with return code of 14. rsync: 
Failed to exec ssh -i rsync-key: No such file or directory (2)
rsync error: error in IPC code (code 14) at pipe.c(84) [receiver=3.0.4]
rsync: connection unexpectedly closed (0 bytes received so far) [receiver]
rsync error: error in IPC code (code 14) at io.c(641) [receiver=3.0.4]
Traceback (most recent call last):
  File "fetch.py", line 95, in main
    rsync(args.source_file, args.output_dir)
  File "fetch.py", line 57, in rsync
    raise Exception("Failed to run rsync command {}. {}".format(' '.join(command), ex))

但是,如果我运行在正常shell中使用相同的命令/usr/bin/rsync -avz -e "ssh -i rsync-key" USERNAME@localhost:/home/USERNAME/.vimrc tmp/,它运行就很顺利。知道为什么 python 似乎找不到我的 rsync-key 文件吗?

我期待任何回复!

你那里有一些额外的引号。删除此行中 ssh 命令周围的一组引号,如下所示:

command = ['/usr/bin/rsync', "-avz", "-e", "ssh -i rsync-key", source, dest]

原因是,通过使用作为列表的 command,您不会 运行 通过 shell,因此通常的 shell 解析规则不会申请。您的列表直接包含传递给子进程的每个参数,参数可以包含空格。