Поведение python: subprocess.Popen()

Я пытаюсь использовать Rsync с Python. Я прочитал, что предпочтительным способом передачи аргументов в Popen является использование массива.

Код, который я пробовал:

p = Popen(["rsync",
        "\"{source}\"".format(source=latestPath),
        "\"{user}@{host}:{dir}\"".format(user=user, host=host, dir=dir)],
        stdout=PIPE, stderr=PIPE)

В результате rsync запрашивает пароль, хотя я настроил SSH-ключи для аутентификации.

Я думаю, что это проблема со средой, в которой запускается новый процесс. Я попробовал следующее:

p = Popen(["rsync", 
   "\"{source}\"".format(source=latestPath),
   "\"{user}@{host}:{dir}\"".format(user=user, host=host, dir=dir)],
   stdout=PIPE, stderr=PIPE, shell=True)

Это приводит к тому, что rsync печатает "правильное использование", поэтому аргументы неправильно передаются в rsync. Я не уверен, если это вообще должно работать (передача массива с shell=True)

Если я удаляю массив в целом, как это:

p = Popen("rsync \"{source}\" \"{user}@{host}:{dir}\"".format(
        source=latestPath, user=user, host=host, dir=dir),
      stdout=PIPE, stderr=PIPE, shell=True)

Программа работает отлично. Это действительно не имеет значения для этого сценария, но я хотел бы знать, в чем разница? Почему два других (в основном первый) не работают?

Просто ли требуется оболочка, а вторая неверна?

РЕДАКТИРОВАТЬ: содержание переменных

latestPath='/home/tomcat/.jenkins/jobs/MC 4thworld/workspace/target/FourthWorld-0.1-SNAPSHOT.jar'
user='mc'
host='192.168.0.32'
dir='/mc/test/plugins/'

3 ответа

Решение

Я хотел бы знать, в чем разница?

когда shell=TrueВся команда передается в оболочку. Там есть кавычки, чтобы оболочка снова могла правильно подобрать команду. В частности, прохождение

foo "bar baz"

в оболочку заставляет ее анализировать команду как (синтаксис Python) ['foo', 'bar baz'] так что он может выполнить foo команда с аргументом bar baz,

Напротив, когда shell=False, Python немедленно передаст аргументы в списке программе. Например, попробуйте следующее subprocess команды:

>>> import subprocess
>>> subprocess.call(["echo", '"Hello!"'])
"Hello!"
0
>>> subprocess.call('echo "Hello!"', shell=True)
Hello!
0

и обратите внимание, что во-первых, цитаты отражаются на вас echo программа, в то время как во втором случае оболочка удалила их перед выполнением echo,

В вашем конкретном случае, rsync получает кавычки, но не знает, как с ними обращаться; В конце концов, это не оболочка.

Может ли это быть связано с cwd или же env параметры? Может быть, в первом синтаксисе он не может найти ключи SSH...

Просто предложение, вам может быть проще использовать sh вместо подпроцесса:

import sh
sh.rsync(latestPath, user+"@"+host+":"+dir)
Другие вопросы по тегам