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


16

我有一个长时间运行的命令,该命令在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

会写:

my-cmd-2014-09-05T10:04:23Z

当达到20M时,它将压缩并打开一个新文件,依此类推,过一会儿它将开始删除最旧的文件。

是否存在这样的命令?

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


什么是“千兆字节”?
彼得·莫滕森

Answers:


6

您可以通过pipelog获得一些所需的信息,它“允许通过将其通过响应外部信号的中间管道传递来旋转或清除正在运行的进程的日志”,例如:

spewstuff | pipelog spew.log -p /tmp/spewpipe.pid -x "gzip spew.log.1"

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

kill -s USR1 $(</tmp/spewpipe.pid)

但是您必须设置cron或其他内容。但是,有一个陷阱。注意我gzip spew.log.1-这是因为在-x旋转日志后执行该命令。因此,spew.log.1.gz除非您编写一个简短的脚本来执行gzip并随后移动文件,然后将其用作-x命令,否则每次都会覆盖另一个问题。

完全公开:我写了这个,所以它当然可以完美地工作。;)对于版本0.2,我会考虑使用compress选项,或者会更好地简化压缩选项(的预期用途-x有所不同,但它会如上所述工作)。另外,自动过渡也是个好主意……第一个版本故意过小,因为我抵制了添加不必要功能的诱惑(毕竟,为此设置cron任务并不难)。

注意它是用于文本输出的;如果存在潜在的空字节,则应使用-z-用其他东西替换零。这是简化实现的折衷方案。


谢谢。我期待着pipelog-0.3;-)。我还遇到了metacpan.org/release/File-Write-Rotate。请注意,cron作业对于基于文件大小的旋转没有太大帮助。
斯特凡Chazelas

根据尺寸旋转!!!它确实使输出保持刷新状态,因此您可以每隔一段时间就对文件进行统计……
goldilocks 2014年

这样就无法可靠地将大小保持在20M以下(按照我的问题要求)。
斯特凡Chazelas

另一件事是,它仅是文本(我在那末添加了最后一段)。
goldilocks

4

丹·伯恩斯坦(Dan Bernstein)的multilog显然可以做到这一点-或也许是其中的大多数,同时通过文件描述符向!processor提供出口以弥补您所希望的差异-尽管20M / 1G大小规格可能需要一些修改,因为看起来16M是它的超出每个日志的限制。接下来,大多数情况下是从上面的链接进行复制+粘贴选择,尽管该链接还详细说明了其他选项,例如每行加时间戳,维护仅包含最新行匹配模式的其他文件等等。 。

接口

 multilog script

... 脚本包含任意数量的参数。每个参数指定一个动作。按输入的每一行顺序执行操作。

选择线

最初选择了每一行。那个行动...

-pattern

...如果图案与线匹配,则取消选择线。那个行动...

+pattern

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

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

自动旋转日志

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

 dir

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

日志格式如下:

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

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

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

那个行动...

 ssize

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

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

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

那个行动...

 nnum

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

那个行动...

 !processor

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


2

到目前为止,我能找到的最好的方法是,不涉及编写大量代码的近似值是以下zsh代码:

autoload zmv
mycmd |
  while head -c20M > mycmd.log && [ -s mycmd.log ]; do
    zmv -f '(mycmd.log)(|.(<->))(|.gz)(#qnOn)' '$1.$(($3+1))$4'
    {rm -f mycmd.log.1 mycmd.log.50.gz; (gzip&) > mycmd.log.1.gz} < mycmd.log.1
  done

在这里分割并旋转为最多51个20MiB大文件。


也许... loopmounts? btrfs也可以与一起安装compress-force=zlib
mikeserv

2

这是一个经过黑客攻击的python脚本,可以完成您所请求的操作:

#!/bin/sh
''':'
exec python "$0" "$@"
'''

KEEP = 10
MAX_SIZE = 1024 # bytes
LOG_BASE_NAME = 'log'

from sys import stdin
from subprocess import call

log_num = 0
log_size = 0
log_name = LOG_BASE_NAME + '.' + str(log_num)
log_fh = open(log_name, 'w', 1)

while True:
        line = stdin.readline()
        if len(line) == 0:
                log_fh.close()
                call(['gzip', '-f', log_name])
                break
        log_fh.write(line)
        log_size += len(line)
        if log_size >= MAX_SIZE:
                log_fh.close()
                call(['gzip', '-f', log_name])
                if log_num < KEEP:
                        log_num += 1
                else:
                        log_num = 0
                log_size = 0
                log_name = LOG_BASE_NAME + '.' + str(log_num)
                log_fh = open(log_name, 'w', 1)

1
是否有理由将其作为使用execpython而不是使用the pythonenv pythonhashbang 的shell脚本?
彼得2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.