12
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

systemdで初期処理の同期をとる方法。

Last updated at Posted at 2018-04-16

先日、systemdを使っていて、

  • 「あるサービス(A)のある処理(B)が正常終了してから、別のサービス(C)を起動させたい。」
  • 「あるサービス(A)のある処理(B)が異常終了したら、別のサービス(C)は起動させたくない。」

という状況になりました。

systemd.serviceは、[Unit]のAfterで起動順序を定義できます。
ですが、それはただ、ExecStartを実行する順序が定義されるものであるため、
ある処理(B)が特に時間のかかる処理だった場合は(C)の起動が(A)を追い越してしまいます。

そこで、(A)に対して、少し細工をすることにしました。

前提条件

Linux系OSのsystemdを使っていること。
私はubuntuで実施してますが他のOSでも同じように動くと思います。

サービス(C)のsystemd.service

サービス(C)のsystemd.serviceの[Unit]定義を以下にします。

C.service
[Unit]
After = A.service
Requires = A.service

サービス(A)のsystemd.service

サービス(A)のsystemd.serviceの[Service]Typeをnotifyにします。
マニュアル

A.service
[Service]
Type = notify

こうすることで、サービスAのプログラムコードと連携できるようになります。
コードから通知を受けたタイミングで、起動処理が正常終了する、という意味になります。

サービス(A)に、sdnotifyを埋め込む。

今回はcppで書かれたサービスだったので、ここを参考に、notifyの処理を埋め込みます。
埋め込む場所は、同期を取りたい処理が正常終了するタイミングです。

#include <systemd/sd-daemon.h>

main(){
  //
  // 処理(B)
  //
  sd_notify(0, "READY=1");
  //
  // main処理
  //
}

マニュアル

イニシャライズ処理をplotしてみる。

systemd-analyze plot > foo.svg

点線部分がsystemdによるExecStartから、Type=notifyされるまでの時間がplotされたものです。
処理(B)を実施している時間が赤くなりました。

Screenshot from 2018-04-16 21-03-36.png

※サービス名は公開できないので隠しています。

各言語のsdnotifyはこちら

検証はしていませんが、go,pythonのsdnotifyです。

https://github.com/coreos/go-systemd/blob/master/daemon/sdnotify.go
https://github.com/bb4242/sdnotify

12
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?