Какой самый простой способ использовать SSH с помощью Python?


82

Как я могу просто подключиться к удаленному серверу по SSH из локального скрипта Python (3.0), указать логин / пароль, выполнить команду и распечатать вывод в консоли Python?

Я бы предпочел не использовать какую-либо большую внешнюю библиотеку или устанавливать что-либо на удаленном сервере.

Ответы:


42

Я не пробовал, но может помочь этот модуль pysftp , который, в свою очередь, использует paramiko. Я считаю, что все на стороне клиента.

Интересная команда, вероятно, .execute()выполняет произвольную команду на удаленной машине. (Модуль также имеет функции .get()и .putметоды, которые больше ссылаются на его характер FTP).

ОБНОВИТЬ:

Я переписал ответ после того, как сообщение в блоге, на которое я изначально ссылался, больше не доступно. Некоторые комментарии, относящиеся к старой версии этого ответа, теперь будут выглядеть странно.


Хорошая находка! Пока вы не заботитесь о настройке ответов об ошибках, эта дополнительная абстракция будет очень полезна.
Cascabel

Модуль ssh сделал свое дело. Просто и отлично работает. Никакого поиска через API Paramiko.
Кристофер Токар,

2
Ссылка на файл ssh.py внутри предоставленной вами ссылки не работает: /
dgorissen

Ага, можно новую ссылку, пожалуйста. Я нашел ssh.py на github, но он не тот (и не такой хороший)
joedborg

1
Пакет pysftp предоставляет только SFTP. Вдали от клиента SSH.
bortzmeyer

61

Вы можете написать код самостоятельно, используя Paramiko, как было предложено выше. В качестве альтернативы вы можете заглянуть в Fabric, приложение на Python для выполнения всего, о чем вы спрашивали:

Fabric - это библиотека Python и инструмент командной строки, предназначенный для упрощения развертывания приложений или выполнения задач системного администрирования через протокол SSH. Он предоставляет инструменты для выполнения произвольных команд оболочки (либо как обычный пользователь, либо через sudo), загрузки и скачивания файлов и т. Д.

Думаю, это соответствует вашим потребностям. Это также небольшая библиотека и не требует установки сервера, хотя у нее есть зависимости от paramiko и pycrypt, которые требуют установки на клиенте.

Раньше здесь было приложение . Теперь его можно найти здесь .

* The official, canonical repository is git.fabfile.org
* The official Github mirror is GitHub/bitprophet/fabric

Об этом есть несколько хороших статей, но будьте осторожны, потому что за последние шесть месяцев он изменился:

Развертывание Django с помощью Fabric

Инструменты современного Python-хакера: Virtualenv, Fabric и Pip

Простое и легкое развертывание с помощью Fabric и Virtualenv


Позже: Fabric больше не требует установки paramiko:

$ pip install fabric
Downloading/unpacking fabric
  Downloading Fabric-1.4.2.tar.gz (182Kb): 182Kb downloaded
  Running setup.py egg_info for package fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no files found matching 'fabfile.py'
Downloading/unpacking ssh>=1.7.14 (from fabric)
  Downloading ssh-1.7.14.tar.gz (794Kb): 794Kb downloaded
  Running setup.py egg_info for package ssh
Downloading/unpacking pycrypto>=2.1,!=2.4 (from ssh>=1.7.14->fabric)
  Downloading pycrypto-2.6.tar.gz (443Kb): 443Kb downloaded
  Running setup.py egg_info for package pycrypto
Installing collected packages: fabric, ssh, pycrypto
  Running setup.py install for fabric
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no files found matching 'fabfile.py'
    Installing fab script to /home/hbrown/.virtualenvs/fabric-test/bin
  Running setup.py install for ssh
  Running setup.py install for pycrypto
...
Successfully installed fabric ssh pycrypto
Cleaning up...

Однако это в основном косметический характер: ssh - это форк paramiko, сопровождающий для обеих библиотек один и тот же (Джефф Форсьер, также автор Fabric), а сопровождающий планирует воссоединить paramiko и ssh под именем paramiko . (Это исправление через pbanka .)


