我在 /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.txt
或echo -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 并看看是否有任何不同。
更多猜测:
正常文件锁定:
是否有其他进程对该文件拥有独占锁?您可以使用以下方法之一找到它们:
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 检查。由于有一个进程具有非独占锁,因此无论硬链接如何,都不可能有另一个进程具有独占锁。扩展属性:
此文件是否有任何扩展属性,例如仅附加?您可以使用它来检查
lsattr /tmp/c3600_router_log.txt
并在输出中查找a
。可能还有其他扩展属性会导致您看到的行为,例如 ACL。您可以使用 检查 ACL
getfacl /tmp/c3600_router_log.txt
。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
意义