systemd で LSB な init script を走らせる（ささやかな抵抗）

# はじめに

好むと好まざるとに関わらず、[systemd の時代](https://en.wikipedia.org/wiki/Systemd#Adoption_and_Reception)なのだそうです。でも、サービス起動用のスクリプトは SysV init で実績のあるものがあるので、できればそのまま使いたい。なので試しに使ってみたところ、依存関係でちょっと困ったのでメモ。systemd で統一できるなら、そのほうが混乱がなくて良いでしょう、たぶん（好むと好まざるとに関わらず）。

# systemd で SysV init 用スクリプトを使う

systemd は SysV init 用スクリプトをサポートしています。[いくつか制限](http://www.freedesktop.org/wiki/Software/systemd/Incompatibilities/)があるようですが、コンソールからパスワード読むとか、ブート初期の特殊な runlevel で走らせたいといったことをしない一般的なサービスであれば、特に支障はないと思われます。

# スクリプトのインストール手順

インストールはこれまでと同じ手順でいけます。

サービス起動用のスクリプト（ここでは仮に `foobar` とする）を用意したら、`/etc/rc.d/init.d` に配置し、`chkconfig --add foobar` でインストールします。runlevel 3,4,5 で起動順は 99、停止順は 10 としたければ、スクリプトのヘッダーコメントに `# chkconfig: 345 99 10` と記述しておきます。

```bash:/etc/rc.d/init.d/foobar
#!/bin/sh
#
#       /etc/rc.d/init.d/foobar
#
#       Startup script for foobar
#
# chkconfig: 345 99 10
# description: foobar application
...
```

確認してみます。

```
foo@bar$ chkconfig

Note: This output shows SysV services only and does not include native
      systemd services. SysV configuration data might be overridden by native
      systemd configuration.
      If you want to list systemd services use 'systemctl list-unit-files'.
      To see services enabled on particular target use
      'systemctl list-dependencies [target]'.
foobar          0:off   1:off   2:off   3:on    4:on    5:on    6:off
netconsole      0:off   1:off   2:off   3:off   4:off   5:off   6:off
network         0:off   1:off   2:on    3:on    4:on    5:on    6:off
foo@bar$
```

systemd のサービスじゃないよと言うメッセージが出ていますが、ちゃんと認識してますね。runlevel の指定も問題なし。念のため、systemctl でも確認してみます。

```
foo@bar$ systemctl is-enabled foobar
foobar.service is not a native service, redirecting to /sbin/chkconfig.
Executing /sbin/chkconfig foobar --level=5
enabled
foo@bar$
```

自分の守備範囲じゃない場合は chkconfig に転送してます。なるほど。

# LSB ヘッダーで依存関係を記述する

chkconfig で指定した起動順等は、systemd が有効なシステムでは役立たずです。なにせ、/etc/rc.d/rcN.d はほぼ空っぽですからね。そこで、systemd 配下のサービスへの依存関係を LSB ヘッダーで記述します。

```bash:/etc/rc.d/init.d/foobar
...
# chkconfig: 345 99 10
# description: foobar application
### BEGIN INIT INFO
# Provides: foobar
# Required-Start: $remote_fs docker
### END INIT INFO
...
```

LSB ヘッダーは `### BEGIN INIT INFO` と `### END INIT INFO` で囲まれたコメント部分です。`Provides` には通常スクリプト名を指定します。

重要なのは、`Required-Start` です。ここに、systemd 配下で起動するサービスや `$remote_fs` などの仮想機能を指定します。

systemd からどのように見えるかを確認します。

```
foo@bar$ systemctl show foobar
Id=foobar.service
Names=foobar.service
Requires=basic.target
Wants=system.slice
WantedBy=multi-user.target graphical.target
Conflicts=shutdown.target
Before=shutdown.target multi-user.target graphical.target
After=remote-fs.target docker.service systemd-journald.socket basic.target system.slice netconsole.service
Description=LSB: foobar application
LoadState=loaded
ActiveState=active
SubState=exited
SourcePath=/etc/rc.d/init.d/foobar
...
```

この後も延々と続きますが、`After=remote-fs.target docker.service ...` の箇所を確認すればいいですね。ちゃんと認識されています。

`systemctl list-dependencies --after <SERVICE NAME>` を使えば、起動時の依存関係をツリー表示できます。

```
foo@bar$ systemctl list-dependencies --after foobar
foobar.service
|-docker.service
|-netconsole.service
|-system.slice
|-systemd-journald.socket
|-basic.target
| |-rhel-import-state.service
| |-systemd-ask-password-plymouth.path
| |-paths.target

...

-centos\x2dswap.swap
| `-timers.target
|   `-systemd-tmpfiles-clean.timer
`-remote-fs.target
  |-mnt.mount
  `-remote-fs-pre.target
```

ふむ、良さそう。LSB ヘッダーをきちんとサポートしている点については、:+1: です。

# まとめ

systemd と SysV init スクリプトを共存する方法をまとめました。そのうち嫌でも systemd に染まらないといけないのかもしれませんが、ひとまず過渡的な対応で逃げることができたので良かったです（先送り）。

# 参考

- [systemd](http://www.freedesktop.org/wiki/Software/systemd/)
- [Comment Conventions for Init Scripts - Linux Standard Base Core Specification 3.1](http://refspecs.linuxfoundation.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/initscrcomconv.html)