paramiko 遠程控制介紹
Python paramiko是一個相當好用的遠程登錄模塊,采用ssh協議,可以實現linux服務器的ssh遠程登錄。首先來看一個簡單的例子
import paramiko #實例化ssh客戶端
ssh = paramiko.SSHClient() #創建默認的白名單
policy = paramiko.AutoAddPolicy() #設置白名單
ssh.set_missing_host_key_policy(policy) #鏈接服務器
ssh.connect( hostname = "192.168.2.186", #服務器的ip
port = 22, #服務器的端口
username = "root", #服務器的用戶名
password = "123" #用戶名對應的密碼
) #遠程執行命令
stdin,stdout,stderr = ssh.exec_command("ls") #exec_command 返回的對象都是類文件對象
#stdin 標准輸入 用於向遠程服務器提交參數,通常用write方法提交
#stdout 標准輸出 服務器執行命令成功,返回的結果 通常用read方法查看
#stderr 標准錯誤 服務器執行命令錯誤返回的錯誤值 通常也用read方法 #查看結果,注意在Python3 字符串分為了:字符串和字節兩種格式,文件返回的是字節
result = stdout.read().decode() print(result)
這是一段最簡單的paramiko的代碼,其中比較難理解的就是白名單概念,所謂的白名單就是ssh的know_hosts文件,用來記錄paramiko可以信任的遠程主機,在
paramiko當中,需要生成和采用兩個步驟,來避免在遠程鏈接的時候,被詢問是否信任遠程登錄的服務器。
threaing多線程介紹
想要學習多線程,先要明白:
進程:是程序的一次運行,我們運行一個程序,就會形成一個進程,進程有獨立的內存空間,也被稱為重量級進程。
線程:線程是進程下的一個分支,也被稱為輕量級進程。
threading是python多線程的基礎模塊,也可以說Python程序員接觸多線程最初接觸的模塊,
我們來看一下threading最基礎的案例
為了好理解我們來了解前置代碼的編寫
最簡單的例子:
1 from time import sleep 2 #通過這個例子我們來看計算機正常情況下的執行順序 從左往右,從上到下 3 def loop0(): 4 print("loop 0 is start") 5 sleep(3) 6 print("loop 0 is down") 7 8 def loop1(): 9 print("loop 1 is start") 10 sleep(2) 11 print("loop 1 is down") 12 13 def main(): 14 print("all is start") 15 loop0() 16 loop1() 17 print("all is down") 18 19 if __name__ == "__main__": 20 main()
代碼優化過的例子:
from time import sleep def loop(num,sleeptime): """ 當前函數作為功能函數 :param num: 函數的編號 :param sleeptime: 睡眠的時間 """
print("loop %s is start"%num) sleep(sleeptime) print("loop %s is done"%num) def main(): sleep_list = [3,2] #睡眠時間
lenth = len(sleep_list) #獲取列表長度
print("all is start") for i in range(lenth): loop(i,sleep_list[i]) #按照列表長度和列表內容調用函數
print("all is down") if __name__ == "__main__": main()
多線程調用的例子:
1 import threading 2 from time import sleep 3 4 def loop(num,sleeptime): 5 """ 6 當前函數作為功能函數 7 :param num: 函數的編號 8 :param sleeptime: 睡眠的時間 9 """ 10 print("loop %s is start"%num) 11 sleep(sleeptime) 12 print("loop %s is done"%num) 13 14 def main(): 15 sleep_list = [3,2] #睡眠時間 16 lenth = len(sleep_list) #獲取列表長度 17 thread_list = [] 18 print("all is start") 19 for i in range(lenth): 20 #threading.Thread 就是用線程來執行我們的功能 21 t = threading.Thread(target = loop,args = (i,sleep_list[i])) #按照列表長度和列表內容調用函數 22 thread_list.append(t) #將生成的線程添加到列表里 23 for t in thread_list: 24 t.start() #開始執行線程 25 for t in thread_list: 26 t.join() #掛起線程,到所有線程結束 27 print("all is down") 28
通過上面例子的執行,我們需要掌握以幾個點:
1、threading.Thread方法用來創建線程,線程被創建的時候沒有執行,需要通過start方法執行
2、多線程調用實際上就是把原有的功能發到線程上面去跑,所以我們使用多線程,功能要寫成函數
3、Python的多線程是異步並發,而不是大家理解的並行,在這里
並發:指的是同時出發,不同時執行
並行:指的是同時進行,不一定同時出發
希望各位同學注意上面的三點,而值得大家思考的就是上面代碼最后的for循環可以簡化嗎?為啥?
paramiko+threading 實現遠程服務器批量執行命令
完成上面的代碼實例,我們進行代碼的整合,完成遠程服務器批量執行命令的效果
1 #coding:utf-8
2
3 import sys 4 import paramiko 5 import threading 6
7 def getConnection(ip,username,password,command,port = 22): 8 """
9 :param ip: 服務器的ip 10 :param username: 服務器的用戶名稱 11 :param password: 服務器的密碼 12 :param CMD: 服務器的命令 13 :param port: 服務器的端口 14 """
15 ssh = paramiko.SSHClient() 16 policy = paramiko.AutoAddPolicy() 17 ssh.set_missing_host_key_policy(policy) 18 ssh.connect( 19 hostname = ip, # 服務器的ip
20 port = port, # 服務器的端口
21 username = username, # 服務器的用戶名
22 password = password # 用戶名對應的密碼
23 ) 24 stdin, stdout, stderr = ssh.exec_command(command) 25
26 result = stdout.read().decode() 27
28 error = stderr.read().decode() 29
30 print("+++++++++++++++++++++++start++++++++++++++++++++") 31 print("[connect success] | ip : %s" % ip) 32 print("result: \n %s"%result) 33 if error != " ": 34 print("error: \n %s"%error) 35 print("+++++++++++++++++++++++done++++++++++++++++++++") 36
37 ssh.close() 38 #我們采用多線程
39 def main(host_list,command): 40 thread_list = [] 41 for ip,username,password in host_list: 42 thread = threading.Thread(target = getConnection, args = (ip,username,password,command)) 43 thread_list.append(thread) 44 for t in thread_list: 45 t.start() 46 for t in thread_list: 47 t.join() 48
49
50 if __name__ == "__main__": 51 host_list = [ 52 ("192.168.2.186", "root", "123"), 53 ("192.168.2.88", "root", "123"), 54 ] 55 command = sys.argv[1] 56 main(host_list,command)
在這當中,我們使用了sys.argv方法來接收腳本外面執行的參數,當然,我們也可以將host_list寫到一個配置文件當中使用。執行效果如下: