0%

Linux下获取进程的PID

Linux系统中常常需要获取进程的pid进行一些操作,而Linux 的交互式 Shell 与 Shell 脚本存在一定的差异,主要是由于后者存在一个独立的运行进程,因此在获取进程 pid 上二者也有所区别。

ps 命令

ps命令是最常用的Linux命令之一,用于获取当前系统中的进程信息,ps是显示瞬间进程的状态,并不动态连续;如果想对进程进行实时监控应该用top命令。

ps命令的参数非常多,这个可以自己找资料查看,最常用的就是ps -ef或者ps -aux了。

ps -aux表示显示所有包含其他使用者的行程,一般能够获取到比较详细的进程信息了,ps -ef也表示显示所有进程信息,连同命令行。因此如果想查找一个进程,通常这两个命令就比较全面了。

交互式 Shell 获取 pid

在ps命令的基础上,如果我们知道进程的name,那么可以利用grep来获取其pid(需要通过-v来过滤掉grep本身),并通过awk显示出来。

ps -ef | grep "name" | grep -v grep | awk '{print $2}'

或者直接使用awk

ps -ef | awk '/[n]ame/{print $2}'

这里名称首字母加[]的目的是为了避免匹配到awk自身的进程。

当然,Linux系统也支持直接查找:

  • 最简单的方法是使用pgrep

    pgrep -f name

  • 如果需要查找到 pid 之后kill掉该进程,还可以使用pkill

    pkill -f name

  • 如果是可执行程序的话,可以直接使用pidof

    pidof name

Bash Shell 脚本获取进程 pid

在使用 Shell 脚本获取进程 pid 时,如果直接使用上述命令,可能会出现多个 pid 结果,例如:

1
2
3
4
5
#! /bin/bash
# process-monitor.sh
process=$1
pid=$(ps x | grep $process | grep -v grep | awk '{print $1}')
echo $pid

执行 process-monitor.sh 会出现多个结果:

1
2
$> sh process-monitor.sh
3036 3098 3099

进一步排查可以发现,多出来的几个进程实际上是子 Shell 的(临时)进程:

1
2
3
root      3036  2905  0 09:03 pts/1    00:00:45 /usr/java/jdk1.7.0_71/bin/java ...name
root 4522 2905 0 16:12 pts/1 00:00:00 sh process-monitor.sh name
root 4523 4522 0 16:12 pts/1 00:00:00 sh process-monitor.sh name

对于这种情况,我们也只能加入更多的grep条件来做进一步的判断了

如果我们不确定找到的进程是否正确,可以通过判断pid所在的进程是否运行:

1
2
3
4
5
if ps -p $PID > /dev/null
then
echo "$PID is running"
# Do something knowing the pid exists, i.e. the process with $PID is running
fi

/dev/null是Linux中的一个特殊输出位置。