0

我在两个单独的终端上做了以下操作:

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 -flsof返回空输出:

└──> 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,所以我可以杀死它并且日志文件将停止增长。

我的问题是:

  1. 为什么不lsof显示(即使重复发出)实际正在写入日志文件的进程?我知道 20604 属于bash并且不是 bash 直接写入文件,而是 child date。但是lsof没有显示 也bash没有date
  2. 如果我不知道 PID 20604 怎么办?那么如何跟踪写作过程呢?

PS:使用的shell:GNU bash,版本 4.2.37(1)-release (x86_64-pc-linux-gnu)

4

1 回答 1

2

这里有一个异步采样形式的经典工程问题。

本质上,每等待很长一段时间,一个进程都会很快启动,写入文件,然后死掉。

与此完全异步,您运行lsof它来查找打开的文件 - 但仅在某个时刻有效,在写入文件时可能不匹配。(实际上,lsof执行多步操作,但可能只有一次机会抓住任何给定的作家)。

如果你在一个循环中运行了足够多的时间,你可能会很容易地认为lsof,你最终会抓住作者的行为——也许你会的。但是,根据您系统的调度程序和 I/O 功能的工作方式,写入过程可能非常短暂,以至于在此期间没有任何机会运行另一个进程。

如果您想要一个可以在实际操作中捕捉到的版本,请继续在带括号的子shell 中按时间间隔生成,但要使编写操作保持一致:

(while true; do date ; sleep 1; done) > log &

或者,如果您想尝试捕捉短暂的事件,您可以查看inotify机制(您可以查看其文档man inotify)请记住,没有演员的身份,当演员像这样短暂存在时,您可以'然后去进行lsof类型搜索以找出它是谁。

于 2015-05-07T17:43:35.307 回答