如何检查我的shell脚本的另一个实例是否正在运行

时间:2013-05-29 07:25:55

标签: bash shell concurrency

GNU bash,版本1.14.7(1)

我的脚本名为" abc.sh" 我只能从abc.sh脚本检查这个... 在里面我写了以下声明

status=`ps -efww | grep -w "abc.sh" | grep -v grep | grep -v $$ | awk '{ print $2 }'`
if [ ! -z "$status" ]; then
        echo "[`date`] : abc.sh : Process is already running"
        exit 1;
fi

我知道这是错误的,因为每次它退出,因为它在' ps'中找到了自己的过程。 怎么解决? 我该如何检查脚本是否已经运行?{/ 1}}?

15 个答案:

答案 0 :(得分:44)

检查已经执行的进程的更简单方法是pidof命令。

if pidof -x "abc.sh" >/dev/null; then
    echo "Process already running"
fi

或者,让脚本在执行时创建一个PID文件。然后,这是一个检查PID文件是否存在的简单练习,以确定该进程是否已在运行。

#!/bin/bash
# abc.sh

mypidfile=/var/run/abc.sh.pid

# Could add check for existence of mypidfile here if interlock is
# needed in the shell script itself.

# Ensure PID file is removed on program exit.
trap "rm -f -- '$mypidfile'" EXIT

# Create a file with current PID to indicate that process is running.
echo $$ > "$mypidfile"

...

<强>更新 现在问题已改为从脚本本身检查。在这种情况下,我们希望始终看到至少有一个abc.sh在运行。如果有多个abc.sh,那么我们知道该进程仍在运行。我仍然建议使用pidof命令,如果进程已经运行,它将返回2个PID。您可以使用grep过滤掉当前PID,在shell中循环,甚至还可以恢复为仅使用wc计算PID来检测多个进程。

以下是一个例子:

#!/bin/bash

for pid in $(pidof -x abc.sh); do
    if [ $pid != $$ ]; then
        echo "[$(date)] : abc.sh : Process is already running with PID $pid"
        exit 1
    fi
done

答案 1 :(得分:20)

我想要“pidof”方法,这就是诀窍:

    if pidof -o %PPID -x "abc.sh">/dev/null; then
        echo "Process already running"
    fi

-o %PPID参数告诉我们省略调用shell或shell脚本的pid。 pidof手册页中的更多信息。

答案 2 :(得分:10)

以下是您在不同地方可以看到的一个技巧:

status=`ps -efww | grep -w "[a]bc.sh" | awk -vpid=$$ '$2 != pid { print $2 }'`
if [ ! -z "$status" ]; then
    echo "[`date`] : abc.sh : Process is already running"
    exit 1;
fi

[a]周围的括号(或选择不同的字母)会阻止grep找到自己。这使得grep -v grep位不必要。我还删除了grep -v $$并修复了awk部分以完成同样的事情。

答案 3 :(得分:6)

如果我在这里错了,有人请把我击倒

我理解mkdir操作是原子操作,所以你可以创建一个锁目录

#!/bin/sh
lockdir=/tmp/AXgqg0lsoeykp9L9NZjIuaqvu7ANILL4foeqzpJcTs3YkwtiJ0
mkdir $lockdir  || {
    echo "lock directory exists. exiting"
    exit 1
}
# take pains to remove lock directory when script terminates
trap "rmdir $lockdir" EXIT INT KILL TERM

# rest of script here

答案 4 :(得分:3)

以稍微不同的方式使用PS命令来忽略子进程:

ps -eaf | grep -v grep | grep $PROCESS | grep -v $$

答案 5 :(得分:3)

以下是我在bash脚本中的表现:

if ps ax | grep $0 | grep -v $$ | grep bash | grep -v grep
then
    echo "The script is already running."
    exit 1
fi

这允许我将此代码段用于任何bash脚本。我需要grep bash,因为当与cron一起使用时,它会创建另一个使用/ bin / sh执行它的进程。

答案 6 :(得分:2)

我在执行期间创建了一个临时文件。

我就是这样做的:

#!/bin/sh
# check if lock file exists
if [ -e /tmp/script.lock ]; then
  echo "script is already running"
else
# create a lock file
  touch /tmp/script.lock
  echo "run script..."
#remove lock file
 rm /tmp/script.lock
fi

答案 7 :(得分:2)

pidof没有为我工作,所以我搜索了更多内容并遇到pgrep

for pid in $(pgrep -f my_script.sh); do
    if [ $pid != $$ ]; then
        echo "[$(date)] : my_script.sh : Process is already running with PID $pid"
        exit 1
    else
      echo "Running with PID $pid"
    fi  
done

部分取自上述答案和https://askubuntu.com/a/803106/802276

答案 8 :(得分:2)

我发现@Austin Phillips的答案很明确。我要做的一个小改进是添加-o(忽略脚本本身的pid)并匹配具有基本名称的脚本(即,可以将相同的代码放入任何脚本中):

if pidof -x "`basename $0`" -o $$ >/dev/null; then
    echo "Process already running"
fi

答案 9 :(得分:1)

我发现使用反引号将命令输出捕获到一个变量中,不幸的是,会产生太多的 ps aux 结果,例如:对于单个正在运行的 abc.sh 实例:

ps aux | grep -w "abc.sh" | grep -v grep | wc -l

返回&#34; 1&#34;。然而,

count=`ps aux | grep -w "abc.sh" | grep -v grep | wc -l`
echo $count

返回&#34; 2&#34;

似乎使用反引号构造不知何故暂时创建另一个进程。可能是topicstarter无法使这项工作的原因。只需要递减$ count var。

答案 10 :(得分:1)

我不想在支票中硬编码abc.sh,所以我使用了以下内容:

MY_SCRIPT_NAME=`basename "$0"`
if pidof -o %PPID -x $MY_SCRIPT_NAME > /dev/null; then
    echo "$MY_SCRIPT_NAME already running; exiting"
    exit 1
fi

答案 11 :(得分:1)

最干净最快的方法:

processAlreadyRunning () {
    process="$(basename "${0}")"
    pidof -x "${process}" -o $$ &>/dev/null
}

答案 12 :(得分:0)

这是紧凑且通用的

# exit if another instance of this script is running
for pid in $(pidof -x `basename $0`); do
   [ $pid != $$ ] && { exit 1; }
done

答案 13 :(得分:0)

绝对可以。

if [[ `pgrep -f $0` != "$$" ]]; then
        echo "Exiting ! Exist"
        exit
fi

答案 14 :(得分:-1)