Работа по ssh python

Работа по ssh python

Сегодня я хотел бы поведать вам о том, как можно работать с 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 для работы с файлами. Какой метод предпочтительнее — дело ваше. Посмотрим оба варианта.

Читайте также:  Add version to css file

Вариант номер один — 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() 

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

Читайте также:  Php get image from file

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

stdin, stdout, stderr = ssh.exec_command("sudo -S reboot")br /> stdin.write(" \n")br /> stdin.flush() 
  1. выполняю команду “sudo reboot”
  2. в результате выполнения мне нужно ввести пароль пользователя (настройки по умолчанию для sudo — пароль вашего пользователя). Для этого я пишу в stdin, как в обычный файл, свой пароль вместе с переносом строки, и отправляю содержимое stdin серверу.

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

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

Комментарии

I think result = stdout.read.splitlines() should be result = stdout.read().splitlines()

Thanks, I’ve updated the article

Источник

Работа с ssh в Python

Хочу рассказать про paramiko — модуль для работы с ssh в python.
С его помощью можно написать скрипт, который получит доступ к удаленному серверу (или многим) и что-то на нем сделает.

Кому интересно — прошу под кат.

Достаточно часто на работе требовалось выполнить очень однотипные действия на серверах клиентов. Действия пустяковые, наподобие «исправить строчку №12 в конфигурационном файле» или «заменить файл „version_017“ на „version_018“. Это было легко, пока серверов не накопилось *надцать штук. Также подобные задачи надоедали очень быстро, поэтому подобную работу старались поручить новичкам с формулировкой „для приобретения навыков работы с ssh“.

Поначалу самые простые задачи можно было решить стандартными средствами ssh — копированием файла и удаленным исполнением кода. Также пробовали использовать утилиту empty .

Я в то время как раз начинал учить python, решил посмотреть, что в нем есть для этих целей. Гугл услужливо подсказал про paramiko.

Paramiko (комбинация слов языка есперанто „параноик“ и „друг“ — »paranoja» + «amiko») — это модуль для python версии 2.3 и выше, который реализует ssh2 протокол для защищенного (с шифрованием и аутентификацией) соединения с удаленным компьютером. При подключении предоставляется высокоуровневое API для работы с ssh — создается обьект SSHClient. Для большего контроля можно передать сокет (или подобный обьект) классу Transport и работать с удаленным хостом в качестве сервера или клиента. Клиенту для аутентификации можно использовать пароль или приватный ключ и проверку ключа сервера.

Небольшой пример использования этого модуля. Комментарии будут ниже.

import paramiko host = '192.168.0.8' user = 'login' secret = 'password' port = 22 client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(hostname=host, username=user, password=secret, port=port) stdin, stdout, stderr = client.exec_command('ls -l') data = stdout.read() + stderr.read() client.close() 

Получить данные для доступа к удаленному серверу можно любым удобным способом — прописать напрямую в коде, вынести в конфиг, базу данных и т.д. Очевидно, что если хостов несколько, то для их обхода нужно делать цикл.

Основным классом для подключения и удаленной работы является SSHClient. Он предоставляет нам «сессию» с которой мы можем работать далее.

В строчке client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) мы добавляем ключ сервера в список известных хостов — файл .ssh/known_hosts. Если при соединении с сервером ключа в нем не найдено, то по умолчанию ключ «отбивается» и вызввается SSHException.

Для соединения с сервером используем client.connect(). Авторизироваться можно как по комбинации логин-пароль так и по ключам. При соединении можно задать хост, имя пользователя, пароль, порт, ключ, и прочие параметры.

Строка client.exec_command(‘ls -l’) — выполняет команду на удаленном сервере. Потоки ввода-вывода программы возврашщаются в файлообразные обьекты — stdin, stdout, stderr.

Возможно, я недоразобрался, но у меня не получилось получить права рута на уделенном сервере. Буду благодарен, если мне подскажут, как это сделать. Для выполнения действий с правами суперпользователя делал так:

stdin, stdout, stderr = ssh.exec_command('sudo -S rm *') stdin.write('password' + '\n') stdin.flush() 

UPD: meph1st0 в комментариях предложил для этих целей воспользоваться классом Channel

import paramiko client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(. ) channel = сlient.get_transport().open_session() channel.get_pty() channel.settimeout(5) channel.exec_command('sudo ls') channel.send(password+'\n') print channel.recv(1024) channel.close() client.close() 

Для передачи файлов по sftp можно использовать класс Transport. Для непосредственной передачи файлов используются команды put и get.

host = "example.com" port = 22 transport = paramiko.Transport((host, port)) transport.connect(username='login', password='password') sftp = paramiko.SFTPClient.from_transport(transport) remotepath = '/path/to/remote/file.py' localpath = '/path/to/local/file.py' sftp.get(remotepath, localpath) sftp.put(localpath, remotepath) sftp.close() transport.close() 

Вкратце всё. Сайт проекта и документация — http://www.lag.net/paramiko/

UPD. В комметариях подсказали, что есть ряд других библиотек инструментов, которые также можно использовать для работы по ssh решения подобных задач. Из перечисленного: fabric, chef, puppet, libbsh2 (pylibbsh2), exscript и net-ssh-telnet на руби. Всем комментаторам спасибо.

Источник

Оцените статью