自作のプログラムやスクリプトをデーモン化したい場合がある。でも、デーモンとして動作するようには作っていない……そういう時には Supervisor の出番だ。
Supervisor は Python 製のツールで、デーモンとして動作するように作られていないプログラムでもデーモン化できる。Supervisor 自体は root 権限でデーモンとして動かす必要があるけど、その下にぶら下がるプログラムはユーザー権限で管理できるのがいい点だ。
今日は、Ubuntu マシンの wplj に Supervisor をインストールして、以前 Go で作った画像アップローダを動かしてみる。
環境
- Ubuntu 16.04 LTS
- Python 2.7.12
Supervisorのインストールといろいろ下準備
Supervisor 自体は pip でインストールできる。
takatoh@wplj $ sudo pip install supervisor
/etc/supervisord.conf にデフォルトの設定ファイルを生成。
takatoh@wplj $ sudo echo_supervisord_conf > /etc/supervisord.conf
-bash: /etc/supervisord.conf: 許可がありません
あれ、sudo つけてるのになんでだ?よくわからないけど sudo -s してからやってみよう。
takatoh@wplj $ sudo -s
root@wplj # echo_supervisord_conf > /etc/supervisord.conf
今度はできた。つぎ、include 設定ファイル用のディレクトリを作成。
root@wplj # mkdir /etc/supervisord.d
supervisord 自体のはくログ周りの設定。デフォルトでは /tmp/supervisord.log に吐き出すことになっているので、設定ファイル /etc/supervisord.conf を修正して /var/log/supervisord.log に吐くようにする。
[supervisord] ;logfile=/tmp/supervisord.log ; main log file; default $CWD/supervisord.log logfile=/var/log/supervisord.log
PID ファイルの設定。/var/run 以下に置くように変更。
;pidfile=/tmp/supervisord.pid ; supervisord pidfile; default supervisord.pid pidfile=/var/run/supervisord.pid
/etc/supervisord.d 以下のファイルを include するように変更。これで設定ファイルの修正は終了。
[include]
files = supervisord.d/*.ini
supervisord自体のサービス登録
/etc/systemd/system/supervisord.service ファイルを作成する。
[Unit] Description=Supervisor process control system for UNIX Documentation=http://supervisord.org/ After=network.target [Service] ExecStart=/usr/local/bin/supervisord -n -c /etc/supervisord.conf ExecStop=/usr/local/bin/supervisorctl $OPTIONS shutdown ExecReload=/usr/local/bin/supervisorctl $OPTIONS reload KillMode=process Restart=on-failure RestartSec=50s [Install] WantedBy=multi-user.target
起動と自動起動の登録
root@wplj # systemctl start supervisord
root@wplj # systemctl enable supervisord.service
Created symlink from /etc/systemd/system/multi-user.target.wants/supervisord.service to /etc/systemd/system/supervisord.service.
自作プログラムの配置
Go で作った画像アップローダ sulaiman を配置する。こんなふうにした。
takatoh@wplj $ tree ~/sulaiman
/home/takatoh/sulaiman
├── config.json
├── photos
│ ├── img
│ └── thumb
├── static
│ ├── css
│ │ └── style.css
│ ├── html
│ │ └── index.html
│ └── js
│ └── sulaiman.js
└── sulaiman
試しに動かしてみる。
takatoh@wplj $ ./sulaiman
_ _ / // /
/ // / \/ _ \
//__////_/ v3.3.5
High performance, minimalist Go web framework
https://echo.labstack.com
_________________________________O/_
O\
⇨ http server started on [::]:9099
大丈夫そうだ。
プロセス管理登録と起動確認
配置したプログラムを supervisord の管理下に登録する。/etc/supervisord.d 以下に設定ファイル sulaiman.ini を作る。
[program:sulaiman] command=/home/takatoh/sulaiman/sulaiman process_name=sulaiman user=takatoh directory=/home/takatoh/sulaiman autostart=true autorestart=true stdout_logfile=/home/takatoh/sulaiman/sulaiman.log stdout_logfile_maxbytes=1MB stdout_logfile_backups=7 stdout_capture_maxbytes=1MB redirect_stderr=true
これで OK のはずだ。確認してみよう。
takatoh@wplj $ supervisorctl start sulaiman
error: , [Errno 13] Permission denied: file: /usr/lib/python2.7/socket.py line: 228
はぁ?どういうこと?
問題解決
ソケット周りでエラーが出てるようだ。権限がないとかいってる。supervisord の設定ファイルを眺めてみると、ソケットファイルのモードを設定する項目が見つかった。これを変更してみよう。
[unix_http_server]<br>file=/tmp/supervisor.sock ; the path to the socket file<br>;chmod=0700 ; socket file mode (default 0700)<br>chmod=0777
supervisord をリロード。
takatoh@wplj $ sudo systemctl reload supervisord
確認。
takatoh@wplj $ supervisorctl status sulaiman
sulaiman RUNNING pid 19356, uptime 0:00:22
こんどは OK。
これで、プログラムやスクリプトを簡単にデーモン化できるようになった。