Поведение 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)