Contents

从PID获取过程的名称

1. 概述

Linux 操作系统为每个进程生成一个PID 。在这个快速教程中,让我们探索如何通过给定的 PID 获取进程名称。

2. 问题介绍

像往常一样,让我们通过一个例子来理解这个问题。

首先,让我们创建一个简单的 shell 脚本来模拟一个长时间运行的进程:

$ cat long-running.sh
#!/bin/bash
echo "PID of $0: $$"
echo "Parameter: $1"
watch -n 300 date > /dev/null

正如我们所见,我们首先通过读取特殊变量*$$ 来打印当前脚本的 PID 。然后,我们告诉watch 命令每 300 秒执行一次date*命令并丢弃输出。

这样我们在启动脚本的时候就可以知道它的PID。此外,它作为一个“长期运行”的进程运行:

$ ./long-running.sh PARAM
PID of ./long-running.sh: 407203
parameter: PARAM

现在,假设我们只知道这个 PID,我们想知道哪个进程正在使用这个 PID 运行。

当然,我们预期的结果是long-running.sh脚本。接下来,让我们看看如何找到该进程。

3. 使用ps命令

ps 命令是在 Linux 命令行中检查当前进程状态的标准工具。

此外,我们可以将*-p PID选项传递给ps*命令以仅获取给定进程的信息,例如:

$ ps -p 407203 
    PID TTY          TIME CMD
 407203 pts/3    00:00:00 long-running.sh

如上面的输出所示,我们在 CMD 列中看到了预期的进程名称。我们也可以调整ps命令的*-o*选项,让 ps只输出需要的信息

例如,我们可以将“ -o comm ”传递给ps命令以仅获取程序的名称:

$ ps -p 407203 -o comm
COMMAND
long-running.sh

如果我们想知道用于启动给定进程的整个命令行,我们可以将“ -o command ”传递给ps

$ ps -p 407203 -o command
COMMAND
/bin/bash ./long-running.sh PARAM

如输出所示,这一次ps命令报告了完整的命令,包括用于启动进程的参数。

有时,我们想抑制列标题,例如上面输出中的“ COMMAND ”,以便我们可以轻松地将结果传递给其他程序进行进一步处理。

为了抑制ps输出的标题,我们可以简单地在-o ColumnName*选项 之后添加“=”字符*:

$ ps -p 407203 -o command=
/bin/bash ./long-running.sh PARAM

4. 读取*/proc/PID*目录下的文件

/proc目录存在于所有 Linux 发行版上。该目录是一个虚拟文件系统。** /proc目录包含有关进程的**详细信息和其他系统信息,例如内核、内存使用情况、CPU 数据和配置参数。操作系统在启动时挂载*/proc*。

每个进程在/proc*目录下都有一个以 PID 命名*的子目录。比如我们要查看进程407203的信息,可以进入*/proc/407203目录。每个/proc/PID*目录下都有许多“文件” 。这些文件包含有关该过程的详细信息:

$ ls /proc/407203  
arch_status	    cwd@	maps	        pagemap	      stat
attr/		     environ	mem	       personality   statm
...
exe@ ...
cmdline		     io		ns/	       sessionid     timers
comm ...

**我们可以读取三个文件来获取进程的名称或命令行:commexecmdline。**接下来,让我们看看他们的行动。

要获取进程的程序名,我们可以读取comm文件:

$ cat /proc/407203/comm
long-running.sh

exe文件是一个符号链接。它链接到真正的命令文件以启动该过程:

$ ls -l /proc/407203/exe 
lrwxrwxrwx 1 kent kent 0 Apr 26 09:20 /proc/407203/exe -> /usr/bin/bash

由于我们的进程是一个shell脚本,它总是由shell启动,所以exe文件只会链接到shell命令,在这种情况下是*/usr/bin/bash*。但是,如果我们的进程是由常规程序启动的,则exe文件将指向可执行文件:

$ ls -l /proc/437301/exe 
lrwxrwxrwx 1 kent kent 0 Apr 26 09:17 /proc/437301/exe -> /usr/bin/vim

上面的例子显示了一个vim进程。 但是,如果我们想知道启动进程的完整命令及其参数,我们可以查看cmdline文件:

$ cat /proc/407203/cmdline 
/bin/bash./long-running.shPARAM

如上面的输出所示,shell 命令、脚本名称和脚本参数被打印出来,但是它们没有分隔符连接在一起。 实际上,输出由空字符 分隔。如果我们将*-A选项(显示全部)传递给cat*命令,我们可以看到它们:

$ cat -A /proc/407203/cmdline
/bin/bash^@./long-running.sh^@PARAM^@

这一次,我们可以看到空字符表示为’ ^@ ‘。 我们可以使用tr 命令重新格式化输出。例如,我们可以用空格替换所有空字符:

$ cat /proc/407203/cmdline | tr '\0' ' '
/bin/bash ./long-running.sh PARAM