记录stdout的旋转?


53

我有一个Linux程序,可以将信息写入stdout和stderr。

我有一个Shell脚本,可将输出重定向到中的文件/var/log。(通过>>2>&1。)

有没有办法使该日志文件旋转?(最大大小,然后切换到其他文件,仅保留有限数量的文件)

我已经看到了一些有关该logrotate程序的答案,听起来不错,但它们似乎也集中在内部生成日志文件并处理HUP信号的程序上。有没有办法通过基本的输出重定向脚本来实现此目的?


1
您为什么不能只修改重定向输出以包含旋转逻辑的脚本?
2011年

我可以,如果有人可以告诉我如何检测日志文件的大小并在不影响该进程的情况下,将其从一个进程的标准输出下旋转出来。我不必须使用logrotate,如果有更好的选择,这只是听起来像一个方便的起点进行讨论。
Miral

2
您不必使用logrotate,但是使用logrotate可以节省时间...通常,重新设计轮子没有什么意义。
bubu

就是我的意思。那么,有没有办法使logrotate与正在进行的进程的重定向标准输出一起工作?
Miral

Answers:


44

或者,您可以通过设计用于主要目的是维护大小上限,自动轮换的日志文件集的工具传递输出,例如:

  • multilogdaemonsteins的Dan Bernstein
  • multilog来自daemontools-encore的Bruce Guenter's
  • Laurent Bercot s6-log来自S6的
  • Gerrit Pape svlogd来自runit
  • 韦恩·马歇尔(Wayne Marshall)的tinylog演员
  • cyclog来自nosh

用于处理multilog格式日志文件集的工具包括:

进一步阅读


1
谢谢,multilog看起来就像我需要的。
Miral

multilog似乎是debian中唯一的即插即用解决方案(daemontools具有官方软件包)。但是在我的特定情况下,我想将日志存储在fat32分区上,因此旋转不起作用,因为多日志想使用符号链接。没有即插即用的功能:)
Arnout

事实并非如此,因为multilog没有地方会创建或要求符号链接。对他们而言,这完全是中立的。
JdeBP '18

“本世纪不使用logrotate或newsyslog”的URL带有额外的点
duyue,

15

rotatelogsapache附带的工具(在bindir中)(请参阅docs)从stdin获取输入,并在经过特定时间后旋转日志


14

如果可以将其转到标准日志流之一(syslog,daemon,cron,用户,安全性,邮件等),则可以使用logger命令并通过管道传递给它。

echo "Hello." | logger -p daemon.info

否则,您最好将记录的内容传递到自定义程序或脚本以对其进行处理,或者着眼于设置logrotate配置。

编辑:JdeBP的答案似乎有您想要的东西。


2
为简单起见,+ 1。顺便说一句,您还可以配置自定义工具(local0)而不是标准工具(示例中的守护程序)
Roger Keays 2012年

14

我有类似的问题,最初放弃了logrotate,但事实证明logrotate可以做到这一点,关键指令是“ copytruncate ”。由于某种原因,这个词在我进行的所有谷歌搜索中都没有出现,因此我添加了此答案以明确说明在这种情况下如何使用它。

诀窍是,当重定向使用“ >> ”(追加)而不是“ > ”(创建)完成时,此方法才有效

配置文件(truncate.cfg):

/tmp/temp.log {
    size 10M
    copytruncate
    rotate 4
    maxage 100
}

测试程序(永不放弃文件)。您可以看到它正在填充磁盘,尽管删除日志文件似乎可以正常工作,但实际上并不会释放磁盘上的任何空间:

cat /dev/urandom >> /tmp/temp.log

运行日志轮换:

logrotate truncate.cfg

这是一个很好的理论,但是它实际上不适用于我尝试过的任何系统。该文件实际上并没有被截断,程序仍像以前一样继续添加到该文件。(是的,即使通过>>进行重定向也是如此。)((顺便说一句,这个答案已经在前面给出了。))
Miral

1
…如logrotate中所述,不会截断原始文件(在我们的Unix&Linux站点上)。同样,echo /dev/urandom >> /tmp/temp.log将向其中写入13个确定性字符/tmp/temp.log,然后立即退出。你是说cat /dev/urandom
G-Man说'Resstate Monica'2014/

2
刚刚在这里测试,它似乎可以工作。文件内容被复制到新的日志文件。原始文件被进程保持打开状态并被截断(大小现在显示为0)。
菲利普

1
请注意使用copytruncate可能会丢失数据。
wanghq

