Я пытаюсь получить скрипт python на удаленном развертываемом встроенном Linux-устройстве для выполнения команды scp. Выполнение команды прост, но если целевой сервер не указан в файле «known_hosts», scp выдает предупреждение, с которым необходимо взаимодействовать. Я бил головой об этом в течение нескольких дней, и я не могу решить 2 проблемы.Python - обработка запроса на ввод в подпроцессах
Во-первых, я не могу получить неблокирующее считывание ответов от подпроцесса для правильной работы. В следующем коде select всегда возвращает ([], [], []), даже если я знаю, что могу читать из stderr (при условии, что генерируется предупреждение о доверенных файлах хоста).
cmdString = 'scp [email protected]:file localFile -i ~/.ssh/id_rsa'
process = subprocess.Popen(shlex.split(cmdString), shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while(process.poll() is None):
readable, writable, exceptional = select.select([process.stdout], [], [process.stderr], 1)
if not (readable or writable or exceptional):
# Always hits this condition, although adding an "os.read(...)" here
# will return the error prompt from process.stderr.
print "timeout condition"
else:
# Never makes it here
for e in exceptional:
stderr = os.read(process.stderr.fileno(), 256)
print stderr
for r in readable:
stdout = os.read(process.stdout.fileno(), 256)
print stdout
Во-вторых, я не могу заставить подпроцесс продвигаться за пределы предупреждения путем подачи ввода через входной PIPE. Следующий код считывает код предупреждения из process.stderr, но затем зависает, пока я не нажму {enter} в моем терминале. Я попытался отправить «n», «n \ n» и «\ n», но ни один из них не приводит к продолжению выполнения подпроцесса (хотя все три шаблона работают при вводе вручную).
cmdString = 'scp [email protected]:file localFile -i ~/.ssh/id_rsa'
process = subprocess.Popen(shlex.split(cmdString), shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Correctly grabs warning and displays it
stderr = os.read(process.stderr.fileno(), 256)
print stderr
# Just in case there was some weird race condition or something
time.sleep(0.5)
# Doesn't ever seem to do anything
process.stdin.write('\n')
И, наконец, это имеет значение? Сначала я начал исследовать подпроцесс и PIPES, потому что я запускал scp, используя «os.system (cmdString)», который блокировал мой поток и заставлял меня разбираться с этой проблемой. Теперь, когда я использую подпроцесс, плохо ли просто отключить команду и позволить ей преуспеть или потерпеть неудачу? Неудачные подпроцессы в конечном итоге отмирают, или я могу в конечном итоге оказаться там, где у меня есть десятки или сотни скрытых попыток scp, но ожидающих ввода пользователем?
Спасибо!
Спасибо, то понимание того, что он не использует стандартный STDIN/стандартный вывод/STDERR помогло много. Похоже, что «pexpect» может правильно управлять scp, и есть даже scp-аддон для paramiko, чтобы привести все это в мир python. К сожалению, «pexpect» не может создать виртуальный файл, который ему нужен, и у меня нет скомпилированной версии пакета криптографии, который требуется paramiko. Так как я работаю на стороннем встроенном устройстве с голой костью, изменение системных настроек, позволяющих создавать pty или кросс-компиляцию пакета сложно. – digitalosmosis
@ digitalosmosis Добавлен пример «голых костей», который может вам помочь. – mweerden