Поскольку это кажется интересной ссылкой, я бы хотел обновить ее, поскольку ваша теперь не работает. пожалуйста, используйте: clemesha.org/blog/…
dlewin

Разве спрашивающий не указал, что он не хочет использовать «большую внешнюю библиотеку»? Paramiko и Fabric - перебор, когда все, что автор действительно просил, - это простой одноразовый рецепт ssh.
Зоран Павлович

1
@Zoran Pavlovic: все ответы были либо на установку локального пакета (paramiko, fabric, ssh, libssh2), либо на использование подпроцесса для запуска ssh. Последнее решение не требует установки, но я не думаю, что создание ssh - отличная идея, как и OP, поскольку он выбрал ответ для установки модуля ssh. В этих документах говорится: «ssh.py предоставляет три общие SSH-операции: получение, размещение и выполнение. Это абстракция высокого уровня для Paramiko». Поэтому, если вы не отдаете предпочтение libssh2, который требует много кода, соответствующей рекомендации нет. Я предпочитаю дать хорошее решение, когда условия OP не могут быть разумно выполнены.
hughdbrown

24

Если вы хотите избежать каких-либо дополнительных модулей, вы можете использовать модуль подпроцесса для запуска

ssh [host] [command]

и захватить вывод.

Попробуйте что-нибудь вроде:

process = subprocess.Popen("ssh example.com ls", shell=True,
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output,stderr = process.communicate()
status = process.poll()
print output

Чтобы иметь дело с именами пользователей и паролями, вы можете использовать подпроцесс для взаимодействия с процессом ssh или вы можете установить открытый ключ на сервере, чтобы избежать запроса пароля.


7
Но что, если клиент работает под Windows?
Натан

Может быть сложно указать пароль для sshподпроцесса через канал. Видеть Почему бы просто не использовать канал (popen ())? . Вам может понадобиться pty, pexpectмодули , чтобы обойти его.
jfs

похоже, не работает для строки ssh somecomputer; python -c "import numpy; print numpy .__ version__" 'он говорит, что не знает команду «import»
usethedeathstar

1
@usethedeathstar: заключите всю удаленную команду в кавычки: ssh somecomputer 'python -c "import this; print this"'
Нил

17

Я написал привязки Python для libssh2 . Libssh2 - это клиентская библиотека, реализующая протокол SSH2.

import socket
import libssh2

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('exmaple.com', 22))

session = libssh2.Session()
session.startup(sock)
session.userauth_password('john', '******')

channel = session.channel()
channel.execute('ls -l')

print channel.read(1024)

2
Вроде очень низкий уровень. Например (ваш собственный пример), вы должны явно сказать, что вы используете IPv4 или IPv6 (то, что вам не нужно делать с клиентом командной строки OpenSSH). Также не нашел, как заставить работать с ssh-агентом.
bortzmeyer

2
Преимущество pylibssh2 в том, что он передает файлы НАМНОГО быстрее, чем любая нативная реализация ssh на python, например paramiko.
Дэмиен

8

Здесь важно ваше определение «простейшего» - простой код означает использование модуля (хотя «большая внешняя библиотека» - это преувеличение).

Я считаю, что самый современный (активно разрабатываемый) модуль - это paramiko . Он поставляется с загружаемыми демонстрационными скриптами и имеет подробную онлайн-документацию по API. Вы также можете попробовать PxSSH , который содержится в pexpect . По первой ссылке есть небольшой образец вместе с документацией.

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


6

Как и hughdbrown, мне нравится Fabric. Обратите внимание: хотя он реализует собственный декларативный сценарий (для развертывания и т.п.), его также можно импортировать как модуль Python и использовать в ваших программах без необходимости писать сценарий Fabric.

У Fabric новый сопровождающий, и в настоящее время идет процесс переписывания; это означает, что большинство руководств, которые вы (в настоящее время) найдете в Интернете, не будут работать с текущей версией. Кроме того, Google по-прежнему показывает старую страницу Fabric в качестве первого результата.

