自作プログラムをSupervisorでデーモン化してみた

Linux環境において自作のプログラムを常に動かしておきたい場合、いくつかの方法が考えられます。
パッと思い付くのは以下の二つでしょうか。

  • SSHでログインして起動する
    →当該SSHセッションがそのプログラムの実行で占有されてしまう。
  • SSHでログインして「&」を後ろに付けて実行する
    →バックグラウンドで実行されるがSSHセッションが切れるとプログラムのプロセスもkillされてしまう。

どちらの場合もSSHセッションを継続しておく必要があります。

SSHセッションが切れても実行を続けさせる方法としては「nohup」コマンドがあります。

nohup {プログラム名} &

その名の通り「SIGHUP」シグナルを無視してプログラムを動かすコマンドです。
これを使うことでSSHセッションからログアウトしてもプログラムを実行させ続けることができます。

上記のパターンで十分な場合もありますが、もう少しスマートにしたい場合は「Supervisor」をオススメします。

Supervisor

Supervisor: A Process Control System
Supervisor is a client/server system that allows its users to monitor and control a number of processes on UNIX-like operating systems.

すごく大雑把に言えば、ユーザーに代わって指定されたプログラムを立ち上げてくれて、その死活監視までしてくれる便利な仕組みです。

Supervisorのインストール

dnfまたはyumコマンド、あるいはpipコマンドによるインストールが便利です。
今回はCentOS Stream 9にインストールしましたが、dnfコマンドによるインストールはパッケージが見つからなかったのでpipコマンドでインストールしました。

sudo pip install supervisor

/usr/local/bin配下にインストールされるので必要に応じて環境変数PATHに追加してください。

以降の手順はCentOS Stream 9にpipでインストールした場合です。
パッケージ管理ツールを使ってインストールした場合は一部の設定が自動的に適用されています。

設定ファイルの作成

下記のコマンドでサンプルの設定ファイルを作成できます。

echo_supervisord_conf > /tmp/supervisord.conf

デフォルト設定のままでもSupervisorの起動はできるのですが、以下の項目については変更しておいた方がいいように思います。

unix_http_serverセクション

file=/run/supervisor/supervisor.sock

supervisordセクション

logfile=/var/log/supervisor/supervisord.log
pidfile=/run/supervisord.pid

supervisorctlセクション

serverurl=unix:///run/supervisor/supervisor.sock

includeセクション(冒頭の;を削除して有効化します)

files = supervisord.d/*.ini

supervisorとsupervisordがある点、ご注意ください。

作成したら当該ファイルを/etcディレクトリに移動しておきます。

サービスに登録する

systemctlコマンドで管理できるようにSupervisorをサービスに登録します。

/usr/lib/systemd/system配下にsupervisord.serviceファイルを作成します。
内容は以下のようにします。

[Unit]
Description=Process Monitoring and Control Daemon
After=rc-local.service

[Service]
Type=forking
ExecStart=/usr/local/bin/supervisord -c /etc/supervisord.conf

[Install]
WantedBy=multi-user.target

ファイルを作成したら念のためリロードしておきます。

sudo systemctl daemon-reload

ディレクトリの作成

以下のディレクトリが存在しない場合は作成しておきます。

/run/supervisor
/var/log/supervisor
/etc/supervisord.d

サービスの起動

以下のコマンドでSupervisorを起動します。

sudo systemctl start supervisord

また、必要に応じて自動起動の設定をしておきます。

sudo systemctl enable supervisord

以上でSupervisorの設定は完了です。

デーモン化するプログラム用の設定ファイルの作成

Supervisorで立ち上げるプログラム用の設定ファイルを/etc/supervisord.dディレクトリ内に作成します。
ファイル名は適宜つけてください。ただし拡張子は「ini」にしてください。
内容は以下のような感じになります。

[program:AwsEc2Api]
directory=/usr/local/self_tools
command=/usr/local/self_tools/AwsEc2Api -web
autostart=true
autorestart=true
stopsignal=TERM
startsecs=5
user=ec2-user
stdout_logfile=/usr/local/self_tools/AwsEc2Api_process.log
stdout_logfile_backups=10
redirect_stderr=true

programは当該プログラムの識別名です。
directoryは当該プログラムのホームディレクトリです。
commandは当該プログラムを実行するときのコマンドラインです。
autostartはsupervisordが起動するときに自動的に当該プログラムを立ち上げるかどうかのフラグです。
autorestartは何からの理由で当該プログラムが停止したとき自動的に再立ち上げするかどうかのフラグです。
userは当該プログラムの実行ユーザーです。

各項目の詳細は公式サイトをご覧ください。

プログラムの実行

supervisorctlコマンドを使ってプログラムの実行を行います。

sudo supervisorctl reread
sudo supervisorctl start AwsEc2Api

rereadで設定ファイルを再読込します。
startの後に、設定ファイルの「program」の部分に記載したプログラムの識別名を指定します。

以上で自作プログラムのデーモン化は完了です。
デーモン化したプログラムの停止、再実行などはsupervisorctlの各種コマンドを使って行います。
詳細はsupervisorctlコマンドのヘルプをご覧ください。


まとめ

Supervisorを使えば自作プログラムを簡単にデーモン化することができます。
是非お試しください。

この記事が自作プログラムをデーモンっぽく動かしたい方の参考になれば幸いです。