ssh зависает при прямом вызове команды, но завершается чисто при интерактивном запуске

StackOverflow https://stackoverflow.com/questions/33475

  •  09-06-2019
  •  | 
  •  

Вопрос

Мне нужно запустить сервер на удаленном компьютере и получить номер порта, на котором выполняется запуск серверного процесса.При вызове сервер прослушивает случайный порт и выводит номер порта в 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 в его описании.

Я использовал этот метод для выполнения всех видов команд на удаленных машинах.Суть в том, чтобы заключить команды, которые вы хотите выполнить, в одинарные кавычки (') и разделять каждую команду точкой с запятой (;).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top