为什么 pgrep 找不到通过 env 启动的脚本?

ter*_*don 5 bash ps process-management env

例如:

$ cat foo.sh
#!/usr/bin/env bash
while true; do sleep 1 ; done
$ ./foo.sh &
$ pgrep foo.sh
$
Run Code Online (Sandbox Code Playgroud)

对比:

$ cat bar.sh
#!/bin/bash
while true; do sleep 1 ; done
$ ./bar.sh &
$ pgrep bar.sh
21202
Run Code Online (Sandbox Code Playgroud)

由以下命令启动的进程env bash显示在输出中ps aux

terdon 4203  0.0  0.0  26676  6340 pts/3    S    17:23   0:00 /bin/bash
Run Code Online (Sandbox Code Playgroud)

而开头的/bin/bash显示为

terdon  9374  0.0  0.0  12828  1392 pts/3    S    17:27   0:00 /bin/bash ./bar.sh
Run Code Online (Sandbox Code Playgroud)

这可能解释了为什么它第一个没有被 捕获pgrep。所以,问题是:

  • 为什么调用时不显示脚本名称env
  • 是否pgrep简单地解析 的输出ps
  • 有什么办法可以解决这个问题,以便pgrep可以向我显示通过 启动的脚本env吗?

slm*_*slm 5

问#1

\n\n
\n

为什么通过 env 调用时不显示脚本名称?

\n
\n\n

来自shebang 维基百科文章

\n\n
\n

在类 Unix 操作系统下,当带有 shebang 的脚本作为程序运行时,程序加载器会将脚本初始行的其余部分解析为解释器指令;而是运行指定的解释器程序,并将尝试运行脚本时最初使用的路径作为参数传递给它。

\n
\n\n

因此,这意味着脚本的名称是内核所知道的进程名称,但是在调用它之后,加载程序立即执行参数#!脚本的其余部分传递给作为一个论点。

\n\n

env不这样做。当它被调用时,内核知道脚本的名称,然后执行envenv然后搜索$PATH寻找可执行文件来执行。

\n\n\n\n

然后env执行解释器。它不知道脚本的原始名称,只有内核知道这一点。在此刻env正在解析文件的其余部分并将其传递给刚刚调用的解释器。

\n\n

问#2

\n\n
\n

pgrep 是否简单地解析 ps 的输出?

\n
\n\n

是的,有点。ps它调用正在使用的相同 C 库。它不仅仅是一个包装ps.

\n\n

问#3

\n\n
\n

有什么办法可以解决这个问题,以便 pgrep 可以向我显示通过 env 启动的脚本吗?

\n
\n\n

我可以在中看到可执行文件的名称ps

\n\n
$ ps -eaf|grep 32405\nsaml     32405 24272  0 13:11 pts/27   00:00:00 bash ./foo.sh\nsaml     32440 32405  0 13:11 pts/27   00:00:00 sleep 1\n
Run Code Online (Sandbox Code Playgroud)\n\n

在这种情况下你可以使用pgrep -f <name>来查找可执行文件,因为它将搜索整个命令行参数,而不仅仅是可执行文件。

\n\n
$ pgrep -f foo\n32405\n
Run Code Online (Sandbox Code Playgroud)\n\n

参考

\n\n\n