Я знаю, что это дубликат, но сейчас я не могу найти соответствующие темы по этому поводу. Все, что я получаю, это output.communicate()
.
Итак, вот фрагмент, который может быть полезен:
import subprocess
cmd = ['ngrok', 'http', '5000']
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while process.poll() is None:
print(process.stdout.readline())
print(process.stdout.read())
process.stdout.close()
Это выведет все, что выводит процесс, через ваш скрипт на ваш вывод. Это делается путем поиска символа новой строки перед выводом.
Этот фрагмент кода мог бы работать, если бы не тот факт, что ngrok
использует ncurses и/или перехватывает вывод для своего собственного пользователя/потока, как когда SSH запрашивает пароль, когда вы выполняете ssh user@host
.
process.poll()
проверяет, есть ли у процесса код выхода (если он мертв), если нет, он продолжает цикл и печатает что-либо из stdout
процесса.
Есть и другие (лучшие) способы сделать это, но это минимум, который я могу вам дать, не усложняя его очень быстро.
Например, process.stdout.read()
можно использовать в сочетании с select.select()
для достижения лучшей буферизации вывода, когда символы новой строки пугают. Потому что, если \n
никогда не придет, приведенный выше пример может привести к зависанию всего вашего приложения.
Здесь много буферных ловушек, о которых вам нужно знать, прежде чем делать такие вещи вручную. В противном случае используйте вместо него process.communicate()
.
Редактировать: чтобы обойти ограничение ввода-вывода, используемое ngrok, вы можете использовать pty.fork()
и прочитать дочерний стандартный вывод через модуль os.read
:
#!/usr/bin/python
## Requires: Linux
## Does not require: Pexpect
import pty, os
from os import fork, waitpid, execv, read, write, kill
def pid_exists(pid):
"""Check whether pid exists in the current process table."""
if pid < 0:
return False
try:
kill(pid, 0)
except (OSError, e):
return e.errno == errno.EPERMRM
else:
return True
class exec():
def __init__(self):
self.run()
def run(self):
command = [
'/usr/bin/ngrok',
'http',
'5000'
]
# PID = 0 for child, and the PID of the child for the parent
pid, child_fd = pty.fork()
if not pid: # Child process
# Replace child process with our SSH process
execv(command[0], command)
while True:
output = read(child_fd, 1024)
print(output.decode('UTF-8'))
lower = output.lower()
# example input (if needed)
if b'password:' in lower:
write(child_fd, b'some response\n')
waitpid(pid, 0)
exec()
Здесь все еще есть проблема, и я не совсем уверен, что и почему.
Я предполагаю, что процесс каким-то образом ожидает сигнала/сброса.
Проблема в том, что он печатает только первый «установочные данные» ncurses, что означает, что он очищает экран и устанавливает цвет фона.
Но это даст вам, по крайней мере, результат процесса. замена print(output.decode('UTF-8'))
покажет вам, что это за вывод.
person
Torxed
schedule
09.11.2018
subprocess
. - person Torxed   schedule 10.11.2018