为什么“tail”不能截断日志文件?

时间:2009-11-18 22:03:52

标签: ubuntu

我正在尝试使用cron脚本管理我的日志文件大小。我基本上想要每晚删除除日志文件的最后2000行以外的所有内容。我正在尝试运行此命令,但它似乎正在清空整个文件而不是按照我的意愿执行:

tail -2000 logfile.txt> LOGFILE.TXT

有谁知道为什么这不起作用和/或如何完成我想要的东西?谢谢!

6 个答案:

答案 0 :(得分:14)

tail开始阅读之前,您正在覆盖该文件。 shell通过首先清除文件来处理>重定向运算符。然后它运行tail,无法读取数据。

您可以使用临时文件解决此问题:

tail -2000 logfile.txt >logfile.tmp
mv logfile.tmp logfile.txt

答案 1 :(得分:10)

您可能希望使用logrotate来寻找更强大的解决方案,而不是使用自己的cron文件执行此操作。您可以旋转日志,控制它们保留多长时间,通过电子邮件发送,压缩旧日志,然后根据需要运行脚本。

请参见手册页here 或者从命令行输入man logrotate

在/etc/logrotate.d/目录中创建一个新的logrotate文件。这是一个例子:

/var/logs/myapp/logfile.txt {
  # keep the 5 latest rotations of the log 
  rotate 5
  # rotate once the file is bigger than 2k
  size 2k
  # don't error if the file isn't there
  missingok
  # compress rotated (old) log files
  compress
  # set ownership and permissions on the new log file
  create 0640 myuser myuser
}

答案 2 :(得分:10)

如果进程保持日志文件打开,则接受的解决方案存在问题;你基本上需要重用i-node。 Mmrobins的反应很好, logrotate 应该做对了。

要使用,您可以执行某些操作(类似于Pantonza& Greg的想法),但通过原位截断原始文件来保留原始文件:

tail -2000 logfile.txt >logfile.tmp
cat logfile.tmp > logfile.txt
rm logfile.tmp

要避免临时文件,您可以读入变量,然后将其填充:

bash -c 'X=$(tail -2000 logfile.txt);echo "$X">logfile.txt'

在所有情况下,截断与附加到文件的进程之间可能存在竞争条件。不确定 logrotate 是否处理了这个问题, tail 解决方案都没有。

答案 3 :(得分:4)

这是另一个解决方案,不处理tmp文件:

echo "`tail -2000 logfile.txt`" > logfile.txt

答案 4 :(得分:1)

Greg Hewgill是对的,logfile.txt在tail可以工作之前被截断。

尝试:

tail -2000 logfile.txt > logfile2.txt; rm -f logfile.txt; mv logfile2.txt logfile.txt

答案 5 :(得分:1)

如果您是vim用户,则另一个选项是使用vi代替tail,直接对该文件进行操作:

vi "+execute \"normal! G2000kO\<esc>dgg\"" "+w" "+q" logfile.txt

字符串G2000kO\<esc>dgg只是用于使用vi执行此操作的键盘输入(必须转义转义按钮)。它使用非常直观,涵盖了大量的用例。

vi还可以处理大型(10+ GB)文本文件,甚至不会减慢速度,因此这种方法非常强大。