如何使用>>限制日志文件大小


24

如何将写入的日志文件的大小限制>>为200MB?

$ run_program >> myprogram.log

1
您要在200MB后杀死程序吗?还是您想要最后200MB的存储空间,并将旧存储桶中的所有旧存储桶存储?
亚伦·马拉斯科

不,这个过程
大卫

决定进行logrotate,感谢大家的宝贵意见
大卫

Answers:


9

如果您的应用程序(即run_program)不支持限制日志文件的大小,则可以与外部应用程序或脚本循环地定期检查文件大小。

您还可以logrotate(8)用来旋转日志,它具有size可以用于您的目的的参数:

这样,当达到指定的大小时,日志文件将旋转。大小可以字节(默认),千字节(sizek)或兆字节(sizem)指定。


1
具有重复信息的+1日志文件通常可以按数量级压缩。
用户未知

是logrotate截断文件,还是简单地复制或移动它们?因为这仅在与fd关联的文件被截断的情况下才有效。如果是mv'd,则文件将继续增长;如果未链接,则文件将保持打开状态并继续增长,直到该过程退出为止... IIRC logrotate复制,取消链接并创建新文件,这就是为什么当日志旋转后,通常必须将SIGHUP发送给恶魔的原因。
Michael Trausch

请注意,即使文件被截断,如果未在附加模式下打开文件也会出现问题(日志文件始终在附加模式下打开,但根据我的经验,通常不会打开)
Random832

一旦文件达到一定大小(每天,每周等),Logrotate就可以旋转。它也可以压缩,并且您可以使用该postscript选项将logrotate配置发送SIGHUP给程序。
laebshade 2011年

12

如果您的程序不需要编写其他任何大于此限制的文件,则可以使用将该限制通知内核ulimit。在运行命令之前,请运行以下命令为当前Shell会话中运行的所有进程设置200MB的文件大小限制:

ulimit -f $((200*1024))

这将保护您的系统,但可能会妨碍程序写入文件。如eyazici所建议,请考虑logrotate在它们达到一定大小或年龄后设置修剪修剪日志文件。您可以丢弃旧数据或在一系列压缩文件中将其存档一段时间。


这限制了程序编写的任何文件的大小
Kim

真正。如果程序有合理的需要编写其他大文件,则需要其他解决方案。
卡莱布

6

您可以创建一个新的文件系统映像,使用循环设备挂载它并将日志文件放在该文件系统上:

dd if=/dev/zero of=./200mb.img bs=1024 count=200000 # create new empty 200MB file
mkfs.ext2 200mb.img # or ext3, or whatever fits your needs
mkdir logs
sudo mount -t ext2 -o loop 200mb.img logs # only root can do '-o loop' by default
run_program >>logs/myprogram.log

tmpfs如果您有足够的内存,也可以使用而不是文件。


创意...让它决定程序用尽时的处理方式。
亚伦·马拉斯科

6

您可以使用以下命令截断输出head

size=$((200*1024*1024-$(stat -c %s myprogram.log)))
run_program | head -c ${size} >> myprogram.log

非常有创意。请注意,这仅会限制将新数据写入文件,而不会考虑文件的大小。
卡莱布

2
请注意,SIGPIPE一旦达到大小限制,这很可能会杀死带有()的程序,而不是丢弃数据。
2011年

1
我当时在想一些dd魔术,但是@ Random832是正确的,您会得到一个SIGPIPEas head/ dd/ whateverdrop。
亚伦·马拉斯科

忽略它trap '' SIGPIPE呢?
tuxce 2011年

或用管道代替{ head -c "$size" >> log; cat > /dev/null; }
斯特凡Chazelas

5

软件包apache2-utils中提供了名为的实用程序rotatelogs,它可能对您有所帮助。

概要:

rotatelogs [-l] [-L 链接名称 ] [-p 程序 ] [-f] [-t] [-V] [-e] [-c] [-n 数的-文件 ]日志文件rotationtime | 文件大小(B | K | M | G)[ 偏移量 ]

例:

your_program | rotatelogs -n 5 /var/log/logfile 1M

您可以在此链接上阅读完整手册。


该链接不存在。
亚历山大·贡奇

1

我敢肯定原始海报找到了解决方案。这是供其他人阅读的主题...

缩减限制程序输出的大小,并使用以下命令保留最后200MB的输出:

$ run_program | curtail -s 200M myprogram.log

参考文献

注意:我是上述存储库的维护者。只是分享解决方案...


我喜欢缩减的想法。我对C不那么熟悉,所以有机会为其提供二进制文件吗?或至少有关于如何安装的详细说明?
费利佩

0

由于它是文本,因此我将以您喜欢的语言编写脚本并将其传递给该脚本。让它处理文件I / O(或将其全部保存在内存中,然后将其转储到SIGHUP类似文件上)。为此,我会想到要跟踪的“合理”行数,而不是200MB。


除了能够截断数据外,仅将200MB日志数据保留在内存中并不是对系统资源的很好利用。也不对大日志文件进行行计数。我建议使用为此syslog而构建的工具logrotate
卡莱布

0

以下脚本可以完成这项工作。

LOG_SIZE=500000
NUM_SEGM=2
while getopts "s:n:" opt; do
  case "$opt" in
    s)
      LOG_SIZE=$OPTARG
      ;;
    n)
      NUM_SEGM=$OPTARG
      ;;
  esac
done
shift $((OPTIND-1))
if [ $# == 0 -o -z "$1" ]; then
    echo "missing output file argument"
    exit 1
fi
OUT_FILE=$1
shift
NUM=1
while :; do
    dd bs=10 count=$(($LOG_SIZE/10)) >> $OUT_FILE 2>/dev/null
    SZ=`stat -c%s $OUT_FILE`
    if [ $SZ -eq 0 ]; then
        rm $OUT_FILE
        break
    fi
    echo -e "\nLog portion finished" >> $OUT_FILE
    mv $OUT_FILE $OUT_FILE.n$NUM
    NUM=$(($NUM + 1))
    [ $NUM -gt $NUM_SEGM ] && NUM=1
done

它有一些明显的捷径,但总的来说,它可以满足您的要求。它将日志分割成有限大小的块,并且块的数量也受到限制。所有这些都可以通过命令行参数指定。日志文件也是通过命令行指定的。

如果将其与派生到后台的守护进程一起使用,请注意一个小陷阱。使用管道将防止守护程序进入后台。在这种情况下,有一种(可能是特定于bash的)语法可以避免该问题:

my_daemon | ( logger.sh /var/log/my_log.log <&0 & )

请注意<&0,虽然看似多余,但没有它就无法工作。

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.