Публичный номер: «Время программирования на Python», автор: Ming Ge.
При написании некоторых сценариев на Python в некоторых случаях нам нужно часто входить в удаленную службу, чтобы выполнить команду и вернуть некоторые результаты.
В среде оболочки мы делаем это так.
$ sshpass -p ${passwd} ssh -p ${port} -l ${user} -o StrictHostKeyChecking=no xx.xx.xx.xx "ls -l"
Затем вы обнаружите, что в вашем выводе есть много информации, которая вам не нужна, но вы не можете избавиться (возможно, есть способ, пожалуйста, оставьте сообщение для связи), что-то вроде этого
host: xx.xx.xx.xx, port: xx
Warning: Permanently added '[xx.xx.xx.xx]:xx' (RSA) to the list of known hosts.
Login failure: [Errno 1] This server is not registered to rmp platform, please confirm whether cdn server.
total 4
-rw-r--r-- 1 root root 239 Mar 30 2018 admin-openrc
Для прямого использования команд оболочки для выполнения команд вы можете напрямую использовать каналы или перенаправить стандартный вывод в файл, чтобы получить результаты, возвращаемые выполнением команды.
1. Использование подпроцесса
Если мы используем Python для этого, мы обычно думаем об использовании некоторых библиотек выполнения команд, таких как os.popen, os.system, commands, subprocess и т. д., чтобы получить их косвенно.
Но, насколько мне известно, вывод, получаемый этими библиотеками, является не только стандартным выводом, но и стандартной ошибкой (то есть избыточной информацией выше)
Таким образом, каждый раз, когда нам нужно очистить данные вывода, а затем организовать и отформатировать их, мы можем получить нужные данные.
Используя подпроцесс в качестве примера, как это
import subprocess
ssh_cmd = "sshpass -p ${passwd} ssh -p 22 -l root -o StrictHostKeyChecking=no xx.xx.xx.xx 'ls -l'"
status, output = subprocess.getstatusoutput(ssh_cmd)
# 数据清理,格式化的就不展示了
<code...>
Отображая приведенный выше текст + код, вы можете почувствовать болевые точки входа в систему по ssh.
- Болевая точка номер один: Требуется дополнительная установка sshpass (если не без пароля)
- Болезненная точка два: слишком много информации о помехах, очистка данных и форматирование довольно хлопотны
- Боль точка три: Реализация кода не элегантна (немного грязновата), а читабельность слишком плохая.
- Боль номер четыре: ssh-соединение нельзя использовать повторно, а соединение можно выполнить только один раз.
- Пятая болевая точка: Код не является общеплатформенным, доступен только для Linux и OSX.
Чтобы решить эти проблемы, я перерыл всю сеть статей про Python ssh, но не нашел полного введения в этот аспект.
С этой целью я прочитал очень популярный проект Github: awesome-python-cn (Имя GitHub.com/Bing выиграло…
Ожидайте найти здесь несколько полезных библиотек для удаленных подключений.
Я действительно нашел два
- sh.ssh
- Paramiko
2. Используйте sh.ssh
Давайте познакомимся с первым,sh.ssh
shЭто библиотека, которая позволяет вам выполнять системные команды Linxu/OSX через вызовы функций.Ей очень легко пользоваться, и я напишу о ней введение, когда у меня будет возможность.
$ python3 -m pip install sh
Сегодня введена только одна из его функций:ssh
Обычно две машины посещают друг друга, для удобства можно установить беспарольный логин, чтобы пароль не требовался.
Этот код может обеспечить вход без пароля и выполнять наши командыls -l
from sh import ssh
output=ssh("root@xx.xx.xx.xx", "-p 22", "ls -l")
print(output)
Но возможно, что мы не хотим устанавливать взаимное доверие и беспарольный.Чтобы сделать этот код более общим, я предполагаю, что у нас нет беспарольных настроек и мы можем войти только с паролями.
Вопрос в том, что для ввода пароля необходимо использовать интерактивный метод его ввода, как это реализовать в Python?
Исходный метод ssh получает_outПараметр, этот параметр может быть строкой, представляющей путь к файлу, или файловым объектом (или файлоподобным объектом), или функцией обратного вызова, что означает, что при наличии стандартного вывода он вызовет и передаст выходное содержимое этому функция.
Это легко сделать.
Я просто признаю, что естьpassword:Словами, просто пиши мой пароль на стандартный ввод.
Полный код выглядит следующим образом:
import sys
from sh import ssh
aggregated = ""
def ssh_interact(char, stdin):
global aggregated
sys.stdout.write(char.encode())
sys.stdout.flush()
aggregated += char
if aggregated.endswith("password: "):
stdin.put("you_password\n")
output=ssh("root@xx.xx.xx.xx", "-p 22", "ls -l",_tty_in=True, _out_bufsize=0, _out=ssh_interact)
print(output)
Вот официальная документация (Ахмад Корт.GitHub.IO/is/tutorial…
После попытки запустить его обнаруживается, что программа будет работать всегда, никогда не возвращаться, никогда не выходить, и функция обратного вызова никогда не войдет.
Глядя на исходный код через отладку, все еще не могу найти проблему, поэтому перейдите кGithubЯ искал и обнаружил, что эта проблема уже существовала в 2017 году, а в 2020 году она не была устранена. Похоже, что использованиеsh.sshЛюдей не так много, поэтому я снова «поинтересовался», надеясь получить ответ.
Вышеупомянутая проблема появится только тогда, когда необходимо ввести пароль.Если установлено взаимное доверие между машинами, проблем нет.
чувствоватьsh.sshЭффект использования, я установил взаимное доверие машины и без пароля, а затем использовать следующий код.
from sh import ssh
my_server=ssh.bake("root@xx.xx.xx.xx", "-p 22")
# 相当于执行登陆一次执行一次命令,执行完就退出登陆
print(my_server.ls())
# 可在 sleep 期间,手动登陆服务器,使用 top ,查看当前有多少终端在连接
time.sleep(5)
# 再次执行这条命令时,登陆终端数将 +1,执行完后,又将 -1
print(my_server.ifconfig())
Удивлен, чтобы использоватьbakeСюда,my_server.ls()а такжеmy_server.ifconfig()Кажется, это через одно и то же соединение ssh, дважды выполнив команду, но на самом деле вы можете выполнить команду top на удаленной машине, чтобы увидеть изменения подключенного терминала.+1Снова-1, указывающий, что выполнение двух команд достигается через два соединения.
Таким образом, используяsh.sshБолевая точка 1 (если вышеуказанные проблемы могут быть решены), болевая точка 2 и болевая точка 3 могут быть решены.
Но переиспользовать ssh-соединение все равно не получается, все равно неудобно, да и не лучшее решение в моем идеале.
самый важный момент,shЭтот модуль поддерживает только Linxu/OSX, в Windows вы должны использовать родственную библиотеку —pbs, а затем я еще раз взглянул на pypipbs, находится "в аварийном состоянии" и никто его не обслуживает.
На данный момент я на последней капле.
3. Использование парамико
С последним лучом надежды я попытался использоватьparamikoЭта библиотека, наконецparamikoЗдесь обнаруживается элегантность, которая должна принадлежать Python.
Вы можете установить его с помощью следующей команды
$ python3 -m pip install paramiko
Затем мы представим несколько часто используемых методов входа в систему ssh.
Способ 1: вход в sshclient на основе имени пользователя и пароля
Затем вы можете обратиться к следующему коду для удаленного подключения в системе Linux/OSX.
import paramiko
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 建立连接
ssh.connect("xx.xx.xx.xx", username="root", port=22, password="you_password")
# 使用这个连接执行命令
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("ls -l")
# 获取输出
print(ssh_stdout.read())
# 关闭连接
ssh.close()
Способ 2: Авторизоваться через транспорт по логину и паролю
Метод 1 — это традиционная операция подключения к серверу, выполнения команд и закрытия.Несколько операций необходимо подключать несколько раз, а соединения нельзя использовать повторно [Боль номер четыре].
Иногда вам необходимо войти на сервер для выполнения нескольких операций, таких как выполнение команд и загрузка/выгрузка файлов.Способ 1 не может быть реализован, поэтому вы можете использовать метод транспорта.
import paramiko
# 建立连接
trans = paramiko.Transport(("xx.xx.xx.xx", 22))
trans.connect(username="root", password="you_passwd")
# 将sshclient的对象的transport指定为以上的trans
ssh = paramiko.SSHClient()
ssh._transport = trans
# 剩下的就和上面一样了
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("ls -l")
print(ssh_stdout.read())
# 关闭连接
trans.close()
Способ 3: Вход через SSHClient на основе открытого ключа
import paramiko
# 指定本地的RSA私钥文件
# 如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
pkey = paramiko.RSAKey.from_private_key_file('/home/you_username/.ssh/id_rsa', password='12345')
# 建立连接
ssh = paramiko.SSHClient()
ssh.connect(hostname='xx.xx.xx.xx',
port=22,
username='you_username',
pkey=pkey)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('ls -l')
# 结果放到stdout中,如果有错误将放到stderr中
print(stdout.read())
# 关闭连接
ssh.close()
Способ 4: вход через транспорт на основе ключа
import paramiko
# 指定本地的RSA私钥文件
# 如果建立密钥对时设置的有密码,password为设定的密码,如无不用指定password参数
pkey = paramiko.RSAKey.from_private_key_file('/home/you_username/.ssh/id_rsa', password='12345')
# 建立连接
trans = paramiko.Transport(('xx.xx.xx.xx', 22))
trans.connect(username='you_username', pkey=pkey)
# 将sshclient的对象的transport指定为以上的trans
ssh = paramiko.SSHClient()
ssh._transport = trans
# 执行命令,和传统方法一样
stdin, stdout, stderr = ssh.exec_command('df -hl')
print(stdout.read().decode())
# 关闭连接
trans.close()
Вышеупомянутые четыре метода могут помочь вам удаленно войти на сервер для выполнения команд.Если вам нужно повторно использовать соединения: выполнить несколько команд в одном соединении, вы можете использоватьСпособ второйа такжеСпособ 4
Не забудьте закрыть соединение, когда закончите.
Реализовать передачу файлов по sftp
В то же время paramiko — идеальное решение для ssh, оно очень профессионально, а также может реализовать передачу файлов sftp.
import paramiko
# 实例化一个trans对象# 实例化一个transport对象
trans = paramiko.Transport(('xx.xx.xx.xx', 22))
# 建立连接
trans.connect(username='you_username', password='you_passwd')
# 实例化一个 sftp对象,指定连接的通道
sftp = paramiko.SFTPClient.from_transport(trans)
# 发送文件
sftp.put(localpath='/tmp/11.txt', remotepath='/tmp/22.txt')
# 下载文件
sftp.get(remotepath='/tmp/22.txt', localpath='/tmp/33.txt')
trans.close()
Пока победила Paramiko, но есть еще болевой момент, о котором мы не упомянули, то есть мультиплатформенность, то есть Windows, здесь есть и хорошее, и плохое.
Хорошая вещь: paramiko поддерживает окна
Плохо то, что нужно делать много сложных приготовлений, можно погуглить, но предлагаю просто сдаться, слишком глубока яма.
4. Пишите в конце
После некоторого сравнения и некоторых примеров можно увидеть, что Paramiko — это профессиональный и беззаботный инструмент ssh.Я лично считаю, что модуль Paramiko — это один из модулей, который должен изучить обслуживающий и обслуживающий персонал.Если он вам понадобится в Код Python Внедрите ssh на удаленный сервер, чтобы получить некоторую информацию, тогда я рекомендую вам Paramiko.
Наконец, я надеюсь, что эта статья поможет вам.
5. Справочные ссылки
Эта статья опубликована на многопостовой платформеArtiPubавтоматическая публикация