Работа с SSH в Python


Источник: Работа с SSH. Часть 1 — делаем это в Python - Olezhek.net

Сегодня я хотел бы поведать вам о том, как можно работать с SSH в Python. SSH — Secure SHell — сетевой протокол, который позволяет производить удаленное управление операционной системой компьютера по зашифрованному соединению. При помощи SSH можно осуществлять передачу файлов. SSH применяется для соединения с удаленной операционной системой по SFTP.

В Python для работы с ssh используется модуль paramiko. Документацию по модулю вы можете почитать тут, ну а я покажу вам пару основных моментов, от которых вы оттолкнетесь и дальше уже будете применять то, что вам необходимо.

Paramiko присутствует в стандартных репозиториях Ubuntu и Debian, и установить его можно очень даже легко:

# apt-get install python-paramiko

Теперь, когда модуль установлен, приступим к программированию)). Для работы с SSH в модуле предусмотрен класс — SSHClient. С него все и начинается:

#!/usr/bin/env python
import paramiko
ssh=paramiko.SSHClient()

Я создал объект ssh класса SSHClient, и теперь могу устанавливать соединение. Модуль позволяет авторизоваться как при помощи пары «имя пользователя — пароль», так и при помощи ключа. Во втором случае, конечно же, нужно иметь «при себе» этот самый ключ.

Разумеется, на разных серверах SSH настроен по разному. Важно знать, что существует 3 варианта авторизации — по имени пользователя и паролю, ключом и гибридный. По умолчанию, скажем, на Debian-based дистрибутивах включен последний вариант. Осмелюсь предположить, что это наиболее популярный вариант настроек. Что он из себя представляет? Когда вы подключаетесь к серверу по SSH, он, перед запросом логина и пароля, предлагает вам принять ключ, чтобы, позже, вы, выгрузив в директорию с ключами на сервере свой ключ, могли авторизоваться именно по ключу. Что получает пользователь? Он получает удобный диалог, на утвердительный ответ которого SSH-клиент скопирует к себе ключики сервера сам. Что получает программист? Весьма неудобную ситуацию — дело в том, что по умолчанию SSHClient настроен так, чтобы не соединяться с сервером, если у клиента нет ключа. Даже если логин и пароль правильны. Это приводит к тому, что SSHClient сбрасывает соединение, и авторизоваться не получается. К счастью, на такие случаи в Paramiko предусмотрено удобное решение:

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

Ежели вам охота вернуть все обратно, можете просто не прописывать этот метод. Явно политика по умолчанию устанавливается так:

ssh.set_missing_host_key_policy(paramiko.RejectPolicy())

Объект создан и настроен, теперь можно и подключиться:

ssh.connect("<сервер>",username="<имя пользователя>",password="<пароль>")

Необходимо указать свои сервер, имя пользователя и пароль. В качестве сервера можно указать IP-адрес или доменное имя, по которому резолвится ваш сервер.

После успешного соединения есть два варианта работы с сервером — продолжать работать по SSH и выполнять консольные команды сервера или переключиться в режим SFTP и использовать приемы SFTP для работы с файлами. Какой метод предпочтительнее — дело ваше. Посмотрим оба варианта.

Вариант номер один — SFTP. Для переключения в этот режим используем такую конструкцию:

ftp=ssh.open_sftp()

И далее работа с сервером осуществляется по SFTP. В качестве примера приведу пару команд по навигации по директориям сервера и управлению файлами:

fileList=ftp.listdir()
ftp.chdir("/var/log")
currentDir = ftp.getcwd()
ftp.get("sql.log","mysql.log")
ftp.put("sql.log","mysql.log")
ftp.unlink("mysql.log")
ftp.mkdir("test")
ftp.rmdir("test")

В первой строке я получил список файлов. Метод listdir() возвращает кортеж, с которым я могу работать как обычно.

Во второй строке я осуществил переход в директорию /var/log. Таким образом можно перемещаться по директориям на сервере.

В третьей строке мне захотелось узнать, где я нахожусь. В результате выполнения метода getcwd я получил строку, содержащую путь к моей текущей директории.

Для скачивания файла использется метод get() — строка четвертая. В качестве первого параметра задается имя локального файла (куда скачивать), в качестве второго — что скачивать. Можно указывать абсолютные пути.

Для выгрузки файла на сервер используется метод put() — параметры аналогично get(). Стоит отметить, что ни get(), ни put() не принимают в качестве входных параметров маски (например, «*.php»).

Удалить файл можно при помощи метода unlink(). Параметр задается также, как и у get() и put().

Для создания директории можно использовать метод mkdir(), а для удаления — rmdir().

Вообще, если вы имели ранее дело с sftp/ftp, то, думаю, вы заметили похожесть в названиях методов и команд протоколов FTP/SFTP. Так что трудно не будет, а нюансы всегда можно найти в документации к paramiko.

Вариант номер два — работа с сервером по SSH. Работа с сервером не через SFTP, а через SSH отличается прежде всего тем, что можно выполнять консольные команды. Для выполнения команд по SSH служит метод exec_command(). Ниже пример (я продублировал соединение с сервером для наглядности):

#!/usr/bin/env python
import paramiko
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("<сервер>",username="<имя пользователя>",password="<пароль>")
stdin, stdout, stderr = ssh.exec_command("cat /var/log/syslog")

Данный метод примечателен тем, что при выполнении команды необходимо обрабатывать три возвращаемых канала — это содержимое стандартного ввода, стандартного вывода и стандартного вывода ошибок. Например, результат выполнения вышеописанной команды, если он будет успешен, будет содержаться в stdout. Ко всем трём возвращаемым каналам можно обратиться как к файлу и, например, считать оттуда всё, что необходимо. Для получения результата выполнения всё той же команды выше (результатом будет содержимое файла), я могу просто считать его построчно из stdout:

result = stdout.read().splitlines()

Таким образом я получил кортеж строк системного лога удаленного сервера.

Усложним немного. Допустим, мне понадобилось перезагрузить сервер. Команда перезагрузки доступна только для root (/sbin/reboot). Для выполнения команд, доступных только root, от обычного пользователя, можно воспользоваться утилитой sudo. Я исхожу из того, что на сервере установлена и настроена sudo, и моя учетная запись может выполнять эту утилиту (является т.н. sudoer'ом):

stdin, stdout, stderr = ssh.exec_command("sudo reboot")
stdin.write("<пароль пользователя>\n")
stdin.flush()

Мои действия:

  1. выполняю команду «sudo reboot»
  2. в результате выполнения мне нужно ввести пароль пользователя (настройки по умолчанию для sudo — пароль вашего пользователя). Для этого я пишу в stdin, как в обычный файл, свой пароль вместе с переносом строки, и отправляю содержимое stdin серверу.

Результатом выполнения будет перезагрузка сервера . Так что для большей наглядности можете повыполнять другие команды через sudo .

Это основные моменты работы с ssh в Python, для более подробной информации вы всегда можете обратиться к документации, ссылку на которую я дал в начале статьи. Удачи! ;)


Источник: Работа с SSH. Часть 1 — делаем это в Python - Olezhek.net