systemctl コマンド

## systemdとsystemctlの概要

- systemdはLinuxで利用されるデファクトスタンダードな初期化システムで、システムの起動時に各種サービスを立ち上げる役割を担います。
- systemctlは、systemdの制御や管理のためのコマンドラインツールで、サービスの起動・停止・再起動や状態確認など、さまざまな操作ができるものです。
- CentOS6 までは Linux 起動時の最初に動く "PID が 1 のプロセス" は init でしたが、CentOS7以降 は systemd となっています。


## systemdの役割

具体的にsystemdがおこなうことはこちら。
- Linuxシステムの初期化
- サービス管理
- ログ管理

systemdの役割は、”ユニット”と呼ばれる設定ファイルを読み込み、各種サービスやタスクを適切な順序で起動・管理することです。

ユニットにはサービス(service)、タイマー(timer)、ソケット(socket)などが含まれ、それぞれが特定の機能を果たしています。例えばSSHサーバーを起動する場合、sshd.serviceというユニットが存在し、systemdはこのユニットを使用してSSHサーバーを管理しているのです。


## systemdのメリット

systemdは従来のinitシステムに比べて、以下のようなメリットがあります。

- 起動速度の向上: 依存関係を解決し、同時並行でサービスを起動
- サービス管理の柔軟性: サービスの再起動やデーモンの再ロードが容易
- 依存関係の自動解決: サービス間の依存関係を自動的に検出し、必要な順序で起動


## init（serviceコマンド）との違い

CentOS6 までは、デーモンやアプリケーションなどのプロセスを起動する仕組みに initを採用していました。このinitは、BSD系UNIXと System V系UNIXの2系統が存在し、CentOS6 まではSystem V系UNIXのinitに似たものを採用しています。

System V系UNIXの init のメリットは、ランレベルと呼ばれる値によって、システムの状態を変更できるという単純な仕組みと、OSの起動、停止に関わるデーモンやプログラムの登録が容易である点です。

しかし、デメリットとして、下記のような点も存在します。

- デーモンやアプリケーション数が増加すると、起動、停止順序の管理や制御が複雑になる。
- initからの起動は、並列処理がされないため、数が増えるとOSの起動処理時間が長くなる。
- プロセスの親子関係が崩れた場合、子プロセスの挙動を適切に制御できない。

そこで、CentOS7からは、initに置き換わる仕組みとしてsystemdを採用しています。systemdの主なメリットは下記の通りです。

- 従来必要だったアプリケーションの起動、停止スプリクトが不要。
- 起動処理を並列処理できるので、OSの起動、停止を素早く行える。
- 親子関係にあるプロセスの起動と停止制御を適切に行える。

CentOS7では、ランレベルに変わる「ターゲット」が導入されています。ターゲットとは、systemdにおける複数のサービス（デーモン）などの制御対象をまとめたものを指します。

CentOS6系のランレベルとCentOS7のsysytemdターゲットを対応表にすると下記のようになります。

| アーキテクチャ | CentOS6のランレベル | CentOS7のsystemd |
| :---- | :---- | :---- |
| システム停止 | 0 | systemctl isolate poweroff.target |
| シングルユーザーモード | 1 | systemctl isolate rescue.target |
| マルチユーザーモード | 3 | systemctl isolate multi-user.target |
| グラフィカルログイン | 5 | systemctl isolate graphical.target |
| OSの再起動 | 6 | systemctl isolate reboot.target |
| 緊急モード |  | systemctl isolate emergency.target |

また、CentOS7で定義されてる各種ターゲットが従来のCentOSで採用されていたランレベルのどれに相当しているかをコマンドで確認することができます。

`ls -l /lib/systemd/system/runlevel*target`
```
[root@vbox ~]# ls -l /lib/systemd/system/runlevel*target
lrwxrwxrwx 1 root root 15  1月 12  2023 /lib/systemd/system/runlevel0.target -> poweroff.target
lrwxrwxrwx 1 root root 13  1月 12  2023 /lib/systemd/system/runlevel1.target -> rescue.target
lrwxrwxrwx 1 root root 17  1月 12  2023 /lib/systemd/system/runlevel2.target -> multi-user.target
lrwxrwxrwx 1 root root 17  1月 12  2023 /lib/systemd/system/runlevel3.target -> multi-user.target
lrwxrwxrwx 1 root root 17  1月 12  2023 /lib/systemd/system/runlevel4.target -> multi-user.target
lrwxrwxrwx 1 root root 16  1月 12  2023 /lib/systemd/system/runlevel5.target -> graphical.target
lrwxrwxrwx 1 root root 13  1月 12  2023 /lib/systemd/system/runlevel6.target -> reboot.target
```

従来のinitシステムは、シェルスクリプトを用いてシステム起動時のサービスを順序立てて実行していました。
これに対して、systemdはバイナリ形式のユニットファイルを使用し、依存関係を明確に表現できます。また、systemdはシステム全体の状態管理を一元化し、より効率的なシステム管理が可能となっています。


