恢复打开的文件

恢复打开的文件

我有一个有趣的问题,可能有也可能没有解决方案,但如果可能的话我很想有一个:

在 Solaris 上,已删除打开的日志文件,该文件在进程运行时仍会继续填充,但现在所有其他工具(如 、 等)都无法访问该cat文件tail

有没有办法在一切保持运行的情况下将目录中的条目恢复到该文件?

答案1

这是可行的,但有一些黑客攻击和限制(您需要 root 权限)。

首先找到哪个文件描述符正在使用应用程序写入日志文件,然后在先前的日志文件位置创建一个符号链接并指向文件 /proc 条目,例如:

ln -s /var/tmp/file.log /proc/12345/fd/3

第一个限制是,如果文件仅打开以供进程写入,则其权限将不允许非特权用户读取其内容。但是,root 和具有 file_dac_read 权限的用户不会受到影响。或者,您可以使用一个过程来复制文件内容,tail就像吉尔斯在他的评论中建议的那样。例如:

tail -c +1 -f /proc/12345/fd/5 > /var/tmp/file.log

第二个问题是,当进程关闭或退出时,整个文件内容将丢失 ( ln -s) 或部分 ( )。tail -c 1 -f

解决方法是使用一个程序来监视此事件并在实际调用 close 之前备份文件。

完成这项工作的可能工具有 dtrace、truss、mdb 或 dbx。

以下是在 Solaris 10 上使用 dtrace 的概念证明。

#!/bin/ksh
#
# This dtrace script is monitoring a file descriptor for a given process
# and copy its content to the given path when the file is closed.
#

pid=${1:?"$0: Usage: pid fd path"}
fd=${2:?}
path=${3:?}
[[ -f $path ]] && { echo "$path exists"; exit 1; }
dtrace -w -n '
syscall::close:entry
/pid=='$pid' && arg0=='$fd'/
{
        stop();
        system("cp /proc/%d/fd/%d %s",pid,arg0,"'"$path"'");
        system("prun %d",pid);
        exit(0);
}'

相关内容