将命令的输出存储到环形缓冲区中

Sté*_*las 16 logs utilities text-processing

我有一个长时间运行的命令,它会在 stdout 上生成大量输出。例如,我希望能够仅保留最后三天或最后一个 gibibyte(避免在中间切线),并且如果可能,文件块不大于 20 MiB。每个文件块都以数字后缀或时间戳命名。

就像是:

my-cmd | magic-command --output-file-template=my-cmd-%t \
                       --keep-bytes=1G \
                       --keep-time=3d \
                       --max-chunk-size=20M \
                       --compress=xz
Run Code Online (Sandbox Code Playgroud)

会写:

my-cmd-2014-09-05T10:04:23Z
Run Code Online (Sandbox Code Playgroud)

当它达到20M时,它会压缩它并打开一个新的,等等,然后它会开始删除最旧的文件。

有这样的命令吗?

我知道logrotate它管理其他应用程序编写的文件的能力,但我正在寻找更简单的东西,不需要设置 cron 作业、指定规则、暂停进程等。

gol*_*cks 6

您可以通过pipelog获得一些您想要的东西,它“允许通过管道通过响应外部信号的中间体来旋转或清除正在运行的进程的日志”,例如:

spewstuff | pipelog spew.log -p /tmp/spewpipe.pid -x "gzip spew.log.1"
Run Code Online (Sandbox Code Playgroud)

然后,您可以从/tmp/spewpipe.pid,获取 pid :

kill -s USR1 $(</tmp/spewpipe.pid)
Run Code Online (Sandbox Code Playgroud)

但是,您必须使用 cron 或其他东西进行设置。然而,这有一个问题。注意我gzip spew.log.1——这是因为该-x命令是在日志轮换后执行的。因此,spew.log.1.gz除非您编写一个简短的脚本来执行 gzip 并在之后移动文件,然后将其用作-x命令,否则您每次都会遇到覆盖的进一步问题。

完全披露:我写了这个,所以它当然可以完美运行。;) 对于 0.2 版,我会记住一个压缩选项,或者更好地促进它的选项( 的预期目的-x有些不同,但它会像上面一样工作)。自动翻转也是一个好主意......第一个版本故意最小化,因为我抵制了添加不必要功能的诱惑(毕竟为此设置一个cron作业并不难)。

请注意,它用于文本输出;如果有潜在的空字节,您应该使用-z-- 它用其他东西替换零。这是为了简化实现而进行的权衡。


mik*_*erv 5

Dan Bernstein 的multilog显然可以做到这一点 - 或者也许是大部分,同时通过文件描述符向!processor提供一个出口,以根据需要弥补差异 - 尽管 20M/1G 大小规格可能需要一些欺骗,因为看起来 16M 是它的每条日志超出限制。接下来的大部分内容是从上面的链接中进行的复制+粘贴选择,尽管该链接还详细介绍了其他选项,例如每行时间戳、维护仅包含最新行匹配模式等的其他文件。

界面

 multilog script
Run Code Online (Sandbox Code Playgroud)

...脚本由任意数量的参数组成。每个参数指定一个操作。对每行输入按顺序执行这些操作。

选择线路

每行都是最初选择的。那个行动...

-pattern
Run Code Online (Sandbox Code Playgroud)

...如果模式与该行匹配,则取消选择该行。那个行动...

+pattern
Run Code Online (Sandbox Code Playgroud)

如果模式与该行匹配,则选择该行。

...模式是一串星星和非星星。它匹配由所有星号和非星号以相同顺序匹配的任何字符串串联。非明星与自身相匹配。模式末尾之前的星号与不包含模式中下一个字符的任何字符串匹配。模式末尾的星号与任何字符串匹配。

自动轮换日志

如果dir以点或斜杠开头,则操作...

 dir
Run Code Online (Sandbox Code Playgroud)

...将每个选定的行附加到名为dir的日志中。如果dir不存在,multilog则创建它。

日志格式如下:

  1. dir是一个目录,其中包含一些旧日志文件、名为current的日志文件以及用于multilog跟踪其操作的其他文件。

  2. 每个旧日志文件都有一个以@开头的名称,继续显示文件完成时间的精确时间戳,并以以下代码之一结尾:

    • .s:此文件已完全处理并安全写入磁盘。
    • .u:此文件是在中断时创建的。它可能已被截断。它尚未被处理。

那个行动...

 ssize
Run Code Online (Sandbox Code Playgroud)

...设置后续dir操作的最大文件大小。如果当前sizemultilog字节,则将确定当前足够大。如果它在最大文件大小的 2000 字节内看到换行符,也会确定当前足够大;它会尝试在行边界处完成日志文件。)大小必须介于 4096 和 16777215 之间。默认最大文件大小为 99999。multilog

在0.75及以上版本中:如果multilog收到ALRM信号,如果电流非空,则立即判定电流足够大。

(注意:我怀疑如果需要的话zsh schedule,可以很容易地说服内置函数以指定的时间间隔发送。)ALRM

那个行动...

 nnum
Run Code Online (Sandbox Code Playgroud)

...设置后续dir操作的日志文件数。重命名current后,如果multilog看到num或更多旧日志文件,则会删除时间戳最小的旧日志文件。num必须至少为 2。日志文件的默认数量为 10。

那个行动...

 !processor
Run Code Online (Sandbox Code Playgroud)

...为后续的dir操作设置处理器。multilog将通过处理器馈送电流并将输出保存为旧日志文件而不是当前日志文件。还将保存处理器写入描述符 5 的任何输出,并在下一个日志文件上运行处理器时使该输出在描述符 4 上可读。为了可靠性,如果处理器在创建输出时遇到任何问题,则必须退出非零值;然后将再次运行它。请注意,正在运行的处理器可能会阻止向 提供输入的任何程序。multilogmultilogmultilog