## systemctlの基本的な使い方
### systemctlコマンドの構文（サービスの開始・停止・再起動・再読み込み）
systemctlの基本的なコマンド構文は以下の通りです。restart (サービス再起動) とreload (設定再読み込み) の大きな違いは、失敗したときの挙動が異なる点です。**再起動で失敗する場合はたいてい、停止は成功して起動が失敗するので、正しく起動するまでの間、サービス停止が発生します。一方、再読み込みで失敗した場合は、停止をしていないので、設定変更前の状態で起動し続けられます。**

`systemctl [オプション] [コマンド] [ユニット名]`

### よく使うコマンド
| 操作 | コマンド |
| :---- | :---- |
| ユニット（サービス）起動 | systemctl start ${Unit} |
| ユニット（サービス）停止 | systemctl stop ${Unit} |
| ユニット（サービス）再起動 | systemctl restart ${Unit} |
| ユニット（サービス）リロード | systemctl reload ${Unit} |
| ユニット（サービス）ステータス表示 | systemctl status ${Unit} |
| ユニット（サービス）自動起動有効 | systemctl enable ${Unit} |
| ユニット（サービス）自動起動無効 | systemctl disable ${Unit} |
| ユニット（サービス）自動起動設定確認 | systemctl is-enabled ${Unit} |
| ユニット（サービス）一覧 | systemctl list-unit-files --type=service |
| 設定ファイルの再読込 | systemctl daemon-reload |

### systemctl status コマンドの見方
- 起動中の場合はActive:の項目が緑色で **active (running)** と表示されます。
- 起動しておらず、起動失敗もしていない場合は Active: の項目が **inactive (dead)** と表示されます。
- 起動失敗した場合は Active: の項目が赤字で **failed** と表示されます。その他問題個所が赤字で表示されます。

#### running と exited の違い
systemctl status コマンドで起動状態を確認した際、起動中のサービスは Active (running) となっている場合もありますが、Active (exited) と表示される場合もあります。この違いは何でしょうか。

簡単に言うと、running は httpd や postfix 等の、常にクライアントからのアクセスを待ち構えているようなサービス状態のことを指します。常に戦闘モードです。

一方 exited は network サービスに代表されるような、サービス起動時にまず処理が走りますがそれを済ませてしまったらのんびり次に呼び出される機会を待つ状態のことを指します。レスポンスは若干遅いですが来たら対応する、という状態です。

### ジャーナルログの確認
systemd-journald（通常はjournaldと呼ばれます）は、systemdの一部であり、システム全体のイベントを記録し、管理するためのログサービスです。journaldがまずシステム上のログを受け取り、必要に応じてrsyslogへログを転送しています。systemd によって起動された ユニットのログ（journaldのログ）は、`/var/log/journal` 以下にバイナリ形式で保存されるようになっています。そのため、ログの確認には `journalctl` コマンドを利用します。また、`-f` で `tail -f` 的な動きになります。`journalctl` コマンドを使ってsystemdのジャーナルログを確認すると、以下のようなログが含まれます。
- systemd: システム全体のイベント。
- kernel: カーネルのイベント。
- network: ネットワーク関連のイベント。
- auth: 認証関連のイベント。
- user: ユーザー関連のイベント。
- daemon: デーモンプロセスのイベント。
- syslog: システム全体のログ。

ジャーナルログに含まれないログもあります。journalctlのジャーナルログに含まれない一般的なログは、各アプリケーションやサービスが独自に管理するログです。以下のようなログがあります。
- Apacheログ: 通常、/var/log/httpd/に保存されます。
- MySQLログ: 通常、/var/log/mysql/に保存されます。
- Dockerログ: 通常、/var/lib/docker/containers/内の各コンテナごとに保存されます。
- Nginxログ: 通常、/var/log/nginx/に保存されます。
- アプリケーション固有のログ: 例えば、Tomcatのログは/var/log/tomcat/に保存されるなど。

これらのログは、journalctlで取得できるログとは異なり、アプリケーションやサービスごとに個別に管理されています。必要に応じて、各ログファイルのパスや保存場所をアプリケーションの設定ファイルで確認することができます。

| 操作 | コマンド |
| :---- | :---- |
| 全ログの表示 | journalctl |
| 特定のサービスのログ表示 | journalctl -u ${Unit} |
| 最新のログ表示 | journalctl -f |
| 特定の時間範囲のログを表示<br>--since 指定した時間以降のログを表示<br>--until 指定した時間までのログを表示 | journalctl --since="2024-08-27 10:00:00"<br>journalctl --until="2024-08-28 10:00:00"<br>journalctl --since="2024-08-27 10:00:00" --until="2024-08-28 10:00:00" |
| プロセスIDでフィルタ | journalctl _PID=${PID} |
| ユーザIDでフィルタ | journalctl _UID=${UID} |
| コマンド名でフィルタ | journalctl ${コマンドパス} |
| pager表示をやめる（grepにわたす場合など） | journalctl --no-pager |

#### jounaldのログを参照するケース
jounaldでログを見るケースは、サーバで障害が発生し、どのファイルに出力されたログなのか？が分からなかったり、時間帯を絞って、すべてのログを参照したい場合に非常に便利です。

#### journaldログの注意事項
journaldのログとrsyslogで設定するログで同じログが2重で保管されていることになるのですが、journaldのログはサーバが再起動すると消えてしまいます。

ログを保存しておきたい場合は、rsyslogでログを保管するか、journaldの設定を変更して再起動してもログが保管できるように設定しておく必要があります。