cgi-binからpythonスクリプトを起動する
このとき、すでにそのスクリプトが走っていると多重起動することになる
たぶんちゃんと動くけど、実行速度が遅くなってしまうのでよろしくない
そこで、同時に同じスクリプトが走らないような仕組みを作る必要がある
最初に見つけたのはこの記事
python内で、シェルコマンドのpsとかgrepを走らせてその返り値が1かどうかを見てる
1なら同名のスクリプトは1つしか走っていない
けど、実際にこれを動かしてみると、子プロセスがめっちゃできたのと、
もし同じプロセスが4つ走ったときにそれが順次終了していくのを判定する方法がないことに気づいた
4つ走ってたら、最初の1つは正常に終了するけど、残りの3つはそれよりも前に走っていたプロセスが終了したかどうか知る術がない
そこで、プロセスのcpu経過時間を比較しようと思った
cpu時間はpsコマンドにオプションをつければ取れるので、↑のコマンドを書き変えれば動くはず
けど、cpu時間の比較とかめんどくさくないか・・・? とふと不安になる
0:30:00 と0:25:00
でどっちが早く始まったか?
cpu時間の比較もやりたくなくなったので、他の方法を考えた
「より古いプロセスはプロセスIDの数字(PID)が小さい」
ということを使えば良さそう
ターミナル上でPIDを取得するコマンドは
これをpythonで走らせればOKimport subprocess
import time
#
# check the single job is running or not
# if the other jobs are running, wait until the end
#
def check_single_job_running(job_name):
while True:
my_pid = os.getpid()
# list up the pids
cmd = "ps -ef | grep %s | grep -v 'grep' | awk '{ print $2 }'" % (job_name)
pids = subprocess.check_output(cmd, shell=True, universal_newlines=True)
# find the minimum pid
min_pid = min([ int(x) for x in pids.split() ])
#print(pids)
#print(min_pid)
# if minimum pid == my pid, the older jobs finished, so now this job will run
if my_pid == min_pid:
break
# waiting time is set as 2 sec
time.sleep(2)
job_name = os.path.basename(__file__)
check_single_job_running(job_name)
while Trueでとりあえずループさせる
もし、他の同名のスクリプトのジョブが走ってた場合は
それらが終わるまでsleepで待機
2秒おきにif文でチェック
my_pid = os.getpid()
で、今のジョブのプロセスIDを取得
cmd = "ps -ef | grep %s | grep -v 'grep' | awk '{ print $2 }'" % (job_name)
pids = subprocess.check_output(cmd, shell=True, universal_newlines=True)
で、同名スクリプトのジョブのPIDを取得する
PIDはスペース区切りで並んだ文字列になってる
universal_newlines=Trueは付けていないとそのまま意味がわかる文字列になっていない(エンコードがUTF8じゃない?)
min_pid = min([ int(x) for x in pids.split() ])
それを数字に変換しつつリストに入れる
その後、最小値を探す
これで、現在走っている同名スクリプトのPIDのうち最小値が得られる
最小値 = 一番古いプロセス
if my_pid == min_pid:
で自分のプロセスよりも古いプロセスがないかどうかを判定している
ない場合は、自分の順番なのでwhileループを抜けて、スクリプトがどんどん進んでいく感じ
多重起動を防ぐ他の方法もあったのでメモしておく
■ 過去記事 : 2重起動したくない時のための起動スクリプト
■ 過去記事 : Pythonで二重起動を防止する(改良版)
プロセスが走っている場合はロックファイルというのを作って多重起動しないようにする
ここには書いてないけど、おそらくプロセス終了時にそのファイルを削除するようなことをしないといけない
自分はこの方法を取らなかったのは、おそらく自分のスクリプトはなんらかのエラーで異常終了することがあると思うw
そのときに、きちんとロックファイルを処理しないとロックファイルが残り続けるのでスクリプトが走らないようになってしまう
いくらエラー処理をきちんとしても、100%うまくいくとは思わなかったのでやめた
デーモン化というのもあった
これはよくわからんけど、とりあえずメモ
ランキング参加中です
↓クリックしていただけると嬉しいです〜