ssh зависает при прямом вызове команды, но завершается чисто при интерактивном запуске
Вопрос
Мне нужно запустить сервер на удаленном компьютере и получить номер порта, на котором выполняется запуск серверного процесса.При вызове сервер прослушивает случайный порт и выводит номер порта в stderr.
Я хочу автоматизировать процесс входа на удаленный компьютер, запуска процесса и получения номера порта.Я написал скрипт на Python под названием "invokejob.py
" который находится на удаленном компьютере и действует как оболочка, которая вызывает задание, а затем возвращает номер порта, это выглядит следующим образом:
import re, subprocess
executable = ... # Name of executable
regex = ... # Regex to extract the port number from the output
p = subprocess.Popen(executable,
bufsize=1, # line buffered
stderr=subprocess.PIPE
)
s = p.stderr.readline()
port = re.match(regex).groups()[0]
print port
Если я вхожу в систему в интерактивном режиме, этот скрипт работает:
$ ssh remotehost.example.com
Last login: Thu Aug 28 17:31:18 2008 from localhost
$ ./invokejob.py
63409
$ exit
logout
Connection to remotehost.example.com closed.
(Примечание:успешный выход из системы, он не зависал).
Однако, если я попытаюсь вызвать его из командной строки, он просто зависнет:
$ ssh remotehost.example.com invokejob.py
Кто-нибудь знает, почему это зависает во втором случае, и что я могу сделать, чтобы избежать этого?
Обратите внимание, что мне нужно получить выходные данные программы, поэтому я не могу просто использовать ssh-флаг "-f" или перенаправить стандартный вывод.
Решение
s = p.stderr.readline()
Я подозреваю, что это вышеприведенная строка.Когда вы вызываете команду напрямую через ssh, вы не получаете свой полный pty (предполагая Linux) и, следовательно, не можете читать stderr.
Когда вы входите в систему в интерактивном режиме, stdin, stdout и stderr настроены для вас, и поэтому ваш скрипт работает.
Другие советы
@Бен Коллинз
Я думаю, вы правы насчет того, что stderr является проблемой.Я почти уверен, что это блокирует вызов readline().
В конце концов, я сдался и решил использовать модуль pxssh из перспективный чтобы автоматизировать мое взаимодействие с сеансом ssh.
@Миша М
К сожалению, трюк с точкой с запятой здесь не работает:это блокирует выполнение моей программы.
что, если вы сделаете следующее:
ssh <remote host> '<your command> ;<your regexp using awk or something>'
Например
ssh <remote host> '<your program>; ps aux | awk \'/root/ {print $2}\''
Это позволит подключиться, выполнить и затем распечатать каждый PSID для любого пользователя root или любого процесса с root в его описании.
Я использовал этот метод для выполнения всех видов команд на удаленных машинах.Суть в том, чтобы заключить команды, которые вы хотите выполнить, в одинарные кавычки (') и разделять каждую команду точкой с запятой (;).