SSH與Python模塊paramiko

paramiko是用python語(yǔ)言寫的一個(gè)模塊,遵循SSH2協(xié)議弟胀,支持以加密和認(rèn)證的方式楷力,進(jìn)行遠(yuǎn)程服務(wù)器的連接。paramiko支持Linux, Solaris, BSD, MacOS X, Windows等平臺(tái)通過(guò)SSH從一個(gè)平臺(tái)連接到另外一個(gè)平臺(tái)孵户。利用該模塊萧朝,可以方便的進(jìn)行ssh連接和sftp協(xié)議進(jìn)行sftp文件傳輸。

一夏哭、paramiko模塊的安裝

paramiko模塊依賴PyCrypto模塊检柬,而PyCrypto需要GCC庫(kù)編譯,不過(guò)一般發(fā)行版的源里帶有該模塊竖配。這里以u(píng)buntu為例何址,直接借助以下命令可以直接完成安裝:

sudo pip3 install paramiko 

二酱固、paramiko的連接

使用paramiko模塊有兩種連接方式,一種是通過(guò)paramiko.SSHClient()函數(shù)头朱,另外一種是通過(guò)paramiko.Transport()函數(shù)。

方法一:

import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("某IP地址",22,"用戶名", "口令")

上面的第二行代碼的作用是允許連接不在know_hosts文件中的主機(jī)龄减。

方法二:

import paramiko
t = paramiko.Transport(("主機(jī)","端口"))
t.connect(username = "用戶名", password = "口令")

如果連接遠(yuǎn)程主機(jī)需要提供密鑰项钮,上面第二行代碼可改成:

t.connect(username = "用戶名", password = "口令", hostkey="密鑰")

三、paramiko ssh連接

以下是一個(gè)簡(jiǎn)單的通過(guò)paramiko模塊定義的ssh連接并執(zhí)行命令的函數(shù)希停,如下:

#!/usr/bin/python3
#-*- coding: utf-8 -*-
import paramiko
#paramiko.util.log_to_file('/tmp/sshout')
def ssh2(ip,username,passwd,cmd):
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(ip,22,username,passwd,timeout=5)
        stdin,stdout,stderr = ssh.exec_command(cmd)
        # stdin.write("Y") #interact with server, typing Y 
        print(stdout.read())
        # for x in stdout.readlines():
        # print x.strip("n")
        print('%s OK\n'%(ip))
        ssh.close()
    except :
        print('%s Error\n' %(ip))

ssh2("45.76.22.112","root","password","ls")

其中第四行的日志部分烁巫,是記錄ssh連接交互時(shí)的一些信息,可以看做是類似于debug的輸出宠能,一般情況下不需要開(kāi)啟亚隙。

stdin.write部分是用于交互情況下,通過(guò)該命令可以執(zhí)行交互违崇。注意這里可能會(huì)引起歧義阿弃,這里的交互并不是ssh連接過(guò)程中出現(xiàn)的讓輸入yes的交互,因?yàn)閜aramiko模塊在連接過(guò)程中會(huì)自動(dòng)處理好yes確認(rèn)羞延。這里的交互是指后面的cmd需要的執(zhí)行的程序可能出現(xiàn)交互的情況下渣淳,可以通過(guò)該參數(shù)進(jìn)行交互。

stdout標(biāo)準(zhǔn)輸出伴箩,在輸出內(nèi)容比較少時(shí)入愧,可以通過(guò)直接使用read讀取出所有的輸出;但在輸出內(nèi)容比較多時(shí)嗤谚,建議通過(guò)按行讀取進(jìn)行處理棺蛛。不過(guò)按行讀取時(shí),每行結(jié)尾會(huì)有換行符n巩步,這樣輸出的結(jié)果很不美觀旁赊。可以通過(guò)strip進(jìn)行字符串的處理渗钉。
在函數(shù)調(diào)用過(guò)程中需要注意的是彤恶,**IP、username鳄橘、passwd都是屬于字符串型的声离,所以需要加引號(hào)。后面執(zhí)行的cmd瘫怜,如果有多個(gè)命令需要操作時(shí)术徊,需要通過(guò)分號(hào)進(jìn)行分割。

四鲸湃、paramiko sftp示例

