我正在尝试寻找一种简单的方法来附加/写入日志,同时将日志修剪到合理的大小。我不希望只是永远附加文件,然后必须有一个清理日志脚本。我无法理解如何在不使用第二个文件作为临时文件的情况下优雅地完成此操作。
我看过的参考资料:
我已经阅读了高级脚本指南 http://tldp.org/LDP/abs/html/io-redirection.html
两个命令的组合输出: Bash - 如何将两个命令输出到文件?
理想情况下我会有类似的东西(我知道这不起作用)
(tail-n 1000 foo.log; ./foo.sh) > foo.log
它将保留我正在进行的日志的最后 1000 行,然后为 foo.sh 的当前运行附加新的输出。
我想不出一种方法来使用附加重定向>>并限制原始文件,而无需将对 foo.sh 的调用包装在其他 bar.sh 中
tail -n 1000 foo.log > tmp.log
mv tmp.log foo.log
./foo.sh >> foo.log
这看上去很笨重。
也许我的答案是让 foo.sh 不要依赖 STDOUT 作为发送日志消息的地方,而是直接打开文件。
后续编辑:
主流意见认为不建议这么做。我很欣赏这种观点。但是,发生这种情况的服务器不在我的控制范围内,也不会真正处于....警惕的管理员的管理之下。这是一个由许多不同组拥有部分内容的盒子,但没有人对盒子的整体健康状况负责。我可以让日志永远建立,而且随着时间的推移,它可能无关紧要,但我想尽我所能控制它,因为我知道最终管理员不会做任何事情。所以,使用 crontab 来运行 logrotate 对我来说是行不通的。我只是在寻找可以用单个命令的有限点来做的事情。
答案1
如果您的版本sed
有--in-place
开关,您可以使用它。它仍然执行cp
and,mv
但它在后台,因此脚本看起来会稍微不那么混乱,这取决于您对sed
语法的感觉。否则,您的tail
(您在编辑中遗漏了一个)和附加方法是我处理它的方式。
另一种方法sed
是将日志倒置,将最新的条目放在最前面。
sed -ni '1s/^/New Entry\n/;100q;p' logfile
这就是全部内容(除了让“新条目”成为您想要的内容)。这将使滚动的 100 行日志文件按时间倒序排列。优点是您不必知道文件中有多少行(tail
会为您处理这个问题,但sed
不会)。这在某种程度上假设您的日志条目由一行组成。如果您要记录大量来自脚本的输出,我认为您应该返回tail
并附加。
另一个可能适用于详细多行输出的选项是让文件系统为您完成工作。每个日志条目都将是一个单独的文件。
#!/bin/bash
# *** UNTESTED ***
logdir="/path/to/your/log/dir"
# run the script and log its output to a file named with the date and time
script > "$logdir/$(date "+%Y%m%dT%H%M%S").log"
# maintain the logs
# keep the last 100 days of daily logfiles
# (you could keep the last 100 hours of hourly logfiles, for example,
# by using -mmin and doing some math)
# the count is intended to keep old entries from being deleted
# leaving you with nothing if there are no new entries
count=$(find "$logdir" -maxdepth 1 -type f | wc -l)
if (( count > 100 ))
then
find "$logdir" -maxdepth 1 -type f -mtime +100 -delete
fi
答案2
一般来说,我建议你不要担心日志大小。管理它的标准方法是使用 logrotate。让管理员决定他们想要的日志大小。我认为,成为一个好的 *nix 应用程序的一部分就是坚持通用标准,当应用程序做一些不寻常的事情时,人们会生气。
答案3
这是不明智的,因为没有办法在不重写整个文件的情况下删除文件的第一行。根据文件大小,这是一项密集操作。即使你确实想这样做,执行此操作的两种方法(就地查找或取消链接、重新创建)也会导致 tail 看不到新行或认为所有行都是新的。
答案4
以下是一篇类似的帖子,它为我提供了两个很好的答案:将日志文件变成一种循环缓冲区
我也遇到了同样的问题,我很高兴使用ulogbufd。