paramiko使用tail實(shí)時(shí)獲取服務(wù)器的日志輸出詳解
基本思路
現(xiàn)在有這么一個(gè)需求需要實(shí)現(xiàn)自動(dòng)化:需要實(shí)時(shí)獲取服務(wù)器cpu,gpu溫度以及傳感器信息上報(bào)情況,對(duì)高低溫環(huán)境下對(duì)于設(shè)備運(yùn)行狀態(tài)的影響進(jìn)行測(cè)試?;舅悸窞槔胮aramiko ssh到服務(wù)器上,起一個(gè)線程用tail -f命令實(shí)時(shí)獲取日志輸出,起另外一個(gè)線程用‘cat /sys/class/thermal/thermal_zone0/temp'命令定時(shí)獲取cpu,gpu溫度。
代碼
def get_report_info_perid(self, cmd, diff_time, thre_time): # 發(fā)送要執(zhí)行的命令 pre_time_stamp = [0] * 4 self._channel.send(cmd + '\r') # 回顯很長(zhǎng)的命令可能執(zhí)行較久,通過循環(huán)分批次取回回顯 time_stamp_arr = [] index = [0] * 4 current_line = b'' line_counter = 0 line_feed_byte = '\n'.encode(self.encoding) while True: buffer = self._channel.recv(1) if len(buffer) == 0: logger.info('end______________') break current_line += buffer if buffer == line_feed_byte: line = current_line.decode(self.encoding) logger.debug('shell顯示:%s'%line) if not line.startswith(self.rq): line_counter += 1 current_line = b'' continue col = self.check_type(line) time_stamp = int(time.mktime(time.strptime(' '.join([line[:8], line[9:17]]), "%Y%m%d %H:%M:%S"))) time_stamp_dec = line[18: 21] # 精確到毫秒 time_stamp = time_stamp * 1000 + int(time_stamp_dec) logger.info('%s:%s' % (senior_name[col], time_stamp)) self.write_xl(index[col] + 1, col, time_stamp) index[col] += 1 if pre_time_stamp[col] == 0: pre_time_stamp[col] = time_stamp else: if abs((time_stamp - pre_time_stamp[col]) - diff_time[col]) > thre_time[col]: logger.error( '兩幀數(shù)據(jù)間隔為{}ms,時(shí)間戳分別為:({},{}),行號(hào):{}'.format(time_stamp - pre_time_stamp[col], time_stamp, pre_time_stamp[col], index[col])) pre_time_stamp[col] = time_stamp line_counter += 1 current_line = b'' def get_temp_info(self, col, max_number): index = 0 cpu_arr, gpu_arr = [], [] while True: cpu_temp, gpu_temp = self.get_cpu_gpu_temp() logger.info('cpu_temp:%s, gpu_temp:%s' % (cpu_temp, gpu_temp)) cpu_arr.append(cpu_temp) gpu_arr.append(gpu_temp) self.write_xl(index + 1, col, cpu_temp) self.write_xl(index + 1, col + 1, cpu_temp) time.sleep(60) index += 1 if max_number == index: break return cpu_arr, gpu_arr
遇到問題
1.問題1
一開始的cmd命令為 tail -f log.txt | grep -aE “a|b”
結(jié)果出現(xiàn)一個(gè)問題,在代碼運(yùn)行幾分鐘之后,就獲取不到數(shù)據(jù)了
一開始以為是paramiko的問題,會(huì)在一定時(shí)間之后自動(dòng)關(guān)閉client,但是經(jīng)過調(diào)試之后發(fā)現(xiàn)是阻塞在_channel.recv,一直收不到服務(wù)端的數(shù)據(jù)導(dǎo)致。
經(jīng)過百度之后發(fā)現(xiàn)由于linux的緩沖機(jī)制影響導(dǎo)致tail -f 結(jié)合管道|的時(shí)候會(huì)輸出延遲
緩沖是一種有效提高IO效率的方法,把頻繁的讀寫請(qǐng)求積累到一定程度后再一次性的與IO設(shè)備交互操作。
IO緩沖有3種,無(wú)緩沖,行緩沖,和全緩沖。
- 無(wú)緩沖,就是不使用緩沖機(jī)制。面向字節(jié)的設(shè)備?(stderr)
- 行緩沖,緩沖,直到遇到換行符。一般用于終端設(shè)備。
- 全緩沖,緩沖,直到buffer滿。一般用于塊設(shè)備。
在終端窗口中執(zhí)行tail命令,是面向終端設(shè)備的,會(huì)使用行緩沖,所以日志中每寫入一行,立刻就會(huì)輸出。
當(dāng)使用管道時(shí),會(huì)變?yōu)槭褂萌彌_,這樣一來(lái),就要等到日志中寫入的字節(jié)數(shù)填滿buffer后才會(huì)輸出。
解決方法:
把tail的標(biāo)準(zhǔn)輸出重定向到標(biāo)準(zhǔn)錯(cuò)誤上,并把標(biāo)準(zhǔn)錯(cuò)誤也給管道。
因?yàn)閟tderr是無(wú)緩沖的。
例如 tail -f >&2 | grep
或者直接去掉管道
2.問題2
按照問題一的結(jié)論,我去掉了命令中的管道,直接使用 tail -f log.txt命令,將過濾放到check_type函數(shù)中進(jìn)行,發(fā)現(xiàn)運(yùn)行幾分鐘之后獲取不到數(shù)據(jù)的情況并沒有解決。于是繼續(xù)定位。最后經(jīng)過一番挫折之后發(fā)現(xiàn)是使用的tail -f命令有問題
tail -f
等同于–follow=descriptor,根據(jù)文件描述符進(jìn)行追蹤,當(dāng)文件改名或被刪除,追蹤停止
tail -F
等同于–follow=name --retry,根據(jù)文件名進(jìn)行追蹤,并保持重試,即該文件被刪除或改名后,如果再次創(chuàng)建相同的文件名,會(huì)繼續(xù)追蹤
log.txt文件在程序運(yùn)行過程中被修改了文件描述符從而導(dǎo)致tail -f不繼續(xù)跟蹤。修改為tail -F后問題解決
到此這篇關(guān)于paramiko使用tail實(shí)時(shí)獲取服務(wù)器的日志輸出的文章就介紹到這了,更多相關(guān)paramiko用tail實(shí)時(shí)獲取服務(wù)器日志輸出內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python中enumerate函數(shù)遍歷元素用法分析
這篇文章主要介紹了python中enumerate函數(shù)遍歷元素用法,結(jié)合實(shí)例形式分析了enumerate函數(shù)遍歷元素的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-03-03Matplotlib animation模塊實(shí)現(xiàn)動(dòng)態(tài)圖
這篇文章主要介紹了Matplotlib animation模塊實(shí)現(xiàn)動(dòng)態(tài)圖,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02python使用win32com在百度空間插入html元素示例
這篇文章主要介紹了python使用win32com在百度空間插入html元素的示例,大家參考使用吧2014-02-02Numpy數(shù)組的組合與分割實(shí)現(xiàn)的方法
本文主要介紹了Numpy數(shù)組的組合與分割實(shí)現(xiàn)的方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08python虛擬機(jī)pyc文件結(jié)構(gòu)的深入理解
這篇文章主要為大家介紹了python虛擬機(jī)之pyc文件結(jié)構(gòu)的深入探究理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03淺談tensorflow使用張量時(shí)的一些注意點(diǎn)tf.concat,tf.reshape,tf.stack
這篇文章主要介紹了淺談tensorflow使用張量時(shí)的一些注意點(diǎn)tf.concat,tf.reshape,tf.stack,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-06-06Python3實(shí)戰(zhàn)之爬蟲抓取網(wǎng)易云音樂的熱門評(píng)論
這篇文章主要給大家介紹了關(guān)于Python3實(shí)戰(zhàn)之爬蟲抓取網(wǎng)易云音樂熱評(píng)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10Python使用GitPython操作Git版本庫(kù)的方法
這篇文章主要介紹了Python使用GitPython操作Git版本庫(kù)的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02