1
+1尽管“请注意,复制文件和截断文件之间的时间间隔非常短,所以可能会丢失一些日志记录数据。”
塔加尔

3

那么,有没有办法使logrotate与正在进行的进程的重定向标准输出一起工作?

是! 查看logrotate提供的“ copytruncate”指令。指定该值指示logrotate处理这种情况:一个简单的程序,可无限期地保持其日志文件打开。

在您遇到的情况中,一个警告可能会或可能不会成为问题:

请注意,复制文件和截断文件之间的时间间隔非常短,因此可能会丢失某些日志记录数据。

有趣的是,我已经看到一些“真实世界”的日志源,它们确实鼓励用户应用此指令。这里对此选项进行一些讨论。


3

使用split,它是coreutils的一部分。它可以使用stdin并将其分成多个块(基于块大小或行数等)。

例:

app | split --bytes 1G - /var/logs/put-prefix-here

注意破折号(-)指示“分割”使用stdin代替文件。


您能否扩大答案以描述该如何做?谢谢。
fixer1234

刚刚用示例更新了我的回复。
纳扎尔

1G是任意大小,之后会启动一个新文件吗?
fixer1234

1
这并不是对该问题特别好的解决方案,因为这意味着您可以在一个文件中得到一半的消息,而在下一个文件中得到一半的消息。如果机器崩溃而split将数据存储在可能很大的缓冲区中,则还有数据丢失的风险。鉴于有多种工具可以正确解决此问题,所以我认为完全不建议使用这种自行解决方案。
David Richerby 2015年

1
@David Richerby-为未缓冲添加-u怎么样?
尼克

3

我喜欢multilog我的用例,但是我的用例是如此简单/简单,以至于我发现的文档/示例中并没有非常简单地列出它。这是一个简单的多日志旋转示例:

mkdir /tmp/myapp
./myapp | multilog t s10000 n5 '!tai64nlocal' /tmp/myapp 2>&1

一些注意事项:

  • 此转储日志到该/ tmp / myapp /目录
  • s10000代表10,000个字节*
  • n5代表5个文件。*“当前”日志计为文件之一,因此其中包括4个较旧的日志+“当前”日志
  • 它基于FrançoisBeausoleil在以下网址提供的示例:http//blog.teksol.info/pages/daemontools/best-practices
  • 我不了解许多选项-我请您参考各种文档来扩展此功能...
  • 文档警告:"Note that running processor may block any program feeding input to multilog."“处理器”是'!tai64nlocal'命令的一部分

*对于许多应用来说,这些都是长期使用的不佳选择。它们确实使您能够比大型日志更快地观察填充和旋转日志的行为。

最后,如果需要,别忘了nohup!使用nohup,您不需要2>&1(s = 10e6和n = 30):

mkdir -p /tmp/myapp
nohup ./myapp | multilog t s10000000 n30 '!tai64nlocal' /tmp/myapp &

该命令应该使您入门。


1

我只想补充以上的Sam Hendley的评论:

诀窍是,仅当重定向使用>>(append)而非>(create)完成时,此方法才有效。

我遇到了一个相同的问题,即如果使用>(创建)原始文件只是保持增长,但是如果使用>>(附加),则Logrotate copytruncate可以很好地工作并达到预期的效果。原始文件回退到零字节,程序继续写入。

将STDOUT和STDERR重定向到旋转日志文件:

  1. some-program.sh >> /tmp/output.txt 2>&1 &
  2. /etc/logrotate.d在我的情况下,在名为what_output_roll的目录下创建一个logrotate配置文件。

    针对我的情况的示例配置:

    /tmp/output.txt {
        notifempty
        missingok
        size 1G
        copytruncate
        start 0
        rotate 15
        compress
    }
    
  3. /etc/crontab文件中设置您的cron作业

    *  *  *  *  * root /usr/sbin/logrotate /etc/logrotate.d/output_roll
    

    这将每分钟检查一次文件。您可以根据自己的需要进行调整。

  4. 启动它:

    $> service crond restart
    
  5. 而已

注意:我也将SELinux设置为,SELINUX=enforcing因此将其设置为SELINUX=disabled


1

我这个周末写了一个logrotee。如果我已阅读@JdeBP的出色答案和,我可能不会multilog

我专注于它是轻量级的,并且能够bzip2其输出块,例如:

verbosecommand | logrotee \
  --compress "bzip2 {}" --compress-suffix .bz2 \
  /var/log/verbosecommand.log

不过,还有很多工作要做和测试。

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.