如何在日志文件中保留最后 50 行

dor*_*and 26 command-line logs tail

我尝试在我的文件中保留最后 50 行,每分钟保存一次温度。我使用了这个命令:

tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test
Run Code Online (Sandbox Code Playgroud)

但结果是空的测试文件。我想,它会列出测试文件的最后 50 行并将其插入到测试文件中。当我使用此命令时:

tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test2
Run Code Online (Sandbox Code Playgroud)

它工作正常。test2 文件中有 50 行。

有人能解释一下问题出在哪里吗?

Rah*_*hul 33

问题是您的 shell 在运行命令之前设置了命令管道。这不是“输入和输出”的问题,而是文件的内容在 tail 运行之前就已经消失了。它是这样的:

  1. shell 打开>输出文件进行写入,截断它
  2. shell 设置为将文件描述符 1(用于标准输出)用于该输出
  3. 外壳执行tail.
  4. tail运行,打开/home/pi/Documents/test并在那里找不到任何东西

有多种解决方案,但关键是要了解问题、实际出现的问题以及原因。

这将产生你正在寻找的东西,

echo "$(tail -n 50 /home/pi/Documents/test)" > /home/pi/Documents/test
Run Code Online (Sandbox Code Playgroud)

解释 :

  • $() 被称为执行的命令替换 tail -n 50 /home/pi/Documents/test
  • 引号保留输出中的换行符。
  • > /home/pi/Documents/test将输出重定向echo "$(tail -n 50 /home/pi/Documents/test)"到同一个文件。


iob*_*der 9

文件重定向首先清除文件的另一种解决方案是spongemoreutils包中使用,如下所示:

tail -n 50 /home/pi/Documents/test | sponge /home/pi/Documents/test
Run Code Online (Sandbox Code Playgroud)


clk*_*clk 6

这是因为 bash 使用第>一个处理重定向,删除文件的内容。然后它执行命令。如果您使用>>,最后 50 行将附加到文件中当前内容的末尾。在这种情况下,您将重复两次相同的 50 行。

该命令在重定向到其他文件时按预期工作。这是将文件的最后 50 行写入同名文件的一种方法:

tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 && mv /home/pi/Documents/test2 /home/pi/Documents/test
Run Code Online (Sandbox Code Playgroud)

这首先将最后 50 行写入临时文件,然后将其移动mv以替换原始文件。

如评论中所述,如果文件仍处于打开状态,这将不起作用。移动文件还会创建一个新的 inode,并且可能会更改所有权和权限。使用临时文件执行此操作的更好方法是:

tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 ; cat /home/pi/Documents/test2 > /home/pi/Documents/test
Run Code Online (Sandbox Code Playgroud)

临时文件也可以删除,但每次发生这种情况时,其内容都会被覆盖。


cas*_*cas 5

printf '%s\n' '1,$-50d'   w | ed -s /home/pi/Documents/tes
Run Code Online (Sandbox Code Playgroud)

printf用于将命令(每行一个)通过管道传输到ed. 命令ed是:

  • 1,$-50d -- 删除除最后 50 行以外的所有行
  • w -- 将修改后的文件写回磁盘

不涉及重定向,因此 shell 在读取输出文件之前无法覆盖它。

此外,与大多数形式的“就地”编辑(通常仅通过创建临时文件然后在原始文件上重命名来模拟“就地”编辑)不同,ed实际上编辑了原始文件 - 因此它保留相同的索引节点(以及所有者、组和权限 - tempfile + mv 将始终更改 inode,并可能根据情况更改其他内容)。