Рекомендации по удаленному входу на сервер с помощью Python

Python

Публичный номер: «Время программирования на 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автоматическая публикация