Актуальную документацию вы можете проверить: http://docs.fabfile.org


Fabric использует вилку paramiko pypi.python.org/pypi/ssh для всего ssh.
Дэмиен

6

Я обнаружил, что paramiko слишком низкоуровневый, а Fabric не особенно хорошо подходит для использования в качестве библиотеки, поэтому я собрал свою собственную библиотеку под названием spur, которая использует paramiko для реализации немного более приятного интерфейса:

import spur

shell = spur.SshShell(hostname="localhost", username="bob", password="password1")
result = shell.run(["echo", "-n", "hello"])
print result.output # prints hello

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

result = shell.run(["echo", "-n", "hello"], stdout=sys.stdout)

Не поддерживает выполнение нестандартных команд, например, на некоторых маршрутизаторах (MikroTik) команды имеют префикс '/', эта библиотека выдает ошибку. Однако для стандартных хостов Linux это кажется довольно хорошим.
Бабкен Варданян

Когда я передаю IP-адрес в hostname, он выдает ошибку, говоря, что IP не найден в known_hosts ...
rexbelia

@rexbelia Это нормальное поведение SSH: чтобы убедиться, что вы разговариваете с правильным сервером, SSH будет принимать ключ от хоста, только если он уже известен. Решение состоит в том, чтобы либо добавить соответствующий ключ в known_hosts, либо установить для аргумента missing_host_key соответствующее значение, как описано в документации.
Майкл Уильямсон

4

Для тех, кто добирается сюда для поиска в Google образца ssh для Python. Первоначальный вопрос и ответ уже почти расшифрованы. Кажется, что paramiko получил немного функциональности (хорошо. Я признаю - здесь чистое предположение - я новичок в Python), и вы можете создать клиент ssh напрямую с помощью paramiko.

import base64
import paramiko

client = paramiko.SSHClient()

client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.1.1', username='user', password='password')
stdin, stdout, stderr = client.exec_command('cat /proc/meminfo')
for line in stdout:
    print('... ' + line.strip('\n'))
client.close()

Этот код был адаптирован из демонстрации https://github.com/paramiko/paramiko. У меня это работает.


1

Это сработало для меня

import subprocess
import sys
HOST="IP"
COMMAND="ifconfig"

def passwordless_ssh(HOST):
        ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],
                       shell=False,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE)
        result = ssh.stdout.readlines()
        if result == []:
                error = ssh.stderr.readlines()
                print >>sys.stderr, "ERROR: %s" % error
                return "error"
        else:
                return result

1

please refer to paramiko.org, its very useful while doing ssh using python.

import paramiko

import time

ssh = paramiko.SSHClient() #SSHClient() is the paramiko object</n>

#Below lines adds the server key automatically to know_hosts file.use anyone one of the below

ssh.load_system_host_keys() 

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

try:

#Here we are actually connecting to the server.

ssh.connect('10.106.104.24', port=22, username='admin', password='')

time.sleep(5)

#I have mentioned time because some servers or endpoint prints there own information after 
#loggin in e.g. the version, model and uptime information, so its better to give some time 
#before executing the command.

#Here we execute the command, stdin for input, stdout for output, stderr for error

stdin, stdout, stderr = ssh.exec_command('xstatus Time')

#Here we are reading the lines from output.

output = stdout.readlines() 

print(output)


#Below all are the Exception handled by paramiko while ssh. Refer to paramiko.org for more information about exception.


except (BadHostKeyException, AuthenticationException,  
    SSHException, socket.error) as e:           

print(e)

0

Взгляните на spurplus , обертку вокруг spur и paramiko которую мы разработали для управления удаленными машинами и выполнения файловых операций.

Spurplus предоставляет готовую check_output()функцию:

import spurplus
with spurplus.connect_with_retries(
        hostname='some-machine.example.com', username='devop') as shell:
     out = shell.check_output(['/path/to/the/command', '--some_argument']) 
     print(out)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.