systemd - izudon/izudon.github.io GitHub Wiki

Rails アプリを systemd で起動する

結論

  1. 以下の内容を書く。
  2. /etc/systemd/system/redmica.service として配置する。
  3. sudo systemctl enable redmica を実行する。
    • /etc/systemd/system/multi-user.target.wants/redmica.service から
      /etc/systemd/system/redmica.service にシンボリックリンクが張られ、
      起動と同時に立ち上がるようになる。
#
# Redmica
# https://www.redmica.jp
#
[Unit]
Description=The future Redmine you can get today
After=network.target nss-lookup.target nss-lookup.target

[Service]
Type=simple
# User=www-data
# Group=www-data
WorkingDirectory=/var/www/web-apps/redmica
ExecStart=/var/www/web-apps/redmica/bin/rails s -p 4001 -b localhost -e production
TimeoutStopSec=15

[Install]
WantedBy=multi-user.target

状況表示欄に http://... を含む10行程度のもの表示が出れば成功くさい。

$ sudo systemctl status redmica
● redmica.service - The future Redmine you can get today
     Loaded: loaded (/etc/systemd/system/redmica.service; enabled; vendor prese>
     Active: active (running) since Sun 2023-03-12 18:43:44 JST; 6s ago
   Main PID: 248813 (ruby)
      Tasks: 6 (limit: 1026)
     Memory: 152.1M
        CPU: 5.013s
     CGroup: /system.slice/redmica.service
             └─248813 "puma 5.6.5 (tcp://localhost:4001) [redmica-2.2.0]" "" "">

 3月 12 18:43:46 os3-373-19946 rails[248813]: => Run `bin/rails server --help` >
 3月 12 18:43:49 os3-373-19946 rails[248813]: Puma starting in single mode...
 3月 12 18:43:49 os3-373-19946 rails[248813]: * Puma version: 5.6.5 (ruby 3.0.2>
 3月 12 18:43:49 os3-373-19946 rails[248813]: *  Min threads: 0
 3月 12 18:43:49 os3-373-19946 rails[248813]: *  Max threads: 5
 3月 12 18:43:49 os3-373-19946 rails[248813]: *  Environment: production
 3月 12 18:43:49 os3-373-19946 rails[248813]: *          PID: 248813
 3月 12 18:43:49 os3-373-19946 rails[248813]: * Listening on http://127.0.0.1:4>
 3月 12 18:43:49 os3-373-19946 rails[248813]: * Listening on http://[::1]:4001
 3月 12 18:43:49 os3-373-19946 rails[248813]: Use Ctrl-C to stop

3行程度で止まってしまっていたら失敗している。

$ sudo systemctl status redmica
● redmica.service - The future Redmine you can get today
     Loaded: loaded (/etc/systemd/system/redmica.service; enabled; vendor prese>
     Active: active (running) since Sun 2023-03-12 18:50:44 JST; 2s ago
   Main PID: 248857 (ruby)
      Tasks: 1 (limit: 1026)
     Memory: 93.1M
        CPU: 2.435s
     CGroup: /system.slice/redmica.service
             └─248857 ruby /var/www/web-app/redmica/bin/rails s -p 4001 -b loca>

 3月 12 18:50:44 os3-373-19946 systemd[1]: Started The future Redmine you can g>
 3月 12 18:50:47 os3-373-19946 rails[248857]: => Booting Puma
 3月 12 18:50:47 os3-373-19946 rails[248857]: => Rails 6.1.7 application starti>
 3月 12 18:50:47 os3-373-19946 rails[248857]: => Run `bin/rails server --help` >
  • 原因はおそらく何らかの原因により「2重に起動して」しまっているからと思われる。
    (単に起動に時間がかかっているだけということもなくはないが)。
  • ./tmp/pids/server.pid がすでに存在するのに起動した場合などにこのようになるっぽい。
  • 死んだら自動で再立ち上げするオプションが有効になっていたりなどしたせいか、このような場合でも、
    時間によってつながったりつながらなかったりといったことがあって、この原因の究明というか、
    成功か失敗かを見極めるために、大変な苦労をした。

起動権限とリポジトリの参照機能

  • root ではなく User=www-data などで起動すると、
    リポジトリの参照機能を使う際、パーミッションの関係で参照できず、
    画面上にエラーがリポートされることがある。
    「リポジトリに、エントリ/リビジョンが存在しません」
  • root または、リポジトリの参照できる権限で起動する。

puma を systemd で起動する

良いサンプル

その他

rails s コマンドのオプション

  • -d デーモンモードで起動する(ターミナルを閉じてしまっても動き続ける)
    • 今回は指定しない
      • systemd でやる時点ですでにデーモンであるため。
      • 実際動作不安定になる(落ちて再起動を繰り返しているのかつながったりつながらなかったりする)。
  • -e production Rails の起動環境を定義する test development production
  • -p portNo
  • -b bindAddress 127.0.0.1 でなくホスト名 localhost と指定してもうまく行くは行った。
  • --log-to-stdout ログを標準出力に出す(今回は指定しない)

.service ファイルの書き方

[Unit] セクション

  • Description
    • そのサービスの(説明書きというよりも)名称。
  • After
    • network.target としているものが多いためそれで良いと思われる。
      • nss-lookup.target これはサーバの名前引きが有効になった後という意味になるぽい。
      • 複数書き並べるときは After=network.target nss-lookup.target スペースで切る。
    • 詳しくは これを読もう

[Service] セクション

  • Type
    • simple としているものが多いためそれで良いと思われる。
    • forkexec と何が違うか気になるが深掘らないでおこう。
  • User
    • そのサービスの起動ユーザ。
    • 省略すれば root になるのか・・・どうかはわからない。
    • Ubuntu なら www-data、CentOS なら apache が良いのではないか。
      root は強すぎる懸念あり->ウェブサーバの権限が良いのではないかと)。
  • Group
    • そのサービスの起動グループ。
    • 省略すれば当該ユーザのデフォルトのグループになると思われる。
  • WorkingDirectory
    • プロセスのワーキングディレクトリを フルパス で書く。
  • Environment
    • 起動時の環境変数を指定できる、
      • Environment="RAILS_ENV=production"
      • Environment="PORT=3000"
    • 但し rails コマンドはコマンドラインオプションで、
      ポートも(バインドアドレスも)起動モードも指定できるので、
      環境変数でなくコマンドラインオプションを使う選択もアリだ。
  • ExecStart
    • デーモンの起動コマンドを フルパス で書く。
    • WorkingDirectory をしていてもフルパスでないとコケる時がある。
  • ExecStop
    • 設定しなければ単に ExecStart した時のプロセスが kill されるのみ。
      (プロセス番号は起動時にファイルシステム上にちゃんと記録されている)。
  • ExecReload
    • systemctlreload(プロセスを終了させないまま設定ファイルを再読込して
      起動し直す)に対応できる場合はその時のコマンドを フルパス で書く。
  • TimeoutSec
    • TimeoutStartSec この時間内に立ち上がらなければ失敗と見做される。
    • TimeoutStopSec この時間内に終了できなければ失敗と見做される。
    • TimeoutSec この両者を同じ値で一度にセットするためのもの。
  • Restart
    • always としているものが多いためそれで良いと思われる。
    • こうしておくと、なんらかの原因でプロセスが落ちた場合に勝手に再立ち上げしてくれる。
      systemctl コマンドで人為的に停めた場合をもちろん除く)。
  • KillMode
    • デフォルト で良いと思われる(つまりこれは書かなくて良い)。
      nginx などは子プロセスを多く引き連れるから定義してある)。
    • control-group デフォルト コントロールグループ内のすべてのプロセスを殺す。
      ExecStop= で定義されたストップコマンドが起こったのちに)
    • mixed メインプロセスに SIGTERM、以外のグループないプロセスに SIGKILL
    • process メインプロセスだけが殺される(おすすめはしない)。
    • none 何も殺さない(やめておくことを強くお勧めする)。
      ExecStop= で定義されたストップコマンドが起こるだけ)
    • 参考 / 公式ドキュメント

[Install] セクション

  • WantedBy
    • multi-user.target としているものが多いためそれで良いのではないか。
    • この指定により、マルチユーザモードになったタイミングで起動するようになる。
      (つまりシングルユーザモードなどで起動した際には起動しない)。