Answers:
如果您的应用程序(即run_program
)不支持限制日志文件的大小,则可以与外部应用程序或脚本循环地定期检查文件大小。
您还可以logrotate(8)
用来旋转日志,它具有size
可以用于您的目的的参数:
这样,当达到指定的大小时,日志文件将旋转。大小可以字节(默认),千字节(sizek)或兆字节(sizem)指定。
postscript
选项将logrotate配置发送SIGHUP
给程序。
如果您的程序不需要编写其他任何大于此限制的文件,则可以使用将该限制通知内核ulimit
。在运行命令之前,请运行以下命令为当前Shell会话中运行的所有进程设置200MB的文件大小限制:
ulimit -f $((200*1024))
这将保护您的系统,但可能会妨碍程序写入文件。如eyazici所建议,请考虑logrotate
在它们达到一定大小或年龄后设置修剪修剪日志文件。您可以丢弃旧数据或在一系列压缩文件中将其存档一段时间。
您可以创建一个新的文件系统映像,使用循环设备挂载它并将日志文件放在该文件系统上:
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
如果您有足够的内存,也可以使用而不是文件。
您可以使用以下命令截断输出head
:
size=$((200*1024*1024-$(stat -c %s myprogram.log)))
run_program | head -c ${size} >> myprogram.log
SIGPIPE
一旦达到大小限制,这很可能会杀死带有()的程序,而不是丢弃数据。
dd
魔术,但是@ Random832是正确的,您会得到一个SIGPIPE
as head
/ dd
/ whatever
drop。
trap '' SIGPIPE
呢?
{ head -c "$size" >> log; cat > /dev/null; }
。
我敢肯定原始海报找到了解决方案。这是供其他人阅读的主题...
缩减限制程序输出的大小,并使用以下命令保留最后200MB的输出:
$ run_program | curtail -s 200M myprogram.log
注意:我是上述存储库的维护者。只是分享解决方案...
以下脚本可以完成这项工作。
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
,虽然看似多余,但没有它就无法工作。