Python 實現遠端伺服器批量執行命令
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寫到一個配置檔案當中使用。執行效果如下: