Ruby スクリプトをデーモン化する方法についてです。
デーモン(Daemon)とは、マルチタスク OS におけるバックグラウンドで動作するプロセスのことです。
Windows のようなシングルタスク OS では、同様な処理を擬似的に実現するサービスに当たるでしょうか。
以下、Ruby スクリプト作成例を掲示して簡単に説明し、起動スクリプトも紹介します。
0. 前提条件
- Linux Mint 14 (64bit) での作業を想定。
- Ruby 2.0.0-p247 での作業を想定。
- デーモン処理を行う Ruby スクリプトを起動・停止・再起動するスクリプトも作成する。
1. Ruby スクリプト作成
以下のような Ruby スクリプトを作成してみた。(説明は次項で)
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
|
2. Ruby スクリプト説明
- 処理概要
1
から順に1秒間隔でカウントアップし、テキストファイルにカウントを永遠に出力し続けるスクリプトである。- システム割り込みを検出した場合に終了処理を行う。
- デーモン化処理について
- Ruby 1.9 以上では、
Process.fork
を使用する方法以外に、Process.daemon(true, true)
を使用する方法が利用できる。daemon
の第1引数をtrue
にすると、カレントディレクトリを移動しない。(デフォルトは、"/“ ディレクトリへ移動する。)daemon
の第2引数をtrue
にすると、標準入力・標準出力・標準エラーを “/dev/null” へリダイレクトしない。(デフォルトはfalse
なので、"/dev/null" へリダイレクトする。)
- プロセス ID(PID)を “test_daemon.pid” に出力(退避)する。
- Ruby 1.9 以上では、
- トラップ(割り込み)設定について
- “SIGINT”, “SIGTERM” のシステム割り込みを検出した場合に、割り込みフラグを立てる。
- 割り込みフラグを検知したら、ループ中の処理から抜ける。
3. Ruby スクリプト実行
作成した Ruby スクリプトを実行してみる。
1
|
|
コンソールには特に何も出力されないはずである。
この Ruby スクリプトと同じディレクトリに、"test_daemon.pid" という PID ファイルと、"test_daemon.txt" という出力ファイルが作成される。
また、プロセスを確認してみると以下のようになる。 ?
の表示が、ターミナルから離れてデーモンとしてバックグラウンドで動作しているということを意味している。
1 2 |
|
4. Ruby スクリプト停止
デーモンとして動作している Ruby スクリプトを停止するには以下のようにする。(もしくは、システムモニタ等で終了させる。)
1
|
|
kill
コマンドのオプションはデフォルトで -TERM
なので、これにより Ruby スクリプト内のトラップ処理部分で SIGTERM
を検知して終了処理が動く。
ただし、PID ファイルは残ったままなので、残っていて問題になるようなら削除する。
5. シェルスクリプト作成
起動したデーモン(Ruby スクリプト)を停止するのに毎回 PID ファイルを指定して kill
コマンドを実行するのは面倒である。
そこで、容易に起動・終了・再起動できるように、以下のようなシェルスクリプトを作成する。
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
6. 起動スクリプト実行
作成した起動スクリプトで、デーモンを起動・停止・再起動してみる。
(PID ファイルの有無で起動中か停止中かを判定するので、PID ファイルが残っていて起動できない場合は一旦 PID ファイルを削除する)
1 2 3 |
|
参考サイト
Ruby の Process については以下を参照。
ログ出力に Logger を使用してもよいが、Ruby 2.0 では、うまく機能しない部分があるので注意!
- library logger
- [ruby-trunk - Bug #7917][Open] Can’t write to a Logger in a signal handler - Ruby Forum
これで、Ruby スクリプトのデーモン化についての基本的なことは理解できました。
色々と応用できそうです。
以上。