为什么截断后此日志文件不为空?

为什么截断后此日志文件不为空?

我在 /tmp 目录下有一个名为 c3600_router_log.txt 的 142MiB 日志文件,该文件由一个进程使用(动态):

root@potato:/tmp# lsof | grep c3600_router_log.txt
dynamips  12369        root   15w      REG                8,8  148101336         76 /tmp/c3600_router_log.txt
root@potato:/tmp# 

我想删除此日志文件的内容。如果我使用cat /dev/null >| c3600_router_log.txtecho -n "" >| c3600_router_log.txt,则文件内容不会被删除:

root@potato:/tmp# date +%T; ls -lh c3600_router_log.txt
01:44:07
-rw-r--r-- 1 root root 142M 25. veebr 01:44 c3600_router_log.txt
root@potato:/tmp# date +%T; cat /dev/null >| c3600_router_log.txt
01:44:09
root@potato:/tmp# date +%T; ls -lh c3600_router_log.txt
01:44:11
-rw-r--r-- 1 root root 142M 25. veebr 01:44 c3600_router_log.txt
root@potato:/tmp# date +%T; ls -lh c3600_router_log.txt
01:35:47
-rw-r--r-- 1 root root 142M 25. veebr 01:35 c3600_router_log.txt
root@potato:/tmp# date +%T; echo -n "" >| c3600_router_log.txt
01:35:49
root@potato:/tmp# date +%T; ls -lh c3600_router_log.txt
01:35:50
-rw-r--r-- 1 root root 142M 25. veebr 01:35 c3600_router_log.txt
root@potato:/tmp# 

如果我使用以下选项,文件内容也不会被刷新> c3600_router_log.txt

root@potato:/tmp# date "+%T"; ls -lh c3600_router_log.txt
02:11:55
-rw-r--r-- 1 root root 189M 27. veebr 02:11 c3600_router_log.txt
root@potato:/tmp# date "+%T"; > c3600_router_log.txt
02:11:57
root@potato:/tmp# date "+%T"; ls -lh c3600_router_log.txt
02:11:58
-rw-r--r-- 1 root root 189M 27. veebr 02:11 c3600_router_log.txt
root@potato:/tmp# 

如何解释这种行为?是否存在无法刷新进程正在使用的文件内容的情况?

答案1

现在知道您已经noclobber设置好了(并且已经阅读了手册页),您上面所做的看起来是正确的。我会在其他地方寻找原因。

vim您能否尝试使用其他方法(例如短脚本)截断文件perl?这不是解决方案,只是希望确定是 bash 还是文件系统导致故障。如果我们幸运的话,也许您会从其中一个中收到一条错误消息。

看起来不像bash 命令的退出状态会很有用。bash 退出状态中没有关于文件系统错误的具体信息。

或者,您可以尝试关闭它noclobber,看看它是否开始正常运行。这将确认noclobber问题所在。

另外,尝试关闭 Dynamips 并看看是否有任何不同。

更多猜测:

  1. 正常文件锁定:

    是否有其他进程对该文件拥有独占锁?您可以使用以下方法之一找到它们:

    • fuser /tmp/c3600_router_log.txt
    • lsof /tmp/c3600_router_log.txt
    • ls -i /tmp/c3600_router_log.txt其次是grep <inode> /proc/locks

    我并不指望这能产生任何结果。您的lsof输出显示该文件仅由一个进程打开,并且没有使用独占锁。如果该文件有硬链接,则它可能由另一个进程通过不同的文件路径打开。上述方法通过 inode 检查。由于有一个进程具有非独占锁,因此无论硬链接如何,都不可能有另一个进程具有独占锁。

  2. 扩展属性:

    此文件是否有任何扩展属性,例如仅附加?您可以使用它来检查lsattr /tmp/c3600_router_log.txt并在输出中查找a。可能还有其他扩展属性会导致您看到的行为,例如 ACL。

    您可以使用 检查 ACL getfacl /tmp/c3600_router_log.txt

  3. SELinux:

    ls -Z /tmp/c3600_router_log.txt您是否正在运行 SELinux(或者可能是 AppArmor)?您可以使用和检查您的 shell 的 SELinux 上下文字段ps Z。我对 AppArmor 不够熟悉,无法确定最佳方法,但它似乎aa-complain /etc/apparmor.d/*会导致任何原本会被阻止的内容被记录下来并被允许。

选择上述最适合您环境的调查路线。

如果所有这些都失败了,请尝试strace在另一个会话中在 shell 上运行一个,同时尝试截断该文件,并查看处理该文件时返回了什么错误。

答案2

在 > 之后使用管道符毫无> c3600_router_log.txt意义

相关内容