一、概述
最近發現辦公室有一個感測器網關,偶爾會掉線,重啟之后,就正常了。
手動操作過程如下:
# telnet 10.212.82.90 Trying 10.212.82.90... Connected to 10.212.82.90. Escape character is '^]'. (none) login: root Password: Please make sure that what you're doing! If you aren't administrator, please Don't do anything! :) # ps PID USER VSZ STAT COMMAND 1 root 1124 S init 2 root 0 SW [kthreadd] 3 root 0 SW [ksoftirqd/0] 4 root 3888 S /usr/app/bin/app
說明:先telnet進去,輸入用戶名和密碼之后,執行ps命令。如果有/usr/app/bin/app進程,說明設備正常,否則就需要重啟。
但是手動操作比較麻煩,需要使用python登錄網關設備,檢測是否正常。
二、Telnet對象
Telnet.read_until(expected, timeout=None) : #讀取連接服務器后顯示的內容,直到遇到同expected相同的字節串。或者等待時間大於timeout時直接向下運行。
Telnet.read_very_eager() : 讀取從上次IO阻斷到現在所有的內容,返回的是字節串,需要進行decode()編碼。如果連接關閉或者沒有可用數據時會拋出EOFError,如果沒有其他可用的數據,返回的是b"",除非在IAC中間,否則不會阻礙。
Telnet.open(host, port=23[, timeout]) : 連接到主機,端口號為第二個可選參數,默認為標准的Telnet端口(23),可選的timeout參數指定連接的超時時間,如果未指定,將使用全局默認超時設置。不要嘗試去重新打開一個已經連接的實例對象。
Telnet.close() : 關閉連接。
Telnet.write(buffer) : # 將一個字節串(byte string)寫進socket,如果連接被阻塞,這也會被阻塞,如果連接關閉,會拋出OSError。
Telnet.interact() : telnet的交互功能,下面用了一個死循環保證用戶能夠一直輸入命令進行某些操作,也可以使用Telnet.interact()這個方法來使所連接終端持久化,不過官網說 (emulates a very dumb Telnet client)直譯是一個非常愚蠢的客戶端。
官方文檔,請參考:
https://docs.python.org/zh-cn/3/library/telnetlib.html
三、檢測腳本
check_gateway.py
#!/usr/bin/env python3 # coding: utf-8 import telnetlib import time class TelnetClient(object): def __init__(self, ip, user, pswd): self.tn = telnetlib.Telnet() self.host_ip = ip self.username = user self.password = pswd self.last_res = '' # 記錄上次命令執行結果 # 此函數實現telnet登錄主機 def login_host(self): try: # self.tn = telnetlib.Telnet(host_ip,port=23) self.tn.open(self.host_ip) except: text = '{} 網絡連接失敗'.format(self.host_ip) print(text) return False # 等待login出現后輸入用戶名,最多等待0.3秒 self.tn.read_until(b'Username: ', timeout=0.3) self.tn.write(self.username.encode('ascii') + b'\n') # 等待Password出現后輸入用戶名,最多等待0.3秒 self.tn.read_until(b'Password: ', timeout=0.3) self.tn.write(self.password.encode('ascii') + b'\n') # 延時5秒再收取返回結果,給服務端足夠響應時間 # time.sleep(5) # 獲取登錄結果 # read_very_eager()獲取到的是的是上次獲取之后本次獲取之前的所有輸出 command_result = self.tn.read_very_eager().decode('utf-8') if 'Login invalid' in command_result: # Cisco交換登錄失敗提示語 text = '{} 登錄失敗,用戶名或密碼錯誤'.format(self.host_ip) print(text) return False else: text = '{} 登錄成功'.format(self.host_ip) print(text) return True # 執行某一條命令 def execute_command(self, command, show_res=False): self.tn.write(command.encode() + b'\n') time.sleep(3) # 獲取命令結果 command_result = self.tn.read_very_eager().decode('utf-8') # if show_res: # print('命令執行結果:%s' % command_result) return command_result # 退出telnet def logout_host(self): self.tn.write(b"exit\n") # print('本次操作結束,連接斷開\n') def check_gateway(ip): # 指定連接的交換機管理IP telnet_client = TelnetClient(ip=ip, user='root', pswd='123456') # 如果登錄結果返加True,則執行命令,然后退出 if not telnet_client.login_host(): print("錯誤,ip: %s 登錄失敗"%ip) return False # 執行指定命令,查看進程 res1 = telnet_client.execute_command('ps') # print(res1, type(res1)) if not res1: print("錯誤,ip: %s 執行命令ps失敗" % ip) return False if "/usr/app/bin/app" in res1: print("正常,ip: %s 設備正常" % ip) telnet_client.execute_command('exit') # 退出配置模式 else: print("錯誤,ip: %s 設備掉線" % ip) # 執行重啟 res2 = telnet_client.execute_command('reboot') # 退出登錄 telnet_client.logout_host() return True if __name__ == '__main__': ip = "10.212.82.90" check_gateway(ip)
注意:請根據實際情況,修改ip地址,用戶名和密碼。
執行腳本
# python3 check_gateway.py 10.212.82.90 登錄成功 正常,ip: 10.212.82.90 設備正常
本文參考鏈接:
