为什么这个日志文件在截断之后不为空?

在进程( Dynamips )使用的/ 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 cat /dev/null >| c3600_router_log.txtecho -n "" >| 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# 

如何解释这种行为? 在某些情况下,无法清除进程正在使用的文件的内容?

现在知道你已经设置了noclobber (并阅读了manpage),你在上面做的事情看起来是正确的。 我会寻找其他的原因。

你可以尝试截断文件使用另一种方法,如vim或简短的perl脚本? 这不是一个解决scheme,只是希望确定是否是引起故障或文件系统的bash。 如果我们很幸运,也许你会从其中一个错误信息。

它看起来不像bash命令的退出状态是有用的。 在关于文件系统错误的bash退出状态中没有具体的东西。

或者,你可以尝试closuresnoclobber ,看看它是否开始正常行为。 这将确认noclobber是问题。

此外,请尝试closuresDynamips,看看是否有任何区别。

还有更多的猜测:

  1. 正常的文件locking:

    另一个进程对该文件有独占锁吗? 你可以用下面的一个find它们:

    • fuser /tmp/c3600_router_log.txt
    • lsof /tmp/c3600_router_log.txt
    • ls -i /tmp/c3600_router_log.txt后跟grep <inode> /proc/locks

    我不希望这件事发生。 您的lsof输出显示该文件只能由一个进程打开,而不能使用排它锁。 如果该文件有硬连接,则可以通过不同的文件path以另一个进程打开。 以上方法由inode检查。 由于有一个非独占锁的进程,所以不pipe有没有硬链接,都不能有另一个独占锁。

  2. 扩展属性:

    你有这个文件的扩展属性,如只附加? 你可以使用lsattr /tmp/c3600_router_log.txt来检查,并在输出中查找。 可能有其他扩展属性可能会导致您所看到的行为,如ACL。

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

  3. SELinux的:

    你正在运行SELinux(或可能AppArmor)? 您可以使用ls -Z /tmp/c3600_router_log.txtps Z来检查SELinux上下文字段。 我对AppArmor不够熟悉,以确保最好的方法,但它似乎是aa-complain /etc/apparmor.d/*会导致任何将被阻止logging和允许。

select最适合您的环境的调查线。

如果不这样做,尝试在截断文件时在另一个会话中在shell中运行strace ,并查看处理该文件时返回的错误。

你可以> c3600_router_log.txt没有点使用pipe道后>