我有一些 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 秒截屏”到日志文件中?
答案1
简而言之,假设没有 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
}'
答案2
我使用任一script2log
(简单),或vile-pager
(vi 喜欢 emacs)对于这类事情。该脚本处理上述类型的重打,以及退格/重打。要处理光标移动(就像编辑命令行一样),像这样的简单脚本是不够的。但是,该脚本删除了 ANSI 样式的转义序列。
这脚本使用sed
。这只是 sed 命令:
# 修剪普通 ANSI 序列,然后修剪 OSC 序列,然后退格 # 序列,然后是尾随 CR,最后是重击部分 # 行。 # # 还有几个有趣的情况无法处理 # 使用此类脚本。例如: # CSI K(清晰线) # 光标在行内移动 sed\ -e 's/[[][?]\{0,1\}[;0-9]*[@-~]//g' \ -e's/[]][^]*//g'\ -e's/[]][^]*\\//g'\ -e ':循环; s/[^]\(.\)/\1/g;循环;' \ -e's/*$//g'\ -e 's/^.* //g' \ -e's/[^[]//g'
它包含文字转义字符而不是依赖于非 POSIX 扩展。
进一步阅读:
- sed - 流编辑器(POSIX)
- ECMA-48:编码字符集的控制函数