Bash
如何正確記錄經常更新螢幕“部分”的控制台程序的輸出,從而導致日誌文件混亂?
我有一些 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 }'