有一个 apache 进程,它记录到访问和错误日志中。这两个日志文件已被删除,但 apache 进程尚未重新启动或重新加载,因此它仍然有这些日志文件的打开文件句柄。
我可以通过从目录中读取文件句柄来访问文件内容/proc
:
$ sudo lsof +p 30304
...
rotatelog 30304 root 4w REG 251,0 22480405 265346 /var/log/httpd/error_log-2014-09-11 (deleted)
如果我检查该进程的文件句柄,我可以看到该文件:
$ ls -l /proc/30304/fd
...
l-wx------ 1 root root 64 2014-09-11 10:18 4 -> /var/log/httpd/error_log-2014-09-11 (deleted)
我还可以看到该文件的 inode:
$ ls -i /proc/30304/fd/4
1936760177 /proc/30304/fd/4
我可以复制此文件以获取当前内容,但任何未来的日志消息都不会出现在复制的文件中。有没有办法创建具有该 inode 编号的文件?
这就像用来ln
创建文件的硬链接,但没有现有的文件可以引用。
答案1
你做有一个现有的文件可以引用—— 中的那个/proc/30304/fd
。使用它有点棘手,因为常规 link() 拒绝接受它。您需要使用链接()。
编写一个小的 C 程序。输入以下内容foo.c
:
#include <fcntl.h>
#include <err.h>
int main(int argc, char *argv[]) {
char *src, *dstdir, *dstname;
int dirfd, r;
if (argc < 4)
errx(2, "not enough parameters");
src = argv[1]; dstdir = argv[2]; dstname = argv[3];
dirfd = open(dstdir, O_DIRECTORY);
if (dirfd < 0)
err(1, "open(%s) failed", dstdir);
r = linkat(AT_FDCWD, src, dirfd, dstname, AT_SYMLINK_FOLLOW);
if (r < 0)
err(1, "linkat(%s, %s/%s) failed", src, dstdir, dstname);
return 0;
}
运行如下:
make foo
./foo '/proc/30304/fd/4' '/var/log' 'recovered.log'