“作業”顯示不再存在的程序正在執行
我在後台從 bash 執行一個長時間執行的管道:
find / -size +500M -name '*.txt' -mtime +90 | xargs -n1 gzip -v9 &
管道的第二階段需要很長時間才能完成(幾小時),因為有幾個大文件+舊文件。
相反,管道的第一部分立即完成,並且由於管道未滿,並且已經完成,因此
find
成功退出。父
bash
程序似乎wait
適合子程序。我可以告訴這一點,因為沒有
find
(pid 20851)根據以下任一方式執行:ps alx | grep 20851 pgrep -l find
沒有殭屍程序,也沒有任何程序 ID
20851
可以在系統上的任何位置找到。內置的 bash
jobs
正確地將作業顯示為一行,沒有任何程序 ID:[1]+ Running find / -size +500M -name '*.txt' -mtime +90 | xargs -n1 gzip -v9 &
OTOH:我偶然發現了一個單獨的作業控制命令 (
/bin/jobs
),它顯示:[1]+ 20851 Running find / -size +500M -name '*.txt' -mtime +90 20852 Running | xargs -n1 gzip -v9 &
並且(錯誤地)將已經退出的
20851
查找過程顯示為“正在執行”。這是在 CentOS(編輯:更準確地說:
Amazon Linux 2 AMI
)Linux 上。原來這/bin/jobs
是一個兩行/bin/sh
腳本:#!/bin/sh builtin jobs "$@"
這讓我很驚訝。從另一個程序()開始的單獨程序如何
sh
知道由另一個(bash
)管理的程序在該程序已經完成並退出並且不是殭屍之後的詳細資訊?
pid
進一步:當系統上的其他方法(ps
,pgrep
)不能時,它如何知道有關已退出程序的詳細資訊(包括)?編輯:
(1) 正如比利叔叔在評論中指出的那樣,在這個系統上
/bin/sh
和/bin/bash
是相同的(/bin/sh
是一個符號連結/bin/bash
),但是/bin/jobs
是一個帶有 shebang 行的腳本,所以它在一個單獨的程序中執行。(2) 另外,感謝比利叔叔:一種更簡單的複制方法。
/bin/jobs
是一條紅鯡魚。我錯誤地認為它是產生輸出的那個。jobs
使用以下命令呼叫時,令人驚訝的輸出顯然來自內置 bash-l
:$ sleep 1 | sleep 3600 & [1] 13616 $ jobs -l [1]+ 13615 Running sleep 1 13616 Running | sleep 3600 & $ ls /proc/13615 ls: cannot access /proc/13615: No such file or directory
因此程序 13615 不存在,但被 bash 內置作業控制顯示為“正在執行”,這看起來像
jobs -l
.讓我覺得它一定是罪魁禍首(它不是)的存在
/bin/jobs
似乎令人困惑和可疑。我相信它應該從系統中刪除,因為它是無用的(sh
在單獨的程序中執行的腳本,無論如何都不能顯示呼叫者的工作)。
FWIW,我可以通過以下方式重現您的案例:
rhel8$ /bin/jobs(){ jobs -l; } rhel8$ sleep 1 | sleep 3600 & [1] 2611 rhel8$ sleep 2 rhel8$ jobs [1]+ Running sleep 1 | sleep 3600 & rhel8$ /bin/jobs [1]+ 2610 Running sleep 1 2611 Running | sleep 3600 & rhel8$ pgrep 2610 <nothing!> rhel8$ ls /proc/2610 ls: cannot access '/proc/2610': No such file or directory rhel8$ /bin/jobs [1]+ 2610 Running sleep 1 2611 Running | sleep 3600 & rhel8$ cat /bin/jobs #!/bin/sh builtin jobs "$@"
或與(甚至比以前更薄):
rhel8$ unset -f /bin/jobs rhel8$ export JOBS=$(jobs -l) rhel8$ builtin(){ echo "$JOBS"; } rhel8$ export -f builtin rhel8$ /bin/jobs [1]+ 2610 Running sleep 1 2611 Running | sleep 3600 & rhel8$ type /bin/jobs /bin/jobs is /bin/jobs
注意:如前所述,
jobs -l
在 bash 中顯示的是陳舊資訊,已經退出的管道程序仍顯示為Running
. 恕我直言,這是一個錯誤——zsh、ksh 或 yash 等其他 shell 正確地將它們顯示為Done
.