如何正确记录经常更新屏幕“部分”的控制台程序的输出,从而导致日志文件混乱?

如何正确记录经常更新屏幕“部分”的控制台程序的输出,从而导致日志文件混乱?

我有一些 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-pagervi 喜欢 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 扩展。

进一步阅读:

相关内容