Quantcast
Channel: Bashタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 2885

シェルスクリプト+ロックファイルで二重実行防止

$
0
0
はじめに cronで定期的にコマンドやシェルスクリプトを実行する場合、 そのコマンドやシェルスクリプトが応答を返さない 処理が遅く次の定期実行タイミングまでに終わらない という事象が発生しても重複して実行しないように対応する必要があります。 この対応がない場合、メモリ不足が発生しサーバーの応答がなくなるなどの問題に繋がる場合があります。 今回はその対応をシェルスクリプト+ロックファイルで実施するやり方を紹介します。 cronの定期処理に手っ取り早く二重起動/二重実行を実現したい方! 定期実行の後処理でいろいろなことをしたい方! 引き継いだサーバー+定期処理で再起動時にロックファイルが残ってしまう事象に遭遇している方! そんな方々のお役に立てればと思います。 シェルスクリプト例 my-script.sh #!/bin/bash LOCKFILE="/var/run/my-script.lock" if [ -f $LOCKFILE ]; then echo "Already execute script." exit 9 fi trap "{ rm $LOCKFILE; }" EXIT touch $LOCKFILE #ここにやりたいことを書く 簡単ですね。 touchコマンドで特定の位置(/var/run)にロックファイル(my-script.lock)を生成し、次の実行でそのロックファイルが存在している==前に実行したシェルスクリプトが実行中と判断し中断する、というものです。 以降で、もう少し詳しく見ていきましょう。(trapはなに???ということも含めて) LOCKFILE="/var/run/my-script.lock" ロックファイルのパスを変数に格納します。 /var/runにはプロセスIDを記載した.pidファイルが格納されますが、今回は/var/runに作成するようにしました。ここは任意のフォルダやファイル名で問題ありません。 ただし書き込み権限があるフォルダにする必要がありますので、その点だけ注意してください。 if [ -f $LOCKFILE ]; then ロックファイルの存在をチェックしています。 -fは"ファイルが存在するか"になります。 -eで"パスが存在するか"になりますが、そちらでも問題ありません。 echo "Already execute script." exit 9 ロックファイルが存在していれば、エラーを出して終了しています。上記の場合の終了コードは9になりますが何番でもかまいません。(0でも可) スクリプトの呼び元で終了コードを判定する場合に適切な終了コードを指定してください。 trap "{ rm $LOCKFILE; }" EXIT これがこの記事の肝になります。(私的に) 一見、 \#ここにやりたいことを書く rm $LOCKFILE; とスクリプトの最後でも問題ないように思います。 しかしながら "#ここにやりたいことを書く"で書いたことが応答を返さないなど正常に終了しないケースもあり、Ctrl+C で中断したりプロセスをkillしたりしますが、その場合はロックファイルが削除されません。(実行中にサーバーを再起動した場合も同じですね) trapを利用することで、Ctrl+Cでの中断やプロセスkillのシグナルを受信(トラップ)することができ、任意の処理(ここではrm)を行うことができます。シグナルについてはここでは省きます。 touch $LOCKFILE touchはタイムスタンプを変更するコマンドですが、存在しないファイルを指定した場合は空(ファイルサイズが0)のファイルを作成します。今回の二重実行防止ではファイルが空であれ存在しているかどうか、が判断できればよいので、ロックファイル生成の目的でtouchを利用しています。 その他の後処理 今回、 trap "{ rm $LOCKFILE; }" EXIT ではrmでのロックファイルを削除するだけになっていますが、それ以外の後処理も記載することが可能です。 以下はあくまでも例ですが、 その他不要プロセスのkill その他残骸ファイルの削除 LED消灯 メール通知 某所への投稿 などなど。 ※何がどこまでできるかは私自身も把握しておりません。例ということでご理解ください。 その他の二重実行防止 今回のシェルスクリプト(touch、trap、rm)を利用したやり方以外にも、 各言語のシグナル処理を利用する。 ps、grepを利用する。 などがあります。 各言語にはシグナル処理があり、そちらでシグナルを受信し任意の処理を実行することも可能です。 ただ引き継いだソースにシグナル処理がなく、手っ取り早く対応したいなんて時は今回のやり方で対応してみては如何でしょう。 ps、grepを利用する方法については別の記事で書こうと思います。 他にこんなやり方があるよ!って方はぜひコメントいただけると幸いです。

Viewing all articles
Browse latest Browse all 2885

Trending Articles