Распределение Paramiko и Pseudo-tty
Я пытаюсь использовать Paramiko для подключения к удаленному хосту и выполнения ряда подстановок текстовых файлов.
i, o, e = client.exec_command("perl -p -i -e 's/" + initial + "/"
+ replaced + "/g'" + conf);
Некоторые из этих команд должны выполняться как sudo, что приводит к:
sudo: извините, вы должны иметь tty для run sudo
Я могу принудительно распределить псевдо-tty с помощью ключа -t и ssh.
Можно ли сделать то же самое с помощью paramiko?
Ответы
Ответ 1
Я думаю, вам нужен метод invoke_shell
объекта SSHClient
(я бы хотел указать URL-адрес, но paramiko docs на lag.net являются тяжелыми кадрами и просто не покажут мне определенного URL-адреса для данного места в документах) - он дает вам Channel
, на котором вы можете сделать exec_command
и тому подобное, но что через псевдотерминал (в комплекте с типом терминала и числами строк и столбцов!), который, похоже, является тем, о чем вы просите.
Ответ 2
На самом деле это довольно просто. Просто:
stdin, stdout, stderr = client.exec_command(command, get_pty=True)
Ответ 3
Следующий код работает для меня:
#!/usr/bin/env python
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('localhost',username='root',password='secret')
chan = ssh.get_transport().open_session()
chan.get_pty()
chan.exec_command('tty')
print(chan.recv(1024))
Это было просто собрано из нескольких примеров онлайн... не уверен, что это "правильный" способ.
Ответ 4
В соответствии с sudo manpage:
Опция -S (stdin) заставляет sudo считывать пароль со стандартного ввода вместо терминального устройства. за паролем должен следовать символ новой строки.
Вы можете написать в stdin, потому что это файловый объект с write():
import paramiko
client = paramiko.client.SSHClient()
client.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
client.connect(hostname='localhost', port=22, username='user', password='password')
stdin, stdout, stderr = client.exec_command('sudo -S aptitude update')
stdin.write('password\n')
stdin.flush()
# print the results
print stdout.read()
client.close()