Mar*_*arc 9 command-line scripts process
如果某个进程 (PID) 仍在运行,我如何检查脚本?
\ne.g.\ncheck if PID still running\nif yes then keep checking\nif not then echo PID has finished and send simple email\n\nor \nCheck if PID is not running\necho PID not running and send simple email\nelse\ngo back and check again\nRun Code Online (Sandbox Code Playgroud)\n附加信息:\nMail 将是一个简单的命令,当 PID 消失时执行,例如mail -s "PID update" abc@gmail.com <<< "PID $pid has exited on $HOSTENAME on $(date)" \xe2\x80\x93
附加信息:PID 将活跃几天,因此监控脚本必须在后台继续检查很长时间
\nRaf*_*ffa 10
如果 signal 为0,则不发送实际信号,但仍执行错误检查。
因此,要检查进程(当前用户/调用者被允许发出信号)是否正在运行,您可以使用或者/bin/kill如果您的 shell 有内置kill命令,那么您也可以使用它......kill将退出并带有退出代码0(即成功)如果进程存在并且可以被杀死(由当前用户/调用者)并且它将出错,则打印错误消息并> 0否则退出。
注意:如果当前用户/调用者不允许向进程发出信号,请参阅下面的解决方法部分了解如何执行此操作。
但是,在 中bash,您可以使用内置的 shellkill来执行以下操作:
pid="34223"
kill -0 "$pid" &> /dev/null && echo "$pid exists" || echo "$pid doesn't exist"
Run Code Online (Sandbox Code Playgroud)
和这个:
pid="34223"
if kill -0 "$pid" &> /dev/null;
then
echo "$pid exists"
else
echo "$pid doesn't exist"
fi
Run Code Online (Sandbox Code Playgroud)
和这个:
pid="34223"
while :;
do
if ! kill -0 "$pid" &> /dev/null;
then
echo "$pid has exited"
break
else
sleep 1
fi
done
Run Code Online (Sandbox Code Playgroud)
或者要在要监视其 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
Run Code Online (Sandbox Code Playgroud)
没有真正杀死任何东西。
注意:一旦旧进程死亡,Ubuntu 中的进程 ID 就会被回收并重新用于新创建的进程,并且相同的应用程序/程序很可能在下次运行时被分配不同的 PID...因此,它们不是唯一的,也不是持久的...因此,如果您想知道进程何时刚刚启动,您可以使用 egpgrep通过命令/名称查找进程,因为 PID 在这里没有意义:
cmd="my_command"
while :;
do
if pgrep -f "$cmd" &> /dev/null;
then
echo "$cmd has started"
break
else
sleep 1
fi
done
Run Code Online (Sandbox Code Playgroud)
注意:以及如下所述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
Run Code Online (Sandbox Code Playgroud)
这将检查错误消息本身而不是退出状态kill,因此当进程 ID 存在但发信号用户不允许这样做时,它应该作为错误消息,而Operation not permitted如果该进程不存在,它将读取阅读No such process...因此,检查后者应该有效。
对于第一部分,请尝试以下操作:
\n#!/bin/bash\npid="$1"\nwhile ps -p "$pid" >/dev/null ; do\n sleep 2\ndone\necho "PID $pid has finished"\nmail \xe2\x80\xa6\nRun Code Online (Sandbox Code Playgroud)\n并使用如下命令调用它:
\n$ nohup check_pid.sh 1234 &>/tmp/check_pid.log &\nRun Code Online (Sandbox Code Playgroud)\n但是,如果您想要与上述相反的内容,请尝试以下操作:
\n#!/bin/bash\npid="$1"\nwhile ! ps -p "$pid" >/dev/null ; do\n sleep 2\n ## echo "PID $pid is not running."\ndone\necho "PID $pid has started."\nRun Code Online (Sandbox Code Playgroud)\n实际上,第二个示例没有意义,因为您永远不会知道新启动的进程的 PID(将由内核分配)。
\nif test -d /proc/"$PID"/; then
echo "process exists"
fi
Run Code Online (Sandbox Code Playgroud)
可用于查看 PID 是否存在。但这并不一定意味着它是活跃的。一般来说,我会通过让进程创建一个文件并在特定位置写入它(例如在 while 循环中)来做到这一点。只要发生这种情况,流程就在做某事。
/proc/使用 procfs 的系统上存在的那样),所以要小心。对于从同一个 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
Run Code Online (Sandbox Code Playgroud)
-->
Mar 18 10:05:51 starting process
[1] 18127
[1]+ Done sleep 30
Mar 18 10:06:21 Process 18127 finished
Run Code Online (Sandbox Code Playgroud)
这可能比显式循环和检查内核的进程列表具有更少的开销。