ps -o pid,ppid,stat,exe -e | ps -o pid,ppid,stat,exe -e | grep删除已将“(已删除)”附加到可执行路径

ps -o pid,ppid,stat,exe -e | ps -o pid,ppid,stat,exe -e | grep删除已将“(已删除)”附加到可执行路径
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 上打开该文件的进程,或者可能存在指向该文件的某些硬链接。

答案2

在你的附注命令,使用EXE文件您要求打印可执行文件路径的参数。

man proc会详细介绍该领域:

如果路径名已取消链接,则符号链接将包含附加到原始路径名的字符串“(deleted)”。

由于这不是一个选项(当请求显示路径时)并且您绝对需要显示路径,因此我能想到的唯一解决方案是对结果进行后处理。例如使用 sed :

ps -o pid,ppid,stat,exe -e | sed "s/(deleted)//g"

相关内容