golangで簡単なHTTPサーバを作ってこれをデーモン化してみましょう.
今後はSystemdが主流に代わっていくのでしょうが, まだまだUpstartも多いと思います.
1. サンプルプログラムの準備
サンプルプログラムは以下のような簡単なものです.
Helloを挨拶してくれるだけです.
package main import ( "net/http" "fmt" ) func main() { http.HandleFunc("/", helloHandler) http.ListenAndServe(":8080", nil) } func helloHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello\n") }
[実行結果]
vagrant@vagrant-ubuntu-trusty-64:~/hello$ ./hello & [1] 2584 vagrant@vagrant-ubuntu-trusty-64:~/hello$ curl localhost:8080 Hello
2. ランレベルのおさらい
*nixにはランレベルという概念があります.
デーモン化にあたって必要な知識になるのでここでおさらいしておきます.
ランレベル/ID | 名称 | 説明 |
---|---|---|
0 | 停止 | システムの停止、またはシャットダウン |
1 | シングルユーザモード | デーモン起動なし.rootのみ利用可.いわゆるセーフモード |
2 | マルチユーザモード | ネットワークが使えない. |
3 | マルチユーザモード(通常) | いわゆる通常のモード.X11はなし |
4 | 未使用 | |
5 | X11 | ランレベル3 + Xウィンドウ |
6 | 再起動 | システム再起動 |
3. 起動スクリプトの準備
起動スクリプトを以下に作成します.
/etc/init/
今回は以下のようにしましょう.
vi /etc/init/hello-svr.conf
内容は以下のとおりです.
description "Hello Server" author "twinbird<mail@hostname.domain.jp>" start on runlevel [235] stop on runlevel [016] chdir /usr/local/bin/hello-svr exec ./hello respawn
簡単な解説を付けると
- description => 説明
- author => 記述者とメアド
- start on runlevel[235] => ランレベル2,3,5で開始
- stop on runlevel[016] => ランレベル0,1,6で停止
- chdir => ディレクトリを移動
- exec => プログラムを実行
- respawn => プロセスが死んだら再度実行する
4. 設定を認識させる
# initctl reload-configuration # initctl list
以下のようにリストが表示されます. ちゃんと出てますね.
...[中略]... tty6 start/running, process 968 dmesg stop/waiting hello-svr stop/waiting ...[中略]...
5. 操作する
操作コマンドinitctl
を使うと色々できます.
ちなみにサービスの事をjobと呼ぶみたいです.
(サービスだとWindows用語になるのかな.デーモンと呼ぶのが一般的?)
コマンド | 説明 |
---|---|
initctl status [job名] | jobの状態確認 |
initctl list | jobと状態のリストを表示 |
initctl start [job名] | jobの起動 |
initctl stop [job名] | jobの停止 |
initctl restart [job名] | jobの再起動 |
initctl reload [job名] | jobへsighupシグナルを送る |
initctl reload-configuration | 設定ファイルをリロード |
1. 起動する
簡単です.
root@vagrant-ubuntu-trusty-64:~# initctl start hello-svr hello-svr start/running, process 1617
確認はcurlで.
root@vagrant-ubuntu-trusty-64:~# curl localhost:8080 Hello
2. 停止する
こちらも簡単.
root@vagrant-ubuntu-trusty-64:~# initctl stop hello-svr hello-svr stop/waiting
確認.
root@vagrant-ubuntu-trusty-64:~# curl localhost:8080 curl: (7) Failed to connect to localhost port 8080: Connection refused
6. 起動スクリプトをもうちょっと調べる
メモしておきます.
script ~ end script
上記の例ではexecで直接バイナリを起動しましたが, script ~ end scriptの ブロックで囲むとその間を実行するようです.
script # comment if [...]; then ... fi end script
ちょっとしたシェルスクリプト書くならこの方がいいですね.
respawnに試行回数やインターバルを付ける
respawnはジョブが死んだら再度実行してくれる便利な記述ですが, 再試行するのに回数制限を付けたいパターンもあるかもしれないですね.
respawn limit 最大再試行回数 インターバル時間(秒)
で実現できます.
job起動・停止前後で何かする
- pre-start
- post-start
- pre-stop
- post-stop
という命令で指定できます.
pre-start exec [何かコマンド]
割と簡単にデーモン化できますね.
次はSystemdを使ってみたいです.