はじめに
cron
でPythonプロセスの自動起動を実装していたときのこと。
定期的にプロセスが止まっていないか確認しつつ、多重起動は防止するような仕組みを以下のように実装しました。
#!/bin/sh
* * * * * setlock -xn /hoge/huga/locklock.lock /usr/bin/python3 /hoge/huga/pypy.py >> /hoge/huga/loglog.log 2>&1
問題発生
ところがここで起こった問題が一つ。
/hoge/huga/pypy.py
が更新される度にプロセスを再起動させたかったのですが、丁度その時にプロセスが起動中だった場合、/hoge/huga/locklock.lock
はロックされたままなので再起動ができません。
この時、私が起動させていたPythonプログラムは無限ループで起動し続けるプログラムだったので、/hoge/huga/locklock.lock
のロックに阻まれて再起動ができない!というような状況に陥りました。
解決策
再起動前にこんな感じのシェルを実行させることで解決しました。
$ lslocks | grep /hoge/huga/locklock.lock | awk '{ print "kill -9", $2 }' | sh
解説
していることは簡単で、以下のような感じです。
1. lslocks
でロックされているファイルを一覧表示
$ lslocks
# 出力
# COMMAND PID TYPE SIZE MODE M START END PATH
# ...
# (unknown) 1234 FLOCK WRITE 0 0 0 /run...
# cron 3932 FLOCK 5B WRITE 0 0 0 /run/crond.pid
# python3 5432 FLOCK WRITE 0 0 0 /hoge/huga/locklock.lock
# ...
2. grep
で対象のファイルの行を抽出
$ lslocks | grep /hoge/huga/locklock.lock
# 出力
# python3 5432 FLOCK WRITE 0 0 0 /hoge/huga/locklock.lock
3. awk
で対象のファイルをロックしているプロセスを削除するコマンドを生成
$ lslocks | grep /hoge/huga/locklock.lock | awk '{ print "kill -9", $2 }'
# 出力
# kill -9 5432
4. sh
で実行
$ lslocks | grep /hoge/huga/locklock.lock | awk '{ print "kill -9", $2 }' | sh
おわりに
書くことが思いつかなかったので解決策のシェルを再掲しておきます。
$ lslocks | grep /hoge/huga/locklock.lock | awk '{ print "kill -9", $2 }' | sh