Linuxマシンですでに実行されているインスタンスがあるかどうかを検出し、インスタンスの数を画面に表示するスクリプトを作成しています。
「detect_itself.sh」スクリプトの内容は次のとおりです。
#!/bin/sh
INSTANCES_NUMBER=`ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
echo "Number of detect_itself.sh instances running now =" $INSTANCES_NUMBER
echo "Second method:"
ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l
echo "Third method:"
echo `ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
echo "Please, press a key"
read -r key
スクリプトを実行すると、画面ごとに表示されます。
Number of detect_itself.sh instances running now = 2
Second method:
1
Third method:
2
Please, press a key
しかし、私はそれが示すことを期待していました:
Number of detect_itself.sh instances running now = 1
Second method:
1
Third method:
1
Please, press a key
ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l
を実行すると、値1が返される理由がわかりませんが、この値を変数に保存してエコーで表示すると、2が表示されます。
これは、サブシェルでps
コマンドを実行しているために発生しています。これを実行すると:
INSTANCES_NUMBER=`ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
これは実際に、そのコマンドを実行するための新しいサブシェルをフォークします。このフォークは親のコピーであるため、2つのdetect_itself.sh
インスタンスが実行されています。説明のために、これを実行します。
#!/bin/sh
echo "Running the ps command directly:"
ps -ef | grep detect_itself.sh | grep -v -i grep
echo "Running the ps command in a subshell:"
echo "`ps -ef | grep detect_itself.sh | grep -v -i grep`"
印刷する必要があります:
$ test.sh
Running the ps command directly:
terdon 25683 24478 0 14:58 pts/11 00:00:00 /bin/sh /home/terdon/scripts/detect_itself.sh
Running the ps command in a subshell:
terdon 25683 24478 0 14:58 pts/11 00:00:00 /bin/sh /home/terdon/scripts/detect_itself.sh
terdon 25688 25683 0 14:58 pts/11 00:00:00 /bin/sh /home/terdon/scripts/detect_itself.sh
幸いなことに、そのためのアプリがあります!この種のことがまさにpgrep
が存在する理由です。したがって、スクリプトを次のように変更します。
#!/bin/sh
instances=`pgrep -fc detect_itself.sh`
echo "Number of detect_itself.sh instances running now = $instances"
echo "Second method:"
ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l
echo "Third method (wrong):"
echo `ps -ef | grep detect_itself.sh | grep -v -i grep | wc -l`
印刷する必要があります:
$ detect_itself.sh
Number of detect_itself.sh instances running now = 1
Second method:
1
Third method (wrong):
2
[〜#〜]重要[〜#〜]:これは安全な方法ではありません。たとえば、this_will_detect_itself
というスクリプトがある場合、それはカウントされます。ファイルをテキストエディタで開いている場合は、それもカウントされます。この種のことに対するはるかに堅牢なアプローチは、ロックファイルを使用することです。何かのようなもの:
#!/bin/sh
if [[ -e /tmp/I_am_running ]]; then
echo "Already running! Will exit."
exit
else
touch /tmp/I_am_running
fi
## do whatever you want to do here
## remove the lock file at the end
rm /tmp/I_am_running
または、さらに良いことに、trap
を使用して、スクリプトがクラッシュした場合でもファイルが削除されていることを確認してください。詳細は、実行中のインスタンスを検出する必要がある理由に応じて、正確に何をしたいかによって異なります。