Bash Shell 获取进程 PID

转载地址:http://weyo.me/pages/techs/linux-get-pid/

根据pid,kill该进程:http://www.cnblogs.com/lovychen/p/5411391.html

导读

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

交互式 Bash Shell 获取进程 pid

在已知进程名(name)的前提下,交互式 Shell 获取进程 pid 有很多种方法,典型的通过 grep 获取 pid 的方法为(这里添加 -v grep是为了避免匹配到 grep 进程):

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

或者不使用 grep(这里名称首字母加[]的目的是为了避免匹配到 awk 自身的进程):

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

如果只使用 x 参数的话则 pid 应该位于第一位:

ps x | awk '/[n]ame/{print $1}'

最简单的方法是使用 pgrep

pgrep -f name

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

pkill -f name

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

pidof name


Bash Shell 脚本获取进程 pid

根据进程名获取进程 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 会出现多个结果:

$> sh process-monitor.sh
3036  3098  3099

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

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

其中 3036 是需要查找的进程pid,而 4522、4523 就是子 Shell 的 pid。 为了避免这种情况,需要进一步明确查找条件,考虑到所要查找的是 Java 程序,就可以通过 Java 的关键字进行匹配:

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

获取 Shell 脚本自身进程 pid

这里涉及两个指令: 1. $$ :当前 Shell 进程的 pid 2. $! :上一个后台进程的 pid 可以使用这两个指令来获取相应的进程 pid。例如,如果需要获取某个正在执行的进程的 pid(并写入指定的文件):

myCommand && pid=$!
myCommand & echo $! >/path/to/pid.file

注意,在脚本中执行 $! 只会显示子 Shell 的后台进程 pid,如果子 Shell 先前没有启动后台进程,则没有输出。


查看指定进程是否存在

在获取到 pid 之后,还可以根据 pid 查看对应的进程是否存在(运行),这个方法也可以用于 kill 指定的进程。

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
<think>好的,我现在需要帮助用户解决如何通过Shell脚本获取指定进程PID的问题。用户已经提供了一些引用内容,我需要结合这些信息来给出正确的答案。 首先,用户提到的引用[1]中有一个示例命令,使用ps、grep、awk等工具来获取进程号,同时排除了脚本自身的进程。这应该是一个常用的方法。我需要先理解这个命令的结构:ps -ef列出所有进程,然后grep匹配脚本名,接着排除grep进程本身,再用awk提取第二列的PID,最后用grep -v排除当前脚本的PID。这个方法适用于获取同名进程PID,但需要注意进程名的精确匹配,避免误杀其他进程。 然后,引用[2]提到了Shell脚本中的父子进程和子shell,这可能涉及到脚本执行时产生的子进程问题。例如,如果脚本启动了其他进程,如何正确获取这些子进程PID。但用户当前的问题主要是获取指定进程PID,可能不直接涉及父子进程,但需要考虑进程的归属问题,比如是否属于当前用户或其他用户。 引用[3]显示了一个符号链接cwd指向/proc/24176,这提示了/proc文件系统的使用。每个进程在/proc下有一个目录,其中包含进程的详细信息,比如cwd表示当前工作目录。这可能用于进一步处理获取到的PID,比如检查进程的工作目录是否符合条件。 用户的问题是如何用Shell脚本获取指定进程PID,并需要示例代码。根据引用[1]的方法,可以编写一个基本的脚本,使用ps命令结合grep过滤,但需要考虑进程名的精确匹配问题,避免因为部分匹配而获取到错误的PID。例如,如果进程名是“python”,而用户有一个进程名为“python3”,可能会导致误匹配。 因此,可能需要更精确的匹配方式,比如使用pgrep命令,或者改进grep的正则表达式。例如,在grep中使用全词匹配,如grep '[s]cript_name',这样可以避免grep自身的进程出现。不过用户提供的示例已经用grep -v来排除grep进程,这可能已经足够。 接下来,我需要给出具体的步骤和示例代码。首先,基本方法是使用ps和grep组合,然后通过awk提取PID。然后,可以介绍使用pgrep命令,这可能更简洁。同时,需要考虑处理多个进程的情况,比如将PID存储在数组中,或者循环处理每个PID。 可能的示例代码包括: 1. 使用ps -ef的方法: pid_list=$(ps -ef | grep "process_name" | grep -v grep | awk '{print $2}') 2. 使用pgrep: pid_list=$(pgrep -f "process_name") 但需要注意,pgrep的-f选项是匹配整个命令行,而默认是匹配进程名。因此,根据需求选择合适的选项。 此外,用户可能需要排除脚本自身的PID,比如当脚本名称和进程名相同时。这时候需要在命令中排除当前脚本的PID,如引用[1]中的例子,使用grep -v "$PID",其中$PID是脚本自身的进程ID。可以通过$$获取当前脚本的PID。 综合这些信息,给出一个示例脚本,展示两种方法,并提醒注意事项,比如精确匹配、处理多个PID的情况,以及使用/proc文件系统进一步验证进程信息。 最后,生成相关问题,可能涉及如何杀死进程、如何监控进程状态、处理子进程等。</think>### 如何通过Shell脚本获取指定进程PID #### 方法1:使用`ps`命令结合过滤 这是最基础的方法,通过`ps -ef`列出所有进程信息,再通过`grep`筛选目标进程名,最后用`awk`提取PID字段。需注意以下几点: 1. **排除`grep`自身进程**:使用`grep -v "grep"`过滤掉`grep`命令产生的干扰项。 2. **排除脚本自身PID**:如果脚本名称与目标进程名相同,需通过`grep -v $$`排除当前脚本的PID(`$$`表示脚本自身进程ID)。 3. **精确匹配进程名**:建议在`grep`中使用正则表达式`[p]attern`实现精确匹配,例如`grep "[m]y_process"`会匹配`my_process`但不匹配`grep`命令本身[^1]。 **示例代码**: ```bash #!/bin/bash TARGET_PROCESS="my_process" # 获取PID列表(排除脚本自身) PID_LIST=$(ps -ef | grep "[${TARGET_PROCESS:0:1}]${TARGET_PROCESS:1}" | grep -v "grep" | awk '{print $2}') # 输出结果 echo "目标进程PID列表: $PID_LIST" ``` --- #### 方法2:使用`pgrep`命令 `pgrep`是专为查询进程ID设计的工具,语法更简洁: - `-f`:匹配完整命令行(默认仅匹配进程名)。 - `-x`:精确匹配进程名(避免部分匹配)。 **示例代码**: ```bash #!/bin/bash TARGET_PROCESS="my_process" # 精确匹配进程PID_LIST=$(pgrep -x "$TARGET_PROCESS") # 输出结果 echo "目标进程PID列表: $PID_LIST" ``` --- #### 方法3:通过`/proc`文件系统验证 获取PID后,可通过`/proc/<PID>/`目录进一步验证进程信息(如可执行路径、命令行参数等)[^3]: ```bash #!/bin/bash PID=12345 # 替换为实际PID # 检查进程是否存在 if [ -d "/proc/$PID" ]; then echo "进程存在,详细信息:" cat /proc/$PID/cmdline else echo "进程不存在" fi ``` --- #### 注意事项 1. **权限问题**:普通用户只能查看自己拥有的进程,需`sudo`权限才能查看系统或其他用户的进程。 2. **多进程处理**:若存在多个同名进程,返回的PID列表需用循环处理: ```bash for pid in $PID_LIST; do echo "处理PID: $pid" # 进一步操作(如kill或监控) done ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值