Как передать команду в команде в pexpext в python

Мне нужно в python выполнить эту команду и ввести пароль с клавиатуры, это работает:

import os
cmd = "cat /home/user1/.ssh/id_rsa.pub | ssh [email protected] \'cat >> .ssh/authorized_keys\' > /dev/null 2>&1"
os.system(cmd)

Как видите, я хочу добавить открытый ключ к удаленному хосту через ssh.
См. здесь: эквивалент-of-ftp-put-and-append-in-scp и здесь: копировать-и-добавить-файлы-на-удаленный-machine-cat-error

Конечно, я хочу, чтобы он делал это без пользовательского ввода. Я пробовал pexpect, и я думаю, что команда для него слишком странная:

import pexpect

child = pexpect.spawn(command=cmd, timeout=10, logfile=open('debug.txt', 'a+'))
matched = child.expect(['Password:', pexpect.EOF, pexpect.TIMEOUT])
if matched == 0:
    child.sendline(passwd)

в отладке.txt:

ssh-rsa AAAA..........vcxv233x5v3543sfsfvsv user1@host1
/bin/cat: |: No such file or directory
/bin/cat: ssh: No such file or directory
/bin/cat: [email protected]: No such file or directory
/bin/cat: cat >> .ssh/authorized_keys: No such file or directory
/bin/cat: >: No such file or directory
/bin/cat: 2>&1: No such file or directory

Я вижу два решения:

  1. исправьте команду для pexpect, чтобы она распознавала всю строку как одну команду или,
  2. ввести/записать пароль на стандартный ввод под фальшивым пользователем, но как!?!?

person emcek    schedule 23.10.2015    source источник
comment
несвязанный: нет необходимости экранировать одинарные кавычки внутри двойных кавычек в Python: "_'|'_"   -  person jfs    schedule 24.10.2015
comment
вы рассматривали ssh-copy-id вместо этого?   -  person jfs    schedule 24.10.2015
comment
@ J.F.Sebastian Нет, недоступен.   -  person emcek    schedule 26.10.2015
comment
ssh-copy-id — это просто сценарий оболочки. Если у вас установлен клиент openssh (команда ssh), то он должен быть доступен.   -  person jfs    schedule 26.10.2015


Ответы (2)


Из документов pexpect:

Помните, что Pexpect НЕ интерпретирует метасимволы оболочки, такие как перенаправление, конвейер или подстановочные знаки (>, | или *). Это распространенная ошибка. Если вы хотите запустить команду и передать ее через другую команду, вы также должны запустить оболочку. Например::

child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"')
child.expect(pexpect.EOF)
person jfs    schedule 24.10.2015

Это сработало для меня:

command = "/bin/bash -c \"cat /home/user1/.ssh/id_rsa.pub | ssh [email protected] \'cat >> ~/.ssh/authorized_keys\' > /dev/null 2>&1\""
child = spawn(command=command, timeout=5)
person emcek    schedule 27.10.2015