1. 程式人生 > 程式設計 >paramiko使用tail實時獲取伺服器的日誌輸出詳解

paramiko使用tail實時獲取伺服器的日誌輸出詳解

基本思路

現在有這麼一個需求需要實現自動化:需要實時獲取伺服器cpu,gpu溫度以及感測器資訊上報情況,對高低溫環境下對於裝置執行狀態的影響進行測試。基本思路為利用paramiko ssh到伺服器上,起一個執行緒用tail -f命令實時獲取日誌輸出,起另外一個執行緒用‘cat /sys/class/thermal/thermal_zone0/temp'命令定時獲取cpu,gpu溫度。

程式碼

 def get_report_info_perid(self,cmd,diff_time,thre_time):
  # 傳送要執行的命令
  pre_time_stamp = [0] * 4
  self._channel.send(cmd + '\r')
  # 回顯很長的命令可能執行較久,通過迴圈分批次取回回顯
  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(
       '兩幀資料間隔為{}ms,時間戳分別為:({},{}),行號:{}'.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,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,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”

結果出現一個問題,在程式碼執行幾分鐘之後,就獲取不到資料了

一開始以為是paramiko的問題,會在一定時間之後自動關閉client,但是經過除錯之後發現是阻塞在_channel.recv,一直收不到服務端的資料導致。

經過百度之後發現由於linux的緩衝機制影響導致tail -f 結合管道|的時候會輸出延遲

緩衝是一種有效提高IO效率的方法,把頻繁的讀寫請求積累到一定程度後再一次性的與IO裝置互動操作。

IO緩衝有3種,無緩衝,行緩衝,和全緩衝。

  • 無緩衝,就是不使用緩衝機制。面向位元組的裝置?(stderr)
  • 行緩衝,緩衝,直到遇到換行符。一般用於終端裝置。
  • 全緩衝,緩衝,直到buffer滿。一般用於塊裝置。

在終端視窗中執行tail命令,是面向終端裝置的,會使用行緩衝,所以日誌中每寫入一行,立刻就會輸出。

當使用管道時,會變為使用全緩衝,這樣一來,就要等到日誌中寫入的位元組數填滿buffer後才會輸出。

解決方法:

把tail的標準輸出重定向到標準錯誤上,並把標準錯誤也給管道。

因為stderr是無緩衝的。

例如 tail -f >&2 | grep

或者直接去掉管道

2.問題2

按照問題一的結論,我去掉了命令中的管道,直接使用 tail -f log.txt命令,將過濾放到check_type函式中進行,發現執行幾分鐘之後獲取不到資料的情況並沒有解決。於是繼續定位。最後經過一番挫折之後發現是使用的tail -f命令有問題

tail -f

等同於–follow=descriptor,根據檔案描述符進行追蹤,當檔案改名或被刪除,追蹤停止

tail -F

等同於–follow=name --retry,根據檔名進行追蹤,並保持重試,即該檔案被刪除或改名後,如果再次建立相同的檔名,會繼續追蹤

log.txt檔案在程式執行過程中被修改了檔案描述符從而導致tail -f不繼續跟蹤。修改為tail -F後問題解決

到此這篇關於paramiko使用tail實時獲取伺服器的日誌輸出的文章就介紹到這了,更多相關paramiko用tail實時獲取伺服器日誌輸出內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!