我有一个有趣的问题,可能有也可能没有解决方案,但如果可能的话我很想有一个:
在 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);
}'