write ahead log

ロールフォワード用

UbuntuでUpstartを使ってプログラムをデーモン化する

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にはランレベルという概念があります.

デーモン化にあたって必要な知識になるのでここでおさらいしておきます.

参考: wikipedia - ランレベル

ランレベル/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を使ってみたいです.

7. 参考

Getting Started - upstart

インフラエンジニアway - Upstartを使ってお手軽deamon化

偏った言語信者の垂れ流し - Upstartを使う