Python kullanarak SSH yapmanın en basit yolu nedir?


82

Yerel bir Python (3.0) betiğinden uzak bir sunucuya SSH'yi nasıl basitçe SSH yapabilirim, bir oturum açma / parola sağlayabilir, bir komut çalıştırabilir ve çıktıyı Python konsoluna yazdırabilirim?

Herhangi bir büyük harici kitaplık kullanmayı veya uzak sunucuya herhangi bir şey yüklememeyi tercih ederim.

Yanıtlar:


42

Denemedim , ancak bu pysftp modülü yardımcı olabilir ve bu da paramiko'yu kullanır. Her şeyin müşteri tarafında olduğuna inanıyorum.

İlginç olan komut muhtemelen .execute()uzak makinede rastgele bir komutu çalıştıran komuttur. (Modül ayrıca FTP karakterine daha fazla atıfta bulunan özellikler .get()ve .putyöntemler).

GÜNCELLEME:

Aslen link verdiğim blog yazısı artık mevcut olmadığından sonra cevabı yeniden yazdım. Bu cevabın eski versiyonuna atıfta bulunan bazı yorumlar şimdi tuhaf görünecek.


İyi bul! Hata yanıtlarını özelleştirmeyi önemsemediğiniz sürece, bu ek soyutlama çok yararlı olacaktır.
Cascabel

Ssh modülü hile yaptı. Basit ve iyi çalışıyor. Paramiko API ile arama yok.
Christopher Tokar

2
Verdiğiniz bağlantının içindeki ssh.py dosyasının bağlantısı bozuk: /
dgorissen

Evet, yeni bir bağlantı alabilir miyiz lütfen? Ssh.py'yi github'da buldum, ancak aynı değil (ve o kadar da iyi değil)
joedborg

1
Pysftp paketi yalnızca SFTP sağlar. SSH istemcisinden uzak.
bortzmeyer

61

Yukarıda önerildiği gibi Paramiko kullanarak kendiniz kodlayabilirsiniz. Alternatif olarak, sorduğunuz her şeyi yapmak için bir python uygulaması olan Fabric'e bakabilirsiniz:

Fabric, uygulamaları dağıtmayı veya SSH protokolü aracılığıyla sistem yönetimi görevlerini gerçekleştirmeyi kolaylaştırmak için tasarlanmış bir Python kitaplığı ve komut satırı aracıdır. Rasgele kabuk komutlarını (normal bir oturum açma kullanıcısı olarak veya sudo aracılığıyla) çalıştırmak, dosya yüklemek ve indirmek vb. İçin araçlar sağlar.

Bunun ihtiyaçlarınıza uygun olduğunu düşünüyorum. Aynı zamanda büyük bir kütüphane değildir ve istemcide kurulum gerektiren paramiko ve pycrypt'e bağımlılıkları olmasına rağmen sunucu kurulumu gerektirmez.

Uygulama eskiden buradaydı . Artık burada bulunabilir .

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

Bununla ilgili birkaç iyi makale var, ancak son altı ayda değiştiği için dikkatli olmalısın:

Django'yu Fabric ile Dağıtma

Modern Python Hacker'ın Araçları: Virtualenv, Fabric ve Pip

Yapı ve Virtualenv ile Basit ve Kolay Dağıtım


Daha sonra: Fabric artık kurulum için paramiko gerektirmiyor:

$ 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...

Bununla birlikte, bu çoğunlukla kozmetiktir: ssh, paramiko'nun bir çatalıdır, her iki kitaplığın bakımcısı aynıdır (Jeff Forcier, aynı zamanda Fabric'in yazarıdır) ve bakımcının paramiko ve ssh'yi paramiko adı altında yeniden birleştirme planları vardır . (Bu düzeltme pbanka aracılığıyla .)


Bu ilginç bir bağlantı gibi göründüğü için, sizinki artık bozuk olduğu için onu güncellemek istiyorum. lütfen kullanın: clemesha.org/blog/…
dlewin

Soruyu soran kişi "büyük bir harici kitaplık" kullanmak istemediğini belirtmedi mi? Paramiko ve Fabric, yazarın gerçekten istediği tek seferlik basit bir ssh tarifi olduğunda, her ikisi de aşırıdır.
Zoran Pavlovic

1
@Zoran Pavlovic: tüm cevaplar ya yerel bir paket kurmak (paramiko, fabric, ssh, libssh2) ya da ssh çalıştırmak için alt süreç kullanmaktı. İkincisi, kurulum gerektirmeyen bir çözüm, ancak ssh'yi üretmenin harika bir fikir olduğunu düşünmüyorum ve ssh modülünü kurmak için cevabı seçtiği için OP de yapmadı. Bu dokümanlar şöyle der: "ssh.py üç ortak SSH işlemi sağlar, alma, koyma ve çalıştırma. Paramiko üzerine üst düzey bir soyutlamadır." Bu nedenle, kodlama üzerinde ağır olan libssh2'yi tercih etmediğiniz sürece, uygun bir öneri yoktur. OP'nin koşulları makul bir şekilde karşılanamadığında iyi bir çözüm sunmayı tercih ediyorum.
hughdbrown

24

Herhangi bir ekstra modülden kaçınmak istiyorsanız, çalıştırmak için alt işlem modülünü kullanabilirsiniz.

ssh [host] [command]

ve çıktıyı yakalayın.

Şöyle bir şey dene:

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

