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

use*_*413 10 ubuntu

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

tail -2000 logfile.txt> logfile.txt

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

Gre*_*ill 15

tail开始阅读之前,您将覆盖该文件.shell >通过首先清除文件来处理重定向操作符.然后它运行tail,没有数据可读.

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

tail -2000 logfile.txt >logfile.tmp
mv logfile.tmp logfile.txt
Run Code Online (Sandbox Code Playgroud)

  • 是,但如果文件名与输入相同,则会覆盖它 (2认同)

mmr*_*ins 10

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

请参阅此处的手册页 或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
}
Run Code Online (Sandbox Code Playgroud)


NVR*_*RAM 10

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

要使用tail,你可以做一些事情(类似于Pantonza和Greg的想法),但通过原位截断原始文件来保留原始文件:

tail -2000 logfile.txt >logfile.tmp
cat logfile.tmp > logfile.txt
rm logfile.tmp
Run Code Online (Sandbox Code Playgroud)

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

bash -c 'X=$(tail -2000 logfile.txt);echo "$X">logfile.txt'
Run Code Online (Sandbox Code Playgroud)

在所有情况下,截断和附加到文件的进程之间可能存在竞争条件.不确定logrotate是否处理,这里没有任何尾部解决方案.


udo*_*dan 5

这是另一种解决方案,无需处理 tmp 文件:

echo "`tail -2000 logfile.txt`" > logfile.txt
Run Code Online (Sandbox Code Playgroud)