如何只保留日志文件的最后 n 行?

dr_*_*dr_ 38 logs tail text-processing

我写的一个脚本做了一些事情,最后,在它自己的日志文件中附加了一些行。我只想保留日志文件的最后 n 行(比如 1000 行)。这可以在脚本的末尾以这种方式完成:

tail -n 1000 myscript.log > myscript.log.tmp
mv -f myscript.log.tmp myscript.log
Run Code Online (Sandbox Code Playgroud)

但是有更干净优雅的解决方案吗?也许通过单个命令完成?

par*_*ark 43

这是可能的,但正如其他人所说,最安全的选择是生成一个新文件,然后移动该文件以覆盖原始文件。

下面的方法将行加载到 BASH 中,因此根据来自 的行数tail,这将影响本地 shell 用于存储日志行内容的内存使用情况。

如果空行存在于日志文件的末尾(由于 BASH 评估的行为"$(tail -1000 test.log)"),以下内容还会删除空行,因此不会在所有情况下提供真正 100% 准确的截断,但根据您的情况,可能就足够了。

$ wc -l myscript.log
475494 myscript.log

$ echo "$(tail -1000 myscript.log)" > myscript.log

$ wc -l myscript.log
1000 myscript.log
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案具有竞争条件。如果你不走运,重定向到文件发生在读取文件之前,你最终会得到一个空文件。 (2认同)

Joh*_*024 29

该实用程序sponge专为这种情况而设计。如果你安装了它,那么你的两行可以写成:

tail -n 1000 myscript.log | sponge myscript.log
Run Code Online (Sandbox Code Playgroud)

通常,在写入文件的同时读取文件是不可靠的。 sponge通过myscript.logtail完成读取并终止管道之后才写入来解决此问题。

安装

sponge在类似 Debian 的系统上安装:

apt-get install moreutils
Run Code Online (Sandbox Code Playgroud)

sponge在 RHEL/CentOS 系统上安装,请添加 EPEL 存储库,然后执行:

yum install moreutils
Run Code Online (Sandbox Code Playgroud)

文档

来自man sponge

sponge读取标准输入并将其写出到指定的文件。与 shell 重定向不同,sponge它在写入输出文件之前吸收所有输入。这允许构建读取和写入同一文件的管道。

  • +1 谢谢,我不知道`海绵`。对于所有那些学习了你不能做`sort importantfile.txt > importantfile.txt` 的艰难方法的人来说非常有用:) (3认同)
  • 绝妙的解决方案。工作起来就像一个魅力。 (3认同)

JJo*_*oao 5

绝对“tail + mv”要好得多!但是对于 gnu sed 我们可以尝试

sed -i -e :a -e '$q;N;101,$D;ba' log
Run Code Online (Sandbox Code Playgroud)

  • 愿意解释一下这个魔法到底是为谁做的吗?谢谢。 (4认同)