Сегодня я хотел бы поведать вам о том, как можно работать с 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()
Мои действия:
Результатом выполнения будет перезагрузка сервера . Так что для большей наглядности можете повыполнять другие команды через sudo .
Это основные моменты работы с ssh в Python, для более подробной информации вы всегда можете обратиться к документации, ссылку на которую я дал в начале статьи. Удачи! ;)