SystemdのServiceで複数のプロセスを起動する


環境

Ubuntu Server 18.04

はじめに

あるrubyプログラムを引数により別な挙動をさせたい場合があります。
これを1つのserviceに登録する、というものです。

動かすrubyプログラム

whileで延々と時刻とhelloを書き込むだけのrubyプログラムですが、引数により出力するファイルが違います。
/home/hoge/ruby/hello.rbとし、実行権限を与えます。

/home/hoge/ruby/hello.rb
#!/usr/bin/env ruby
while true
  f = File.open("./out#{ARGV[0]}.txt",'a')
  f.puts Time.now.to_s + " hello"
  f.close
  sleep 1
end
$ chmod 0755 /home/hoge/ruby/hello.rb

これに引数をつけて実行すると、out引数.txtに時刻とhelloが書き込まれます。

/home/hoge/ruby/
./hello.rb 1
out1.txt
2018-09-14 23:10:13 +0900 hello
2018-09-14 23:10:14 +0900 hello
2018-09-14 23:10:15 +0900 hello
2018-09-14 23:10:16 +0900 hello
2018-09-14 23:10:17 +0900 hello

シェルプログラムで並行処理させるには

これに1〜4の引数を与えて、並列プロセスとしてシェルで実行させます。
/home/hoge/bin/hello.sh
以下はダメな例。ただ順番に書いただけでは順列に処理されるだけです。

hello.sh
#!/bin/bash
cd /home/hoge/ruby/
./hello.rb 1
./hello.rb 2
./hello.rb 3
./hello.rb 4

並列プロセスとして処理させたい場合は”&”をつけます。
参考:バックグラウンドプロセス

hello.sh
#!/bin/bash
cd /home/hoge/ruby/
./hello.rb 1 &
./hello.rb 2 &
./hello.rb 3 &
./hello.rb 4 &

これにも実行権限をつけます。

$ chmod 0755 /home/hoge/bin/hello.sh

systemdに登録

「/etc/systemd/system」にUnit定義ファイルを作ります。
WorkingDirectoryを指定してやらないと、rubyの中で相対パスで出力しているため、out*.txtが「/」配下にできてしまいます。
Typeはsimpleではなくforkingで。
wiki=>forkとは
forkingにすることで、個々のrubyプログラムにプロセスIDが割り振られます。
Installセクションが無いと、後述のenableで失敗します。

[Unit]
Description = hello daemon

[Service]
WorkingDirectory = /home/hoge/ruby
ExecStart = /home/hoge/bin/hello.sh
Restart = always
Type = forking

[Install]
WantedBy = multi-user.target

Unit定義ファイルができたら、下記コマンドでsystemctlに読み込みます。

$ sudo systemctl daemon-reload

確認。この段階ではまだ「disabled」です。

$ sudo systemctl list-unit-files --type=service | grep hello
hello.service                          disabled  

起動

下記コマンドでhello をenableします。

$ sudo systemctl enable hello
sudo service hello start

status

サービス起動しているかstatusでチェック

$ sudo service hello status
● hello.service - hello daemon
   Loaded: loaded (/etc/systemd/system/hello.service; enabled; vendor preset: en
   Active: active (running) since Sat 2018-09-15 01:24:49 JST; 4min 26s ago
 Main PID: 5837 (code=exited, status=0/SUCCESS)
    Tasks: 8 (limit: 1104)
   CGroup: /system.slice/hello.service
           ├─6079 ruby ./hello.rb 1
           ├─6080 ruby ./hello.rb 2
           ├─6081 ruby ./hello.rb 3
           └─6082 ruby ./hello.rb 4

Sep 15 01:24:49 parallesubuntu1804sv systemd[1]: Starting hello daemon...
Sep 15 01:24:49 parallesubuntu1804sv systemd[1]: Started hello daemon.

ちゃんとserviceで複数プロセスが起動されています。

参考

Systemdを使ってさくっと自作コマンドをサービス化してみる
シェルスクリプトで単純に並列実行・直列実行を行う