检查进程是否正在运行,如果它已经在运行则退出

use*_*718 5 bash shell scripting scripting-language

我有一个带有方法的shell脚本:

start(){
echo "Hello world"
}

stop(){
ps -ef|grep script.sh|grep -v grep|xargs kill
}

while [ "$1" != "" ]; do
case "$1" in
        start)
            start
            ;;
        stop)
            stop
            ;;
        *)
            echo $"Usage: $0 {start|stop}"
            exit 1
        esac
   shift
done
Run Code Online (Sandbox Code Playgroud)

我正在使用以下命令运行此脚本:./script.sh start调用 start 方法。现在,我想检查此进程是否已在运行,如果已在运行则退出。我在网上尝试了一些解决方案,但没有任何效果。有人请帮忙。我尝试过的解决方案是:

if [ -f /var/tmp/script.lock ]; then
  echo "Already running. Exiting."
  exit 1
else
  touch /var/tmp/script.lock
fi
<main script code>
#some code
rm /var/tmp/script.lock
Run Code Online (Sandbox Code Playgroud)

另一种是:

PID=$(ps -ef | grep script.sh|grep -v grep)

   if [ -z $PID ]; then
       echo "Process already running"
       exit   
fi
Run Code Online (Sandbox Code Playgroud)

即使进程刚刚启动,这些解决方案也不起作用并退出。

Bar*_*mar 3

文件.lock解决方案应该有效。唯一的问题是脚本是否由于错误而退出,并且不删除锁定文件。一种改进是将进程的 PID 存储在文件中,并检查该 PID 是否仍然存在。

if [ -f /var/tmp/script.lock ] && kill -0 $(cat /var/tmp/script.lock); then
  echo "Already running. Exiting."
  exit 1
else
  echo $$ > /var/tmp/script.lock
fi
<main script code>
#some code
rm /var/tmp/script.lock
Run Code Online (Sandbox Code Playgroud)

kill -0实际上并不向进程发送信号,它只是测试是否可以发送信号:PID存在并且您有权向它发送信号(除非您以root身份运行,这意味着进程正在运行您的相同用户 ID)。

如果脚本崩溃并且其 PID 被同一用户重复使用,那么仍然有很小的可能出现误报。但是PID重用需要很长时间,并且被同一用户重用的机会应该很低。

脚本的两个副本也有可能同时启动,并且它们都会看到没有锁定文件。如果您需要防止这种情况,您应该使用该lockfile命令在检查文件的代码周围实现互斥体。