我在两个不同的终端上做了以下行动:
1s术语:
启动在后台写入文件的进程:
└──> while true; do date >> log; sleep 1; done &
[1] 20604
获取在后台运行的最后一个进程的PID:
└──> echo $!
20604
第二学期:
显示正在写入的文件的内容:
└──> tail -f log
Thu May 7 18:48:20 CEST 2015
Thu May 7 18:48:21 CEST 2015
Thu May 7 18:48:22 CEST 2015
Thu May 7 18:48:23 CEST 2015
Thu May 7 18:48:24 CEST 2015
Thu May 7 18:48:25 CEST 2015
Thu May 7 18:48:26 CEST 2015
Thu May 7 18:48:27 CEST 2015
第一学期:
检查谁在访问该文件(请注意,只有读者)
└──> lsof log
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
tail 21038 wakatana 3r REG 8,1 5340 797966 log
关注kill
后,第二个终端上的tail -f
终止并且lsof
返回空输出:
└──> kill 21038
└──> lsof log
└──>
第二学期:
然后我再次启动tail -f
,我看到数据仍然写入日志文件。这意味着某些进程仍在写入日志文件:
└──> tail -f log
Thu May 7 18:52:33 CEST 2015
Thu May 7 18:52:34 CEST 2015
Thu May 7 18:52:35 CEST 2015
Thu May 7 18:52:36 CEST 2015
Thu May 7 18:52:37 CEST 2015
Thu May 7 18:52:38 CEST 2015
Thu May 7 18:52:39 CEST 2015
Thu May 7 18:52:40 CEST 2015
在这种情况下,我实际上知道正在写入文件的进程的神秘PID,它是PID 20604所以我可以杀死它并且日志文件将停止增长。
我的问题是:
lsof
没有显示(即使重复发出)实际写入的进程
日志文件?我知道20604属于bash
并且它不是直接写入文件的bash,而是它的子date
。但lsof
既未显示bash
也未显示date
。PS:使用的shell:GNU bash,版本4.2.37(1)-release(x86_64-pc-linux-gnu)
答案 0 :(得分:2)
这里有异步采样形式的经典工程问题。
基本上,每隔一段很长的等待时间,一个进程将很快旋转,写入文件,然后死掉。
完全异步,你运行lsof
寻找开放文件 - 但只在一个时刻有效,在编写文件时可能不匹配。 (实际上,lsof
执行了多步操作,但可能只有一次机会来捕获任何给定的编写者。)
如果你在一个循环中运行lsof
足够的次数,你最终会在行为中抓住作者 - 也许你会这样做,这可能很诱人。但是,根据系统的调度程序和I / O功能的工作方式,编写过程可能非常简短,因为在此过程中永远不会有其他进程运行。
如果你想要一个你可以在行为中捕获的版本,继续在带括号的子shell中使时间间隔,但是使写入一致的操作:
(while true; do date ; sleep 1; done) > log &
或者,如果您想尝试捕捉简短事件,可以查看inotify
机制(您可以使用man inotify
查看其文档)请记住,没有演员的身份证明当演员这样短暂的时候,你就不能再进行lsof
类型搜索来找出它是谁。