使用Python paramiko模組利用多執行緒實現ssh併發執行操作
1.paramiko概述
ssh是一個協議,OpenSSH是其中一個開源實現,paramiko是Python的一個庫,實現了SSHv2協議(底層使用cryptography)。
有了Paramiko以後,我們就可以在Python程式碼中直接使用SSH協議對遠端伺服器執行操作,而不是通過ssh命令對遠端伺服器進行操作。
由於paramiko屬於第三方庫,所以需要使用如下命令先行安裝
2.安裝paramiko
pip install paramiko
3.常用方法
connect():實現遠端伺服器的連線與認證,對於該方法只有hostname是必傳引數。
常用引數
hostname 連線的目標主機
port=SSH_PORT 指定埠
username=None驗證的使用者名稱
password=None驗證的使用者密碼
pkey=None私鑰方式用於身份驗證
key_filename=None一個檔名或檔案列表,指定私鑰檔案
timeout=None可選的tcp連線超時時間
allow_agent=True,是否允許連線到ssh代理,預設為True允許
look_for_keys=True是否在~/.ssh中搜索私鑰檔案,預設為True允許
compress=False,是否開啟壓縮
set_missing_host_key_policy():設定遠端伺服器沒有在know_hosts檔案中記錄時的應對策略。目前支援三種策略:
設定連線的遠端主機沒有本地主機金鑰或HostKeys物件時的策略,目前支援三種:
AutoAddPolicy 自動新增主機名及主機金鑰到本地HostKeys物件,不依賴load_system_host_key的配置。即新建立ssh連線時不需要再輸入yes或no進行確認
WarningPolicy 用於記錄一個未知的主機金鑰的python警告。並接受,功能上和AutoAddPolicy類似,但是會提示是新連線
RejectPolicy 自動拒絕未知的主機名和金鑰,依賴load_system_host_key的配置。此為預設選項
exec_command():在遠端伺服器執行Linux命令的方法。
如 exec_command("ls /")exec_command("df -h")
4.使用方法
import paramiko # 例項化SSHClient client = paramiko.SSHClient() # 自動新增策略,儲存伺服器的主機名和金鑰資訊,如果不新增,那麼不再本地know_hosts檔案中記錄的主機將無法連線 client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 連線SSH服務端,以使用者名稱和密碼進行認證 client.connect(hostname='192.168.1.1',port=22,username='root',password='123456') # 開啟一個Channel並執行命令 stdin,stdout,stderr = client.exec_command('df -h ') # stdout 為正確輸出,stderr為錯誤輸出,同時是有1個變數有值 # 列印執行結果 print(stdout.read().decode('utf-8')) # 關閉SSHClient client.close()
5.利用多執行緒實現ssh併發訪問
要求:
編寫一個remote_comm.py指令碼,實現以下功能:
- 在檔案中取出所有遠端主機IP地址
- 在shell命令列中接受遠端伺服器IP地址檔案、遠端伺服器密碼以及在遠端主機上執行的命令
- 通過多執行緒實現在所有的遠端伺服器上併發執行命令
步驟一:編寫指令碼
#!/usr/bin/env python3 import sys import getpass import paramiko import threading import os #建立函式實現遠端連線主機、伺服器密碼以及在遠端主機上執行的命令的功能 def remote_comm(host,pwd,command): #建立用於連線ssh伺服器的例項 ssh = paramiko.SSHClient() #設定自動新增主機金鑰 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #連線ssh伺服器,新增連線的主機、使用者名稱、密碼填好,捕獲異常,有異常則跳出函式 try: ssh.connect(hostname=host,password=pwd) except: return #在ssh伺服器上執行指定命令,返回3項類檔案物件,分別是,輸入、輸出、錯誤 stdin,stderr = ssh.exec_command(command) #讀取輸出 out = stdout.read() #讀取錯誤 error = stderr.read() #如果有輸出 if out: #列印主機輸出內容 print('[%s] OUT:\n%s' % (host,out.decode('utf8'))) #如果有錯誤 if error: #列印主機錯誤資訊 print('[%s] ERROR:\n%s' % (host,error.decode('utf8'))) #程式結束 ssh.close() if __name__ == '__main__': #設定sys.argv長度,確保remote_comm函式中引數數量 if len(sys.argv) != 3: print('Usage: %s ipaddr_file "command"' % sys.argv[0]) exit(1) #判斷命令列上輸入如果不是檔案,確保輸入的是檔案 if not os.path.isfile(sys.argv[1]): print('No such file:',sys.argv[1]) exit(2) #fname為儲存遠端主機ip的檔案,用sys.argv方法,可以在執行指令碼時再輸入檔名,更為靈活 fname = sys.argv[1] #command為在遠端主機上執行的命令,用sys.argv方法,可以在執行指令碼時再輸入相應命令,command為remote_comm函式第三個引數 command = sys.argv[2] #通過getpass輸入遠端伺服器密碼,pwd為remote_comm函式第二個引數 # pwd = getpass.getpass() pwd='Taren1.bgsn' #開啟存有遠端主機ip的檔案 with open(fname) as fobj: #將遍歷檔案將ip以列表形式存入ips,line.strip()可以去掉每行ip後\n ips = [line.strip() for line in fobj] #迴圈遍歷列表,獲取ip地址,ip為remote_comm函式第一個引數 for ip in ips: #將讀取到的ip地址作為remote_comm函式實際引數傳遞給函式,ips中有幾個ip地址迴圈幾次 #建立多執行緒 t = threading.Thread(target=remote_comm,args=(ip,command)) #啟用多執行緒 t.start()
步驟二:編寫ssh名單
建立一個檔案,輸入某個網段所有可以ping通的ip,可以先用nmap出活躍主機掃描,或者自己編寫一個python指令碼
[root@room9pc01 ~]#nmap -n -sP 176.130.7.0/24 | grep 176 | awk '{print $5}' > /mnt/server_addr.txt [root@room9pc01 ~]#cat /mnt/server_addr.txt Nmap scan report for 176.130.7.1 Nmap scan report for 176.130.7.24 Nmap scan report for 176.130.7.46 Nmap scan report for 176.130.7.53 Nmap scan report for 176.130.7.57
.....................
步驟三:執行指令碼
執行指令碼,此指令碼有兩個引數,一個是檔案引數,一個是執行命令
[root@room9pc01 mnt]# python3 ssh.py server_addr.txt 'who' [176.130.7.57] OUT: student :0 2019-12-02 09:04 (:0) student pts/0 2019-12-02 15:03 (:0) [176.130.7.169] OUT: student :0 2019-12-02 08:17 (:0) student pts/0 2019-12-02 08:23 (:0) student pts/4 2019-12-02 08:24 (:0) [176.130.7.162] OUT: student :0 2019-12-02 08:17 (:0) student pts/0 2019-12-02 15:03 (:0) [176.130.7.178] OUT: student :0 2019-12-02 08:06 (:0)
總結
以上所述是小編給大家介紹的使用Python paramiko模組利用多執行緒實現ssh併發執行操作,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回覆大家的。在此也非常感謝大家對我們網站的支援!
如果你覺得本文對你有幫助,歡迎轉載,煩請註明出處,謝謝!