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
のみですか?
既に実行中のプロセスを確認する簡単な方法は、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
「pidof」メソッドが必要です。ここにトリックがあります。
if pidof -o %PPID -x "abc.sh">/dev/null; then
echo "Process already running"
fi
どこ -o %PPID
パラメーターは、呼び出しシェルまたはシェルスクリプトのpidを省略するように指示します。詳細はpidof
のmanページをご覧ください。
以下は、さまざまな場所で見られる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
部分を修正して同じことを達成しました。
私がここで間違えたら誰かが私を撃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
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が必要でした。
PSコマンドを少し異なる方法で使用して、子プロセスも無視します。
ps -eaf | grep -v grep | grep $PROCESS | grep -v $$
@Austin Phillipsからの答えがすぐに見つかります。ちょっとした改善点として、-o(スクリプト自体のpidを無視する)を追加し、basenameを持つスクリプトと一致するようにします(つまり、同じコードを任意のスクリプトに配置できます)。
if pidof -x "`basename $0`" -o $$ >/dev/null; then
echo "Process already running"
fi
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
実行中に一時ファイルを作成します。
これは私がそれを行う方法です:
#!/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
逆出力を使用してコマンド出力を変数にキャプチャすると、逆に、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変数を減らすだけです。
ハードコードしたくなかった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
これはコンパクトでユニバーサルです
# exit if another instance of this script is running
for pid in $(pidof -x `basename $0`); do
[ $pid != $$ ] && { exit 1; }
done