日々の備忘録

技術について日々学んだことを書きます。

Systemdでマウントするタイミングで開始するサービスを作る

あまり需要はないと思いますが、解決できたので書いてみます。

Vagrantを使って、synced_folder(vboxsf)でホストOS(Windows)側のソースコードを反映させて... という流れで開発を行っていました。

ゲストOSにはCentos7を入れています。

本番環境でSystemdを使うので、開発環境でも同様に自作サービスを登録してBoot時に自動起動するようにしていたんですが、synced_folderでマウントするタイミングと、自作サービスが開始するタイミングが若干前後し、サービスは起動しているが、コードがないのでエラーを吐くという残念なことが度々起きていました。

Vagrantのprovisionで該当サービスをrestartもしくはreloadさせるか、そもそもBoot時に起動させずに、同じくprovisionでstartさせるかすれば解決するんですが、Systemdに習熟する意味もあり、いろいろ調べた次第です。


Systemdには他サービスとの依存関係を明示する方法があります。

例えば、syslogの準備が完了してから起動させたい場合は以下のように記載します。

[Unit]
...
After=syslog.target

このようにしておくと、自動起動時にsyslogの後に起動するようになります。

syslogの起動に失敗したら開始しなくてもいいのであれば、以下の一行をUnitセクションに追加します。

Requires=syslog.target

また、Systemdではマウント情報も取得できます。

通常のサービスはfoo.serviceといったものになりますが、マウントはbar.mountといった形になります。

ただ、After=bar.mountとしても上手くいきません。

systemd-analyze plot > foo.svg としてsvgファイルをWebブラウザで開けばわかるかと思いますが、synced_folderによるマウントは起動中にVagrantが実施しているので自動起動時の依存関係に組み込まれることはありません。

なので、搦め手になりますが、InstallセクションのWantsByを使います。

Installセクションは、systemctl enableを実行する際にどうするのかを明示するセクションです。

例えば、以下のようにするとrunlevel 3で起動するサービスになります。

[Install]
WantsBy=multi-user.target

これをmountと組み合わせて以下のようにします。

[Install]
WantsBy=vagrant.mount

あとは変更を反映するために、systemctl daemon-reload して、systemctl disable && systemctl enable でリンクを張り直します。

こうすることで、/vagrantに共有フォルダがマウントされるタイミングでサービスが起動されます。

注意点として、Installセクションは必ずserviceファイル本体に記載するようにしてください。

Systemdでは、foo.service.d/baz.confとして、Drop-in形式で一部分の追記、上書きが可能ですが、Installセクションに関してはDrop-in形式で記載しても全く効果はありません。


以上で、マウント時に起動するサービスを作ることができました。

冒頭でも記載しましたが、開発環境の問題で他に単純な解決策はあるのでこれを無理に使う必要はありません。

Systemdにはいろいろな機能があるようなので気になる方は調べてみるといいかもしれません。