.................................................
|
日 |
月 |
火 |
水 |
木 |
金 |
土 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
|
.............................
何となくリンク
.............................
|
|
レスを書き込みます
|
Linux上で、シェルを作成する際、自分自身が起動しているかどうか。
つまり二重起動チェックの実装について面白いことが判明した。
test.sh というシェルを作ります。
このシェルが既に起動されていれば、何もせず終了させる。
といったことをやりたい。
test.sh の中身
-------------------------------
#!/bin/sh
ps -ef | grep $0 | grep -v grep
-------------------------------
これを実行すると、普通に考えると
-----------------------------------------------------------------
root 7838 7599 0 22:52 pts/0 00:00:00 /bin/sh ./test.sh
-----------------------------------------------------------------
のように1行のみ出力される筈である。実際大体は1行で出力される。
これは自分自身が実行されているのだから当たり前だ。
なので、出力された行数を取得し、1以外だったら終了とすればいい。
なんだ、簡単じゃねぇーか。と思いきやそこに罠が潜んでます。
何度かやると気付きますが、たまーに以下のように出力されます。
-----------------------------------------------------------------
root 7834 7599 0 22:52 pts/0 00:00:00 /bin/sh ./test.sh
root 7837 7834 0 22:52 pts/0 00:00:00 /bin/sh ./test.sh
-----------------------------------------------------------------
2行出力っ?! なんで?!
答えはLinuxにはサブシェルとかいう概念があるから。
起動されたtest.shのPIDは7834で、このシェルから呼び出されたコマンドは
サブシェルとして起動します。
なので下のプロセスの親PIDは7834となってます。
ここで、思いついたのは、大元のシェルのPIDを全て除外すれば、
必ず 0 になるんじゃないか? ということです。
以下のように修正しました。
--------------------------------------
ps -ef | grep "sh $0" | grep -v " $$ "
--------------------------------------
こうすることで、大元のシェルを親PIDとして持つ子プロセスは全て除外され
結果的に 0 になるという訳です。実際 0 になりました。
これで漸く解決。 と思いきや、とんでもない超展開が待っていました。
カウントを取る為、シェル内では以下のように組み込む筈です。
CNT=`ps -ef | grep "sh $0" | grep -v " $$ " | wc -l`
CNTが0以外であれば、既に同じシェルが起動中、つまり二重起動と判断できる。
ところが、何故か0〜2の何れかの値でカウントされます。
な、なんでだ!?
すると驚くべきことが判明しました。
バッククォートでコマンドを実行すると、起動シェルの子プロセスとしてではなく完全に別プロセスとして起動されるようです。
つまり、起動シェルのPIDを、親PIDとして持たないPIDが起動される!
今回実装した起動数チェックは、あくまで起動シェルのPIDを持つプロセスを全て除外するというロジックなので、起動シェルのPIDを一切持たない同じ名前のプロセスはカウントされてしまう!
これじゃ二重起動のチェックできねぇよ!
ということで、ロックファイル形式に変えるのでした(´д`)
|
|
|