Bash

如何正確記錄經常更新螢幕“部分”的控制台程序的輸出,從而導致日誌文件混亂?

  • April 13, 2016

我有一些 Java 執行檔 (jar),它每晚從 cron 作業執行我的一些 shell 腳本。該執行檔不會“像往常一樣”列印日誌語句,只是通過逐行列印(列印後列印)的順序方式列印它們,但是在處理其數據時,它會列印帶有狀態數據的單行,然後“覆蓋”或一遍又一遍地“更新”那一行,直到完成這部分處理。

例子:

一個通用程序會輸出如下內容:

Program XYZ started..<cr+lf>
processing 1<cr+lf>
processing 2<cr+lf>
processing 3<cr+lf>
im done<cr+lf>

簡單的!我可以輕鬆地將其輸出重定向到一個文件,我就完成了。

但我將不得不處理的程序更像是這樣:

Program XYZ started..<cr+lf>
processing 1<cr>
processing 1 - part a<cr>
processing 1 - part b<cr>
processing 1 - part c<cr>
processing 1 - part d<cr>
<cr+lf>
processing 2<cr>
processing 2 - part a<cr>
processing 2 - part b<cr>
processing 2 - part c<cr>
processing 2 - part d<cr>
<cr+lf>
processing 3<cr+lf>
im done<cr+lf>

但比我在這裡展示的要密集得多。所以它並不總是覆蓋狀態行,而是在處理時做了很多。因此,僅將其輸出重定向或附加到日誌文件在這裡似乎沒有多大意義,因為它只會使日誌文件雜亂無章,數以百萬計的螢幕更新無法被人類輕易查看和理解。

所以我的問題是:有沒有一種方法或工具可以讓程序“記錄”或“每 30 秒截屏一次”它們的輸出到日誌文件?

簡單地說,假設沒有要處理的 vt100 轉義,您可以嘗試將輸出推送到

sed 's/\r$//; s/.*\r//'

或 awk 等價物

awk '{ sub("\r$",""); sub(".*\r",""); print}'

但這假設您的 sed 或 awk 可以處理很長的行,因為輸入顯然不是換行符。此外,輸入僅將游標移動到行首,但不會刪除該行上的內容,因此嚴格來說,您應該\r\r\n在範例之前保留長行。

為了處理有效的長行,您可以使用tr '\r\n' '\n\001'將換行符轉換\r為換行符,同時將換行符轉換為不在數據中的其他字元,例如 control-a。

RS='\r'或者,如果您的 awk 允許,您可以使用 更改 awk 的輸入記錄分隔符。這為您提供了一個腳本,例如:

awk -v RS='\r' '
{ if(sub("\n","")){print last;last=""}
 if($0!="")last = $0
}'

引用自:https://unix.stackexchange.com/questions/276202