我如何检查脚本中某个进程(PID)是否仍在运行?
e.g.
check if PID still running
if yes then keep checking
if not then echo PID has finished and send simple email
or
Check if PID is not running
echo PID not running and send simple email
else
go back and check again
附加信息:邮件将是一个简单的命令,当 PID 消失时执行,例如mail -s "PID update" [email protected] <<< "PID $pid has exited on $HOSTENAME on $(date)" –
附加信息:PID 将活跃几天,因此监控脚本必须在后台持续检查很长时间
答案1
简介
如果信号0,则不会发送实际信号,但仍会执行错误检查。
因此,要检查一个过程(当前用户/呼叫者被允许发出信号) 正在运行,您可以使用或者/bin/kill
如果您的 shell 有一个内置kill
命令,那么您也可以使用它...kill
将以退出代码退出0
(即成功)如果进程存在并且可以被终止(由当前用户/呼叫者),否则将会出错,打印错误消息并退出> 0
。
注意:如果当前用户/呼叫者是不是允许向该过程发出信号,然后请参阅解决方法下面的部分将介绍如何操作。
用法
但是,在 中bash
,您可以使用 shell 内置命令kill
来执行如下操作:
pid="34223"
kill -0 "$pid" &> /dev/null && echo "$pid exists" || echo "$pid doesn't exist"
和这个:
pid="34223"
if kill -0 "$pid" &> /dev/null;
then
echo "$pid exists"
else
echo "$pid doesn't exist"
fi
和这个:
pid="34223"
while :;
do
if ! kill -0 "$pid" &> /dev/null;
then
echo "$pid has exited"
break
else
sleep 1
fi
done
或者在脚本中运行上述示例,并在不停止脚本执行的情况下监视其 PID,您可以这样做:
#!/bin/bash
# Put this at the top to be run in a background sub-shel i.e (...) &
pid="$$"
(while :;
do
if ! kill -0 "$pid" &> /dev/null;
then
echo "$pid has exited"
break
else
sleep 1
fi
done) &
# The rest of your code goes below this line
但实际上并没有杀死任何东西。
解决方法
注意:Ubuntu 中的进程 ID 在旧进程死亡后会被回收并重新用于新创建的进程,并且同一个应用程序/程序很可能会在下次运行时被分配不同的 PID...因此,它们不是唯一的也不是持久的...因此,如果您想知道某个进程何时启动,您可以使用例如pgrep
通过命令/名称来查找进程,因为 PID 在这里没有意义:
cmd="my_command"
while :;
do
if pgrep -f "$cmd" &> /dev/null;
then
echo "$cmd has started"
break
else
sleep 1
fi
done
注意:以及如所述man kill(2)
:
如果 sig 为 0,则不发送信号,但仍会执行存在性和权限检查;这可用于检查是否存在进程 ID 或进程组 ID呼叫者是 允许发出信号。
因此,如果运行上述检查的用户kill
需要检查属于其他用户/组的进程,那么他们需要实现,而不是上面的,类似这样:
pid="34223"
if ! kill -0 "$pid" |& grep -q "No such process";
then
echo "$pid exists"
else
echo "$pid doesn't exist"
fi
这将检查错误消息本身而不是退出状态kill
,因此应该作为错误消息工作,当进程 ID 存在但信号用户无权这样做时将读取,Operation not permitted
而如果该进程不存在,它将读取No such process
...因此,检查后者应该有效。
答案2
if test -d /proc/"$PID"/; then
echo "process exists"
fi
可以用来查看是否存在 PID。但这并不意味着它积极的。通常我会通过让进程创建一个文件并在特定位置(例如在 while 循环中)写入文件来实现这一点。只要发生这种情况,进程就会执行某些操作。
- 如果 $PID 为空则返回 true(就像
/proc/
在使用 procfs 的系统上一样),所以要小心。 - 此方法是可移植的,因为所有 Linux 都使用 procfs。Mac 也使用 irc。
答案3
对于流程从同一个 shell 启动,您可以使用 bash 内置wait
命令 ex。
# start a "long running" process in the background
echo "starting process" | ts
sleep 30 &
# get the last backgrounded job's PID and wait for it to finish
wait $! && echo "Process $! finished" | ts
-->
Mar 18 10:05:51 starting process
[1] 18127
[1]+ Done sleep 30
Mar 18 10:06:21 Process 18127 finished
这可能比明确循环并检查内核的进程列表的开销更少。
答案4
对于第一部分,请尝试以下步骤:
#!/bin/bash
pid="$1"
while ps -p "$pid" >/dev/null ; do
sleep 2
done
echo "PID $pid has finished"
mail …
并使用如下命令调用它:
$ nohup check_pid.sh 1234 &>/tmp/check_pid.log &
但是,如果你想要与上述相反的效果,请尝试以下操作:
#!/bin/bash
pid="$1"
while ! ps -p "$pid" >/dev/null ; do
sleep 2
## echo "PID $pid is not running."
done
echo "PID $pid has started."
实际上,第二个例子没有意义,因为您永远不会知道新启动进程的 PID(由内核分配)。