1. 程式人生 > >Python 實現遠端伺服器批量執行命令

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寫到一個配置檔案當中使用。執行效果如下: