【Linux】サービスの順序関係と依存関係

# はじめに
サービスの順序関係や依存関係について調べる機会があったので備忘として残します。

今回使用するサービスは httpd と postgresql。
postgresql ⇒ httpd の順で起動しなければならないという想定で色々ためします。

今回試すのは以下の４パターン
* [パターン１](#パターン１)
全サービス停止状態で httpd を起動すると、postgresql ⇒ httpd の順で起動する

* [パターン２](#パターン２)
全サービス起動状態で postgresql を停止すると、httpd も停止する

* [パターン３](#パターン３)
全サービス停止状態で postgresql を起動すると、httpd も起動する

* [パターン４](#パターン４)
全サービス起動状態で postgresql を再起動すると、httpd ⇒ postgresql の順で停止し、全サービス停止後に postgresql ⇒ httpd の順で起動する

# サービスの順序関係と依存関係
OS のバージョンを一応載せておきます。
```
[root@db-server-01 ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
```

httpd と postgresql は各自でインストールしてください。（別のサービスでも構いません。）

ちなみにユニットファイルは下記の通り。

両方ともデフォルトの状態です。
依存関係・順序関係の設定を行う箇所のみを抜粋して載せてます。

まずは httpd.service
```
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd(8)
Documentation=man:apachectl(8)
```
httpd.service は、`network.target`、`remote-fs.target`、`nss-lookup.target`の後に起動するように順序関係が設定されている状態です。

次に postgresql-14.service
```
[Unit]
Description=PostgreSQL 14 database server
Documentation=https://www.postgresql.org/docs/14/static/
After=syslog.target
After=network-online.target
```
postgresql-14.service は、`syslog.target`、`network-online.target`の後に起動するように順序関係が設定されている状態です。

次に、順序関係・依存関係のおさらい。
[RedHatの公式ページ](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-managing_services_with_systemd-unit_files)の内容を元に記載します。

順序関係は、「このサービスの後（前）じゃないと起動してはいけませんよ」といった起動の順番を定義するもの。
`After`や`Before`を使用することで実現可能です。

依存関係は、「このサービスが停止したら私も一緒に停止するわ！」といった依存の関係性を定義するもの。
`Requires`や`Wants`などを使用することで実現可能です。

現状はユニットファイルに設定を追加していないので、postgresql と httpd の間には依存関係も順序関係もありません。

## パターン１
全サービス停止状態で httpd を起動すると、postgresql ⇒ httpd の順で起動する
パターンを試してみます。

どちらのサービスも停止中
```
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: inactive (dead) since Mon 2023-07-24 01:57:33 PDT; 4s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: inactive (dead)
```

この状態で httpd を起動してみると httpd のみ起動する。
まだ何も設定していないので当たり前です。
```
[root@db-server-01 ~]# systemctl start httpd
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: active (running) since Mon 2023-07-24 01:58:25 PDT; 1s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: inactive (dead) since Mon 2023-07-24 01:57:33 PDT; 56s ago
```

一度 httpd を停止して、どちらも停止中の状態にする。
```
[root@db-server-01 ~]# systemctl stop httpd
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: inactive (dead)
```

では、ユニットファイルを修正していきます。
httpd が起動する時に、postgresql が起動していないといけない状態にする。

つまり起動順序は postgresql ⇒ httpd です。
依存関係は、httpd が postgresql に依存するようにすれば OK。

まずは、postgresql-14.service を修正します。
```
vi /usr/lib/systemd/system/postgresql-14.service
```

「httpd.service のよりも前に起動してください」
という定義を追加したいので中身は下記のように修正。
```
[root@db-server-01 ~]# cat /usr/lib/systemd/system/postgresql-14.service
[Unit]
Description=PostgreSQL 14 database server
After=syslog.target
After=network-online.target
Before=httpd.service          ### 追加
```

続いては、httpd.service
```
vi /usr/lib/systemd/system/httpd.service
```

「私は、postgresql-14.service がいないと起動できません。」
という定義を追加したいので中身は下記のように修正。
```
[root@db-server-01 ~]# cat /usr/lib/systemd/system/httpd.service
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
After=postgresql-14.service          ### 追加 
Wants=postgresql-14.service          ### 追加 
```

修正後は`daemon-reload`を実行します。
```
systemctl daemon-reload
```

この状態で、httpd を起動してみると postgresql ⇒ httpd の順に起動しているのが分かる。
postgresql：2023-07-24 **02:05:59** に起動
httpd：2023-07-24 **02:06:04** に起動
```
[root@db-server-01 ~]# systemctl start httpd
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: active (running) since Mon 2023-07-24 02:05:59 PDT; 13s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: active (running) since Mon 2023-07-24 02:06:04 PDT; 15s ago
```

ちなみに以下は補足なので試さなくてもよいですが、
After と Before を逆にすると、httpd ⇒ postgresql の順で起動します。
```
### httpd.service
[root@db-server-01 ~]# cat /usr/lib/systemd/system/httpd.service
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
#After=postgresql-14.service
Before=postgresql-14.service      ### Before に変更
Wants=postgresql-14.service

### postgresql-14.service
[root@db-server-01 ~]# cat /usr/lib/systemd/system/postgresql-14.service
[Unit]
Description=PostgreSQL 14 database server
Documentation=https://www.postgresql.org/docs/14/static/
After=syslog.target
After=network-online.target
After=httpd.service      ### After に変更        
#Before=httpd.service
```

`Wants=postgresql-14.service`が httpd.service に記述してあるので、
相変わらず httpd は postgresql に依存しております。

なので、この場合は「私( httpd )が起動したら postgresql も一緒に起動してね♡」です。


## パターン２
「全サービス起動状態で postgresql を停止すると、httpd も停止する」のパターンです。

パターン１で、httpd が postgresql に依存している状態を作りました。
なのでこの状態で postgresql を停止すると、依存している httpd も停止するのでは？ という考えです。

現在はどちらも起動している状態です。
```
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: active (running) since Mon 2023-07-24 02:20:42 PDT; 18s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: active (running) since Mon 2023-07-24 02:20:49 PDT; 17s ago
```

ここで httpd が依存している postgresql を停止します。
すると、postgresql のみが停止し、httpd は起動のまま。
```
[root@db-server-01 ~]# systemctl stop postgresql-14
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: inactive (dead) since Mon 2023-07-24 02:22:22 PDT; 3s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: active (running) since Mon 2023-07-24 02:20:49 PDT; 1min 38s ago
```

依存してないじゃん！！
これの理由ですが、`Wants=postgresql-14.service`が原因です。

`Wants`は「postgresql が居てくれたら嬉しいな・・・♡
でも、、、、もし、あなたが居なくても私は頑張って生きていくわ！」
くらいの熱量なので、postgresql が停止しても httpd まで停止しない状態。

以下は公式の説明。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/866cb7af-590b-460c-d410-6171ddbf0f7e.png)

「postgresql が居なくなったら、私も居なくなるわ！！！」くらい依存させないとダメなわけです。

なので、依存関係の頂点にいる`Requires`を使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/797483/6203d392-2a09-a19a-3931-3353d3030670.png)

修正するファイルは httpd.service です。
```
vi /usr/lib/systemd/system/httpd.service
```

修正内容は下記の通り。
```
[root@db-server-01 ~]# cat /usr/lib/systemd/system/httpd.service
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
After=postgresql-14.service
#Wants=postgresql-14.service       ### コメントアウト
Requires=postgresql-14.service     ### 追加
```

修正後は`daemon-reload`を実行します。
```
systemctl daemon-reload
```

どちらも起動している状態にします。
```
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: active (running) since Mon 2023-07-24 02:30:38 PDT; 2min 43s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: active (running) since Mon 2023-07-24 02:20:49 PDT; 12min ago
```

この状態で postgresql を停止すると、httpd まで一緒に停止するようになりました！
httpd の依存度合いが強くなりましたね・・・。
```
[root@db-server-01 ~]# systemctl stop postgresql-14
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: inactive (dead) since Mon 2023-07-24 02:33:59 PDT; 1s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: inactive (dead) since Mon 2023-07-24 02:33:59 PDT; 4s ago
```

Requires は Wants の上なので、パターン１も問題なくクリアしてます。
```
[root@db-server-01 ~]# systemctl start httpd
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: active (running) since Mon 2023-07-24 02:35:19 PDT; 3s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: active (running) since Mon 2023-07-24 02:35:20 PDT; 3s ago
```

## パターン３
「全サービス停止状態で postgresql を起動すると、httpd も起動する」のパターンです。

今は両サービスが停止の状態です。
```
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: inactive (dead) since Mon 2023-07-24 02:36:53 PDT; 1s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: inactive (dead) since Mon 2023-07-24 02:36:53 PDT; 6s ago
```

この状態で、postgresql を起動してみます。
結果としては postgresql のみが起動してます。
```
[root@db-server-01 ~]# systemctl start postgresql-14
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: active (running) since Mon 2023-07-24 02:37:46 PDT; 2s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: inactive (dead) since Mon 2023-07-24 02:36:53 PDT; 57s ago
```
postgresql は httpd に依存していないので、
httpd の停止中は postgresql の動きが httpd に影響を与えることはありません。

つまり、「コンビニ行きたいなー。httpd は寝てるのか。。
なら、俺一人( postgresql )でコンビニ行こうかな。」状態です。

httpd は postgresql にゾッコンですが、postgresql は依存してないらしい。

では、パターン３を達成するためにはどうすればよいか。
「コンビニ行きたいなー。httpd は寝てるのか。。
俺一人( postgresql )で行きたくないから httpd 起こすか！」って状態にすればいい。

ということで postgresql-14.service の修正
```
vi /usr/lib/systemd/system/postgresql-14.service
```

中身は下記のように修正
```
[root@db-server-01 ~]# cat /usr/lib/systemd/system/postgresql-14.service
[Unit]
Description=PostgreSQL 14 database server
Documentation=https://www.postgresql.org/docs/14/static/
After=syslog.target
After=network-online.target
Before=httpd.service
Wants=httpd.service         ### 追加
```

では動作確認をしてみます。
両サービスが停止している状態で、postgresql を起動します。
```
### 両サービス停止中
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: inactive (dead) since Mon 2023-07-24 02:48:36 PDT; 13s ago
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: inactive (dead) since Mon 2023-07-24 02:48:36 PDT; 14s ago

### postgresql-14 起動
[root@db-server-01 ~]# systemctl start postgresql-14
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: active (running) since Mon 2023-07-24 02:49:00 PDT; 3s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: active (running) since Mon 2023-07-24 02:49:05 PDT; 462ms ago
```

パターン３の内容も達成！

## パターン４
「全サービス起動状態で postgresql を再起動すると、httpd ⇒ postgresql の順で停止し、全サービス停止後に postgresql ⇒ httpd の順で起動する」のパターン

パターン２とパターン３を合わせた感じです。

現在はどちらも起動している状態。
```
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: active (running) since Mon 2023-07-24 02:56:18 PDT; 3min 59s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: active (running) since Mon 2023-07-24 02:56:23 PDT; 3min 56s ago
```

postgresql を再起動し、結果を確認したところ問題なさそう。
```
[root@db-server-01 ~]# systemctl restart postgresql-14
[root@db-server-01 ~]# systemctl status postgresql-14 | grep Active
   Active: active (running) since Mon 2023-07-24 03:01:43 PDT; 2s ago
[root@db-server-01 ~]#
[root@db-server-01 ~]# systemctl status httpd | grep Active
   Active: active (running) since Mon 2023-07-24 03:01:49 PDT; 1s ago
```

もう少し詳しく見るために、ログも確認してみます。

postgresql を停止しているのに、httpd から停止されているのが分かります。
これは、順序関係（before / after のやつ）の設定の影響です。
```
[root@db-server-01 ~]# cat /var/log/messages | grep systemd
Jul 24 03:01:42 db-server-01 systemd: Stopping The Apache HTTP Server...
Jul 24 03:01:43 db-server-01 systemd: Stopped The Apache HTTP Server.
Jul 24 03:01:43 db-server-01 systemd: Stopping PostgreSQL 14 database server...
Jul 24 03:01:43 db-server-01 systemd: Stopped PostgreSQL 14 database server.
Jul 24 03:01:43 db-server-01 systemd: Starting PostgreSQL 14 database server...
Jul 24 03:01:43 db-server-01 systemd: Started PostgreSQL 14 database server.
Jul 24 03:01:43 db-server-01 systemd: Starting The Apache HTTP Server...
Jul 24 03:01:49 db-server-01 systemd: Started The Apache HTTP Server.
```

パターン４も問題なし！

# さいごに
色々勉強になりました！

けど、だんだんヤンデレカップルの記事書いてる気分になって疲れました・・・（笑）

他にも色々な記事を投稿していますので是非そちらもご覧ください。