1. 前言
對大部分的人來說,解決 Bug 都是依靠關鍵字去日誌去定位問題!
在除錯情況下,我們可以實時在控制檯檢視日誌;但對於部署到伺服器上的應用,日誌都存放在伺服器某個目錄下,沒法透過本地檢視到
這種情況下,就需要我們先登入伺服器,然後進入到日誌目錄資料夾,最後透過日誌檔案去定位問題;如果涉及到 K8s 容器,可能還需要使用 kubectl 命令進入到服務對應的容器中,進入到日誌目錄,才能開始定位問題,這一切顯得非常繁瑣且低效
本篇文章介紹一款 Python 依賴庫:pexpect,作為一款命令列自動化工具,它可以幫助我們一鍵獲取日誌,快速定位問題!
2. pexpect 介紹pexpect 是 Python 語言實現的類 Expect 的一種實現,透過產生子應用程式並控制它們,透過期望模式對子應用程式的輸出做出相應處理
它主要對人機對話進行模擬,來實現一些自動化的場景
比如:用來和 SSH、FTP、PASSWD、Telnet 等命令列程式進行自動化互動
在使用之前,我們先安裝依賴包
# 安裝依賴庫pip3 install pexpect
3. 實戰一下我們以從伺服器 K8S 容器獲取日誌為例進行講解
3-1.SSH 登入
首先,初始化使用 pexpect 模擬 SSH 遠端登入伺服器
import pexpectPROMPT = ['# ', '>>> ', '> ', '\$ ']def login_with_pexpect(): """ 登入-pexpect :return: """ # 埠號 port = ** # 使用者名稱 user = ** # 密碼 pwd = ** # ip地址 ip = ** ssh_cmd = "ssh -p {} {}@{}".format(port,user,ip) # 指定登入命令,拿到程式操作控制代碼 child = pexpect.spawn(ssh_cmd, timeout=60, encoding='utf-8') # 提示輸入密碼的字元出現,否則超時 ret = child.expect([pexpect.TIMEOUT, '[P|p]assword: '], timeout=10) # 匹配成功後,輸入密碼,執行登陸操作 if ret == 1: # 傳送密碼 child.sendline(pwd) child.expect(PROMPT) return child else: print('登入失敗!')
其中
pexpect.spawn() :用於執行一個程式,並返回一個操作控制代碼
該方法常見的 3 個引數如下:
第一個引數是待執行的命令第二個引數指定超時時間,程式執行後的輸出檢查,如果指定時間內沒有匹配到結果,就會拋異常第三個引數用於設定編碼格式child.expect() :對輸出結果,利用正則表示式進行關鍵字匹配
程式碼中的含義是在 10s 內等待出現關鍵字 '[P|p]assword: '
最後,如果匹配的結果為 1,使用 sendline() 方法傳送帶回車符的字串,模擬密碼的輸入,完成登入操作
3-2.封裝傳送命令
接下來,我們將操作控制代碼傳送命令進行一次封裝,並獲取返回結果
def send_command(child, cmd, expected_content=None, timeout=10): """ 傳送一條命令,並列印結果 :param expected_content: :param child: :param cmd: :return: """ # 傳送一條命令 if expected_content is None: expected_content = ["#"] child.sendline(cmd) # 期望有命令列提示字元出現 child.expect(expected_content, timeout=timeout) # 將之前的內容都輸出 result = child.before return result
需要指出的是,child.before 用於獲取到匹配到關鍵字為止,快取裡面已有的全部資料
3-3.進入容器 pod 日誌目錄
使用上面的方法,透過 kubectl 進入到對應的容器日誌目錄
# 登入pod容器exec_enter_pod = 'kubectl -n %s exec -it %s bash' % (env, pod_name)# 進入容器send_command(child, exec_enter_pod)# 進入到日誌目錄send_command(child, "cd logs", expected_content='tomcat/logs#')
3-4.獲取日誌內容
最後我們只需要組成獲取日誌的命令
比如:使用 grep/tail 命令組成一個提取日誌檔案的命令
然後使用控制代碼物件傳送這條命令
最後,對返回內容進行清洗即可
4. 最後文中使用 pexpect 實現了一個非常簡單的場景
事實上,大部分人機對話自動化互動都可以由它來實現,比如,下載日誌、實時配置、遠端打包下載等