單個(gè)文件小傳下載的示例:

import paramiko
#建立一個(gè)加密的管道
scp=paramiko.Transport(('192.168.0.102',22))
#建立連接
scp.connect(username='root',password='361way')
#建立一個(gè)sftp客戶端對(duì)象赠涮,通過(guò)ssh transport操作遠(yuǎn)程文件
sftp=paramiko.SFTPClient.from_transport(scp)
#Copy a remote file (remotepath) from the SFTP server to the local host
sftp.get('/root/testfile','/tmp/361way')
#Copy a local file (localpath) to the SFTP server as remotepath
sftp.put('/root/crash-6.1.6.tar.gz','/tmp/crash-6.1.6.tar.gz')
scp.close()

一個(gè)目錄下多個(gè)文件上傳下載的示例:

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import paramiko,datetime,os
hostname='192.168.0.102'
username='root'
password='361way'
port=22
local_dir='/tmp/getfile'
remote_dir='/tmp/abc'
try:
    t=paramiko.Transport((hostname,port))
    t.connect(username=username,password=password)
    sftp=paramiko.SFTPClient.from_transport(t)
    #files=sftp.listdir(dir_path)
    files=sftp.listdir(remote_dir)
    for f in files:
    print ''
    print '#########################################'
    print 'Beginning to download file from %s %s ' % (hostname,datetime.datetime.now())
    print 'Downloading file:',os.path.join(remote_dir,f)
    sftp.get(os.path.join(remote_dir,f),os.path.join(local_dir,f))#下載
    #sftp.put(os.path.join(local_dir,f),os.path.join(remote_dir,f))#上傳
    print 'Download file success %s ' % datetime.datetime.now()
    print ''
    print '##########################################'
    t.close()
except Exception:
    print "connect error!" 

注:本處的目錄下所有文件進(jìn)行下載或上傳的示例中子寓,在遇到目錄下還有嵌套的目錄存在時(shí),會(huì)將目錄也當(dāng)做文件進(jìn)行處理笋除,所以如果想要更加的完美的話斜友,可以通過(guò)引入stat模塊下的S_ISDIR方法進(jìn)行處理
paramiko.transport對(duì)象也支持以socket的方式進(jìn)行連接,如下示例:

import paramiko
transport = paramiko.Transport(('localhost',22))
transport.connect(username='root', password = 'password')
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.get(remotefile,localfile)
#如果是上傳則用:
#sftp.put(localfile, remotefile)
transport.close()
#用socket連接
tcpsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcpsock.settimeout(5)
tcpsock.connect((ip,22),)
ssh = paramiko.Transport(tcpsock)
ssh.connect(username=user,password=password)
sftpConnect=paramiko.SFTPClient.from_transport(ssh) 

五垃它、利用paramiko實(shí)現(xiàn)ssh的交互式連接

以下是通過(guò)paramiko模塊直接用ssh協(xié)議登陸到遠(yuǎn)程服務(wù)器的操作代碼鲜屏,這里先定義一個(gè)interactive模塊,代碼如下:

import socket
import sys
# windows does not have termios...
try:
 import termios
 import tty
 has_termios = True
except ImportError:
 has_termios = False
def interactive_shell(chan):
 if has_termios:
 posix_shell(chan)
 else:
 windows_shell(chan)
def posix_shell(chan):
 import select
 oldtty = termios.tcgetattr(sys.stdin)
 try:
 tty.setraw(sys.stdin.fileno())
 tty.setcbreak(sys.stdin.fileno())
 chan.settimeout(0.0)
 while True:
 r, w, e = select.select([chan, sys.stdin], [], [])
 if chan in r:
 try:
 x = chan.recv(1024)
 if len(x) == 0:
 print 'rn*** EOFrn',
 break
 sys.stdout.write(x)
 sys.stdout.flush()
 except socket.timeout:
 pass
 if sys.stdin in r:
 x = sys.stdin.read(1)
 if len(x) == 0:
 break
 chan.send(x)
 finally:
 termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
# thanks to Mike Looijmans for this code
def windows_shell(chan):
 import threading
 sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.rnrn")
 def writeall(sock):
 while True:
 data = sock.recv(256)
 if not data:
 sys.stdout.write('rn*** EOF ***rnrn')
 sys.stdout.flush()
 break
 sys.stdout.write(data)
 sys.stdout.flush()
 writer = threading.Thread(target=writeall, args=(chan,))
 writer.start()
 try:
 while True:
 d = sys.stdin.read(1)
 if not d:
 break
 chan.send(d)
 except EOFError:
 # user hit ^Z or F6
 pass

代碼內(nèi)容可以從paramiko 在github項(xiàng)目上的demo里獲取国拇。再另外寫一個(gè)ssh_inter.py的交互主程序洛史,內(nèi)容如下:

import paramiko
import interactive
#記錄日志
paramiko.util.log_to_file('/tmp/test')
#建立ssh連接
ssh=paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.0.102',port=22,username='root',password='xxxxxx',compress=True)
#建立交互式shell連接
channel=ssh.invoke_shell()
#建立交互式管道
interactive.interactive_shell(channel)
#關(guān)閉連接
channel.close()
ssh.close()

執(zhí)行效果就像我們平時(shí)直接使用ssh登錄一樣。

六酱吝、總結(jié)

paramiko模塊是一個(gè)比較強(qiáng)大的ssh連接模塊也殖,以上的示例只是列出了該模塊的一些簡(jiǎn)單的使用方法,還可以使用threading模塊加塊程序并發(fā)的速度务热;也可以使用configparser模塊處理配置文件忆嗜,而我們將所有IP、用戶信息操作都放入配置文件崎岂;使用setproctitle模塊為執(zhí)行的程序加一個(gè)容易區(qū)分的title等霎褐。
同樣,雖然連fabric這樣大名鼎鼎的軟件使用的ssh都是用paramiko模塊進(jìn)行的封裝该镣,不過(guò)你依然可以選擇不使用它冻璃,你也可以選擇pexpect模塊實(shí)現(xiàn)封裝一個(gè)簡(jiǎn)易的ssh連接工具、或者使用同樣比較火的salt-ssh模塊损合。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末省艳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嫁审,更是在濱河造成了極大的恐慌跋炕,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件律适,死亡現(xiàn)場(chǎng)離奇詭異辐烂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)捂贿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門纠修,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人厂僧,你說(shuō)我怎么就攤上這事扣草。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵辰妙,是天一觀的道長(zhǎng)鹰祸。 經(jīng)常有香客問(wèn)我,道長(zhǎng)密浑,這世上最難降的妖魔是什么蛙婴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮尔破,結(jié)果婚禮上敬锐,老公的妹妹穿的比我還像新娘。我一直安慰自己呆瞻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布径玖。 她就那樣靜靜地躺著痴脾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪梳星。 梳的紋絲不亂的頭發(fā)上赞赖,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音冤灾,去河邊找鬼前域。 笑死,一個(gè)胖子當(dāng)著我的面吹牛韵吨,可吹牛的內(nèi)容都是我干的匿垄。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼归粉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼椿疗!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起糠悼,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤届榄,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后倔喂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體铝条,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年席噩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了班缰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡悼枢,死狀恐怖鲁捏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤给梅,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布假丧,位于F島的核電站,受9級(jí)特大地震影響动羽,放射性物質(zhì)發(fā)生泄漏包帚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一运吓、第九天 我趴在偏房一處隱蔽的房頂上張望渴邦。 院中可真熱鬧,春花似錦拘哨、人聲如沸谋梭。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瓮床。三九已至,卻和暖如春产镐,著一層夾襖步出監(jiān)牢的瞬間隘庄,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工癣亚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丑掺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓述雾,卻偏偏與公主長(zhǎng)得像街州,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子玻孟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理菇肃,服務(wù)發(fā)現(xiàn),斷路器取募,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評(píng)論 6 342
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯(cuò)誤還是無(wú)法避免 以后資料會(huì)慢慢更新 大...
    數(shù)據(jù)革命閱讀 12,134評(píng)論 2 34
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,504評(píng)論 25 707
  • Ubuntu的發(fā)音 Ubuntu,源于非洲祖魯人和科薩人的語(yǔ)言旺聚,發(fā)作 oo-boon-too 的音织阳。了解發(fā)音是有意...
    螢火蟲(chóng)de夢(mèng)閱讀 99,156評(píng)論 9 467