ps -o pid,ppid,stat,exe -e | grep deleted
生成如下输出:
1777 1346 Sl /usr/bin/python3.10 (deleted)
1778 1346 Sl /usr/bin/python3.10 (deleted)
1825 1327 Ss /usr/lib/bluetooth/obexd (deleted)
2007 1 Sl /usr/bin/python3.10 (deleted)
2101 1346 S /usr/bin/python3.10 (deleted)
2199 1 Sl /usr/bin/python3.10 (deleted)
371565 371305 SLl /usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/WebKitNetworkProcess (deleted)
371566 371305 SLl /usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/WebKitWebProcess (deleted)
376426 371305 SLl /usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/WebKitWebProcess (deleted)
380141 371305 SLl /usr/lib/x86_64-linux-gnu/webkit2gtk-4.0/WebKitWebProcess (deleted)
这是什么(deleted)
意思以及如何让 ps 列出路径而不附加它?
答案1
在 Linux 上,ps
通过执行readlink("/proc/<pid>/exe")
.
$ ls -l /proc/self/exe
lrwxrwxrwx 1 chazelas chazelas 0 Dec 17 10:35 /proc/self/exe -> /usr/bin/ls
该文件是一个神奇的符号链接给定进程(或其任何祖先,因为并非所有进程都执行文件)最后的文件被处决。如果文件已被删除(并且可能被新版本替换,例如软件包更新后),则 a(deleted)
会附加到 . 返回的字符串中readlink()
。该符号链接仍然可以已关注到实际删除的文件(这样它就是魔法)。
$ cp /bin/sleep .
$ ./sleep 1h &
[1] 17417
$ ls -ld "/proc/$!/exe"
lrwxrwxrwx 1 chazelas chazelas 0 Dec 17 10:38 /proc/17417/exe -> /home/chazelas/sleep*
$ rm sleep
$ ls -ld "/proc/$!/exe"
lrwxrwxrwx 1 chazelas chazelas 0 Dec 17 10:38 /proc/17417/exe -> '/home/chazelas/sleep (deleted)'
新版本sleep
:
$ cp /bin/sleep .
$ ps -o exe -p "$!"
EXE
/home/chazelas/sleep (deleted)
$ ls -ld "/proc/$!/exe"
lrwxrwxrwx 1 chazelas chazelas 0 Dec 17 10:38 /proc/17417/exe -> '/home/chazelas/sleep (deleted)'
$ ls -iLd "/proc/$!/exe" sleep
3114951 /proc/17417/exe* 3114969 sleep*
用-L
ls
下面的链接(用 代替stat()
)lstat()
就可以得到对应的i
节点号。
我们看到这是两个不同的文件(不同的索引节点号)。
$!
仍在运行旧的已删除版本sleep
,该文件在文件系统上除了那个神奇的符号链接之外没有任何路径/proc/$!/exe
。
/home/chazelas/sleep
现在是一个不同的可执行文件,因此删除它(deleted)
会是错误的,因为它会引用错误的文件。在这里,由于exe
是最后一个字段,因此您可以通过将输出通过管道传输到以下位置来删除它:
sed 's/ (deleted)$//'
$ ps -o pid,ppid,stat,exe
PID PPID STAT EXE
18928 11196 Ss /usr/bin/zsh
18943 18928 SN /home/chazelas/sleep (deleted)
18967 18928 R+ /usr/bin/ps
$ ps -o pid,ppid,stat,exe | sed 's/ (deleted)$//'
PID PPID STAT EXE
18928 11196 Ss /usr/bin/zsh
18943 18928 SN /home/chazelas/sleep
18968 18928 R+ /usr/bin/ps
18969 18928 S+ /usr/bin/sed
但同样,这将是一个谎言,因为它/home/chazelas/sleep
不是进程 18943 正在运行的可执行文件,它是另一个sleep
命令,现在无处可寻,因为自从该进程执行它以来它已被删除。
以及对应/proc/<pid>/exe
于可能执行该文件的其他进程或/proc/<pid>/fd/<fd>
在某些 fd 上打开该文件的进程,或者可能存在指向该文件的某些硬链接。