Kullanıcı adları ve parolalarla ilgilenmek için, ssh süreciyle etkileşim kurmak için alt işlemi kullanabilir veya parola isteminden kaçınmak için sunucuya bir genel anahtar yükleyebilirsiniz.


7
Peki ya istemci Windows üzerindeyse?
Nathan

sshBir boru aracılığıyla alt işleme bir parola sağlamak zor olabilir . Bkz. Neden sadece bir boru (popen ()) kullanmıyoruz? . Sen gerekebilir pty, pexpectmodüller buna bir çözüm bulmak için.
jfs

'ssh bazı bilgisayarlarda çalışmıyor gibi görünüyor; python -c "import numpy; print numpy .__ version__" '"import" komutunu bilmediğini söylüyor
usethedeathstar

1
@usethedeathstar: tüm uzak komutu tırnak içine alın: ssh bir bilgisayar 'python -c "bunu içe aktar; bunu yazdır"'
Neil

17

Libssh2 için Python bağlamaları yazdım . Libssh2, SSH2 protokolünü uygulayan bir istemci tarafı kitaplığıdır.

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
Çok düşük seviyeli görünüyor. Örneğin (kendi örneğiniz), açıkça IPv4 veya IPv6 kullandığınızı söylemelisiniz (OpenSSH komut satırı istemcisi ile yapmanıza gerek olmayan bir şey). Ayrıca, ssh-agent ile nasıl çalıştırılacağını bulamadım.
bortzmeyer

2
Pylibssh2 ile ilgili iyi olan şey, dosyaları paramiko gibi herhangi bir yerel python uygulamasından ÇOK daha hızlı aktarmasıdır.
Damien

8

Burada "en basit" tanımınız önemlidir - basit kod, modül kullanmak anlamına gelir ("büyük harici kütüphane" bir abartı olsa da).

En güncel (aktif olarak geliştirilmiş) modülün paramiko olduğuna inanıyorum . İndirmede demo komut dosyalarıyla birlikte gelir ve ayrıntılı çevrimiçi API belgelerine sahiptir. Şunu da deneyebilirsiniz PxSSH bulunan, pexpect . İlk bağlantıda belgelerle birlikte kısa bir örnek var.

Yine basitlikle ilgili olarak, iyi bir hata tespitinin her zaman kodunuzu daha karmaşık göstereceğini unutmayın, ancak örnek komut dosyalarındaki birçok kodu yeniden kullanabilmeniz ve sonra unutabilmeniz gerekir.


6

Sert kahverengi gibi, Kumaş'ı seviyorum. Lütfen kendi bildirime dayalı komut dosyasını uygularken (dağıtımlar ve benzerlerini yapmak için) bir Python modülü olarak içe aktarılabileceğini ve bir Fabric komut dosyası yazmak zorunda kalmadan programlarınızda kullanılabileceğini unutmayın.

Fabric'in yeni bir bakıcısı var ve yeniden yazılma sürecinde; Bu, web'de (şu anda) bulacağınız çoğu öğreticinin mevcut sürümle çalışmayacağı anlamına gelir. Ayrıca Google hala ilk sonuç olarak eski Fabric sayfasını gösteriyor.

Güncel belgeler için kontrol edebilirsiniz: http://docs.fabfile.org


Fabric, tüm ssh öğeleri için bir paramiko pypi.python.org/pypi/ssh çatalı kullanır .
Damien

6

Paramiko'nun biraz fazla düşük seviyeli olduğunu ve Fabric'in bir kütüphane olarak kullanılmaya özellikle uygun olmadığını buldum, bu yüzden biraz daha hoş bir arayüz uygulamak için paramiko kullanan spur adlı kendi kütüphanemi bir araya getirdim:

import spur

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

Programın çıktısını çalışırken yazdırmayı da seçebilirsiniz; bu, uzun süre çalışan komutların çıktısını çıkmadan önce görmek istiyorsanız yararlıdır:

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

Standart olmayan komutların çalıştırılmasını desteklemez, örneğin bazı yönlendiricilerde (MikroTik) komutlarının önünde "/" bulunur, bu kitaplık bir hata verir. Ancak standart linux hostları için oldukça iyi görünüyor.
Babken Vardanyan

Ben known_hosts bulunamadı IP belirten bir hata atar ana makine adına bir IP adresi ... geçtikten sonra
rexbelia

@rexbelia Bu, SSH'nin normal davranışıdır: Doğru sunucuyla konuştuğunuzdan emin olmak için, SSH yalnızca zaten biliniyorsa bir ana bilgisayardaki anahtarı kabul eder. Çözüm, ilgili anahtarı bilinen_ ana makinelere eklemek veya eksik_host_key bağımsız değişkenini belgelerde açıklandığı gibi uygun bir değere ayarlamaktır.
Michael Williamson

4

Python ssh örneğini araştırarak buraya ulaşanların yararına. Orijinal soru ve cevap artık neredeyse kodu çözülmüş durumda. Görünüşe göre paramiko biraz işlevsellik kazanıyor (Tamam, kabul ediyorum - burada saf tahmin - Python'da yeniyim) ve doğrudan paramiko ile ssh istemcisi oluşturabilirsiniz.

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()

Bu kod https://github.com/paramiko/paramiko demosundan uyarlanmıştır . Benim için çalışıyor.


1

Bu benim için çalıştı

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

Uzak makineleri yönetmek ve dosya işlemlerini gerçekleştirmek için geliştirdiğimiz spur ve paramiko etrafında bir sarmalayıcı olan spurplus'a bir bakın .

Spurplus, kullanıma hazır bir check_output()işlev sunar:

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.