web-dev-qa-db-ja.com

シェルスクリプトの別のインスタンスが実行されているかどうかを確認する方法

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

それが間違っていることは知っていますスクリプトが既に実行されているかどうかを確認するにはどうすればfrom that scriptのみですか?

31
Jatin Bodarya

既に実行中のプロセスを確認する簡単な方法は、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"

...

更新:スクリプト自体から確認するように質問が変更されました。この場合、少なくとも1つのabc.shが実行されていることが常に予想されます。複数のabc.shがある場合、プロセスがまだ実行されていることがわかります。プロセスが既に実行されている場合、2つのPIDを返すpidofコマンドの使用を引き続きお勧めします。 grepを使用して現在のPIDを除外したり、シェルでループしたり、複数のプロセスを検出するために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
44
Austin Phillips

「pidof」メソッドが必要です。ここにトリックがあります。

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

どこ -o %PPIDパラメーターは、呼び出しシェルまたはシェルスクリプトのpidを省略するように指示します。詳細はpidofのmanページをご覧ください。

22
Aba

以下は、さまざまな場所で見られる1つのトリックです。

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部分を修正して同じことを達成しました。

10
twalberg

私がここで間違えたら誰かが私を撃shootしてください

mkdir操作はアトミックであるため、ロックを作成できますdirectory

#!/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
7
glenn jackman

Bashスクリプトで行う方法は次のとおりです。

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

これにより、このスニペットを任意のbashスクリプトに使用できます。 cronを使用すると、/ bin/shを使用してそれを実行する別のプロセスが作成されるため、grep bashが必要でした。

5
CM Cruz

PSコマンドを少し異なる方法で使用して、子プロセスも無視します。

ps -eaf | grep -v grep | grep $PROCESS | grep -v $$
3
Sridhar Kumar N

@Austin Phillipsからの答えがすぐに見つかります。ちょっとした改善点として、-o(スクリプト自体のpidを無視する)を追加し、basenameを持つスクリプトと一致するようにします(つまり、同じコードを任意のスクリプトに配置できます)。

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

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

2
Scott H

実行中に一時ファイルを作成します。

これは私がそれを行う方法です:

#!/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
2
Cleber Reizen

逆出力を使用してコマンド出力を変数にキャプチャすると、逆に、1つが多すぎるps auxの結果が得られることがわかりました。 abc.shの単一の実行インスタンスの場合:

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

「1」を返します。しかしながら、

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

「2」を返します

バックティック構造を使用すると、一時的に別のプロセスが作成されるようです。 topicstarterでこの作業を行えなかった理由が考えられます。 $ count変数を減らすだけです。

2
Jimmy Falcon

ハードコードしたくなかった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
1
Cloud Artisans

これはコンパクトでユニバーサルです

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