原文:https://blog.51cto.com/u_12203282/6000840
作者:咪哥雜談
爲啥要用python去做實時監控linux後臺日誌呢,其實是因爲在元旦監控生產環境時發現的詬病,服務器太多導致xshell一開窗口要開好多個,而現在又沒有實現自動化運維的功能,不僅是這樣,若想要查看某臺服務器上的日誌還需要先ctrl + c終止終端(terminal),而查看篩選條件也需要重複性的大量操作,於是想到有沒有可以用python寫個腳本連接到各臺服務器上,監控的同時直接把日誌寫入到本地上。有了想法,實現只是時間問題咯。。。
環境
python3
linux的各種ip以及對應的賬號密碼
第三方庫:paramiko
這裏要說一下,windows下藉助的第三方庫是paramiko這個加密及SSH功能的強大庫,推薦再有網的情況下進行安裝:
pip install paramiko
代碼實現
廢話不多說,直接上碼,註釋寫的很詳細,老規矩不多講:
import time import paramiko import select now_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) now_day = time.strftime('%Y-%m-%d', time.localtime(time.time())) #方法複用,連接客戶端通過不同id進來即可 #這個方法是進行非實時的連接返回,例如ls這樣的cmd命令,或者grep這樣的命令。。 def link_server_cmd(serverip,user,pwd): print('------------開始連接服務器(%s)-----------' % serverip) client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) print('------------開始認證......-----------') client.connect(serverip, 22, username=user, password=pwd, timeout=4) print('------------認證成功!.....-----------') while 1: cmd = input('(輸入linux命令)~:') stdin, stdout, stderr = client.exec_command(cmd) #enumerate這個寫法可遍歷迭代對象以及對應索引 for i, line in enumerate(stdout): print(line.strip("\n")) break client.close() #此方法是進行實時返回,例如tail -f這樣的命令,本次監控就用的是此方法。 #將實時返回的日誌返回到本地 def link_server_client2(serverip, user, pwd): # 進行連接 print('------------開始連接服務器(%s)-----------' % serverip) client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) print('------------開始認證......-----------') client.connect(serverip, 22, username=user, password=pwd, timeout=4) print('------------認證成功!.....-----------') # 開啓channel 管道 transport = client.get_transport() channel = transport.open_session() channel.get_pty() # 執行命令nohup.log.2017-12-30 tail = 'tail -f /xxxx/xxxxx/nohuplogs/nohuplogs20180101.log' #將命令傳入管道中 channel.exec_command(tail) while True: #判斷退出的準備狀態 if channel.exit_status_ready(): break try: # 通過socket進行讀取日誌,個人理解,linux相當於客戶端,我本地相當於服務端請求獲取數據(此處若有理解錯誤,望請指出。。謝謝) rl, wl, el = select.select([channel], [], []) if len(rl) > 0: recv = channel.recv(1024) # 此處將獲取的數據解碼成gbk的存入本地日誌 print(recv.decode('gbk', 'ignore')) text_save(recv.decode('gbk', 'ignore'), 'tail(' + serverip + ').txt') #鍵盤終端異常 except KeyboardInterrupt: print("Caught control-C") channel.send("\x03") # 發送 ctrl+c channel.close() client.close() # 文件存儲 def text_save(self,content, filename, mode='a'): # Try to save a list variable in txt file. file = open(filename, mode) for i in content: file.write(i) file.close()
結論
結果不言而喻呀,當然是成功了,這裏因爲涉及到隱私問題,就不上傳生產的圖片結果了,有需要的同學可以親測一下,通過這次的代碼需求,感覺對於自己監控而言,確實是方便了不少,在解決channel管道進行實時傳輸數據那裏費時比較多…..因爲對socket編程不是很瞭解,後續繼續看看吧…