Я изо всех сил пытаюсь эффективно запустить mosh в подпроцессе python. Я могу запустить mosh-клиент и подключиться к mosh-серверу, но, похоже, процесс зависает.
пример команды ssh:
ssh -o SendEnv=ENVVAR -l username server_dns_name
пример команды mosh:
mosh --ssh = "ssh -o SendEnv=ENVVAR -l username" server_dns_name
вызов python:
import subprocess
# command = "ssh -o SendEnv=ENVVAR -l username server_dns_name"
command = "mosh --ssh=\"ssh -o SendEnv=ENVVAR -l username\" server_dns_name"
proc = subprocess.run(command, env=os.environ, shell=True)
Ожидаю: нормальное взаимодействие с мош.
Я получаю: нет возможности взаимодействовать, но экран выглядит так, как будто я подключен.
Что мне не хватает?
Оболочка добавляет еще одну движущуюся часть, чем у вас была бы без нее - дополнительная сложность означает больше потенциальных вещей, которые могут пойти не так (например, любой сценарий, указанный в переменной среды с именем ENV
, выполняется во время запуска оболочки, перед оболочка получает до вызова вашей копии mosh
). Не то чтобы это высокая вероятность возникновения вашей ошибки, но чем проще, тем лучше.
Кстати, env=os.environ
совершенно бессмысленен - по умолчанию, если вы вообще не передаете env
, наследует среду родительского процесса.
Это сеанс REPL или сценарий? Имеет ли какой-либо эффект явное подключение дочерних stdin, stdout и stderr к дескрипторам на /dev/tty
(и закрытие родительских копий, если они действительно направлены туда)?
(Еще одно замечание - если вам не нужен аргумент --ssh
для воспроизведения проблемы, и вы можете проверить, что он воспроизводится без него, правильный минимальный воспроизводимый пример устранит его).
... так что я не могу воспроизвести это сам. python3.6 -c 'import subprocess, sys; command = ["mosh", sys.argv[1]]; proc = subprocess.run(command)' myhost
ведет себя идентично прямому запуску mosh
. Нет разницы, когда я добавляю "--ssh=ssh -o SendEnv=ENVVAR"
.
(... в стороне, я настоятельно не рекомендую использовать shlex.split()
, когда вместо этого вы можете жестко кодировать явный argv - как оболочка, это уровень абстракции, который добавляет сложность без каких-либо преимуществ; передача явного списка - это то, что ОС на самом деле происходит под капотом, когда он вызывает системный вызов execve()
, поэтому, если вы хотите иметь как можно больший контроль над тем, что происходит с фактически, когда вы вызываете программу, явный список - это путь).
Без использования shell = True проблем нет. Может кто-нибудь объяснить, почему shell = True является проблемой?
Здесь нет причин использовать
shell=True
; вместо этого передайте список["mosh", "--ssh=ssh -o SendEnv=ENVVAR -l username", "server_dns_name"]
в качестве первого аргумента.