Який найпростіший спосіб SSH за допомогою Python?


82

Як я можу просто передавати SSH на віддалений сервер з локального скрипта Python (3.0), вводити логін / пароль, виконувати команду та друкувати вихідні дані на консолі Python?

Я б не хотів використовувати велику зовнішню бібліотеку чи встановлювати щось на віддаленому сервері.

Відповіді:


42

Я не пробував, але цей модуль pysftp може допомогти, який, у свою чергу, використовує paramiko. Я вважаю, що все на стороні клієнта.

Цікава команда, ймовірно, .execute()яка виконує довільну команду на віддаленій машині. (Модуль також має функції .get()та .putметоди, які більше натякають на його характер FTP).

ОНОВЛЕННЯ:

Я переписав відповідь після того, як публікація в блозі, на яку я спочатку посилався, вже недоступна. Деякі коментарі, що стосуються старої версії цієї відповіді, тепер виглядатимуть дивно.


Гарна знахідка! Поки ви не дбаєте про налаштування відповідей на помилки, ця додаткова абстракція буде дуже корисною.
Cascabel

Модуль ssh зробив свою справу. Простий і чудово працює. Відсутність пошуку через Paramiko API.
Крістофер Токар,

2
Посилання на файл ssh.py усередині посилання не працює: /
dgorissen

Так, ми можемо отримати нове посилання, будь ласка. Я знайшов ssh.py на github, але це не те саме (і не настільки добре)
joedborg

1
Пакет pysftp надає лише SFTP. Далеко не клієнт SSH.
bortzmeyer

61

Ви можете кодувати його самостійно, використовуючи Paramiko, як було запропоновано вище. Крім того, ви можете заглянути у Fabric, програму на пітоні, яка робить все, про що ви запитували:

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

Просте та легке розгортання за допомогою тканини та Virtualenv


Пізніше: Тканина більше не вимагає установки 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

Хіба запитувач не зазначив, що не хоче користуватися "великою зовнішньою бібліотекою"? Параміко та Тканина є надмірними, коли все, про що справді просив автор, - це простий одноразовий рецепт ssh.
Зоран Павлович

1
@Zoran Pavlovic: усі відповіді полягали в тому, щоб встановити локальний пакет (paramiko, fabric, ssh, libssh2) або використовувати підпроцес для запуску ssh. Останнє рішення не встановлюється, але я не думаю, що нерест ssh не є чудовою ідеєю, і це не зробив OP, оскільки він обрав відповідь для встановлення модуля ssh. У цих документах сказано: "ssh.py надає три типові операції SSH, отримання, розміщення та виконання. Це абстракція високого рівня на Paramiko." Отже, якщо ви не віддасте перевагу libssh2, який важко кодує, відповідні рекомендації відсутні. Я виступаю за хороше рішення, коли умови ОП не можуть бути розумно виконані.
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 "імпортуйте це; роздрукуйте"'
Ніл

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 полягає в тому, що він передає файли ШЛЯХ швидше, ніж будь-яка вбудована реалізація python ssh, як paramiko.
Damien

8

Тут важливо ваше визначення "найпростішого" - простий код означає використання модуля (хоча "велика зовнішня бібліотека" - це перебільшення).

Я вважаю, що найсучаснішим (активно розробляється) модулем є paramiko . Він поставляється з демонстраційними сценаріями для завантаження та містить детальну документацію щодо API в Інтернеті. Ви також можете спробувати PxSSH , який міститься в pexpect . Короткий зразок разом із документацією є за першим посиланням.

Знову ж таки, щодо простоти, зауважте, що хороше виявлення помилок завжди робить ваш код більш складним, але ви повинні мати можливість повторно використовувати багато коду зі зразкових сценаріїв, а потім забути про це.


6

Як hughdbrown, мені подобається Fabric. Зверніть увагу, що, хоча він реалізує власні декларативні сценарії (для розгортання тощо), їх також можна імпортувати як модуль Python і використовувати у ваших програмах без необхідності писати сценарій Fabric.

Тканина має нового супровідника і переробляється; це означає, що більшість підручників, які ви (зараз) знайдете в Інтернеті, не працюватимуть із поточною версією. Крім того, Google як і раніше показує стару сторінку Fabric як перший результат.

Для отримання актуальної документації ви можете перевірити: http://docs.fabfile.org


Тканина використовує виделку paramiko pypi.python.org/pypi/ssh для всіх ssh-матеріалів.
Демієн

6

Я знайшов paramiko бути трохи занадто низького рівня, і тканина не особливо добре підходить для використання в якості бібліотеки, тому я зібрав свою власну бібліотеку під назвою шпори , яка використовує 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-адресу на ім'я хосту, вона видає помилку, в якій йдеться про те, що IP не знайдено в known_hosts ...
rexbelia

@rexbelia Це звичайна поведінка SSH: щоб переконатися, що ви розмовляєте з правильним сервером, SSH прийме ключ від хосту, якщо він уже відомий. Рішенням є або додати відповідний ключ до відомих_хостів, або встановити аргумент missing_host_key на відповідне значення, як описано в документації.
Michael Williamson

4

На користь тих, хто звертається сюди, шукаючи зразок 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 , обгортка навколо шпори і 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.