
インスタンスが私の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が表示されます。
答え1
これは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
クラッシュしてもファイルを削除するために使用することを検討することです。詳細は、正確に実行したいタスクと実行中のインスタンスをインスツルメントする必要がある理由によって異なります。