朝から昼寝

ITや家計、身近なことの整理

[お知らせ]
当サイトは、2024年1月1日に
新URL(happynap.net)に引っ越しました





このページの内容は、最新ではない場合がありますので、新URLをご確認ください。






当サイトには広告を含みます。"オススメ"として紹介している商品やサービスは、個人的にそう思えたものだけです。
共感、興味をもっていただけるものがあればご利用ください (広告掲載ポリシー)。

Systemdによるサービス管理ノウハウ (基本)

概要

Systemdは、RHEL7、CentOS7以降における基本的なサービス管理機能 (等を含むシステム管理デーモンやツールの一式) です。従来はUpstart、SysVinitがありました。

本記事では、SystemdによるRHEL、CentOSのサービス管理に関する基本的なポイントをまとめます。

関連記事として、Systemdのネットワーク関連ユニットについて以下にまとめてあります。

happy-nap.hatenablog.com

本記事の目的

  • Systemdで管理されているサービスやその設定を確認する。
  • Systemdで管理されているサービスを手動で停止、起動する。
  • 自身で作成したプログラム等をSystemdのサービスとして登録する。

基本

Systemd の基本的なサービス管理コマンドについて説明します。

操作対象とするサービスは、httpd.serviceを例にします。

httpd.service は Apache HTTP Server のサービスが Systemd に登録されたものです。適宜、サービス名を読み替えてください。

サービス管理 (systemctl)

基本的なサービス管理コマンド、systemctl です。

各項目の詳細は$ man systemctlで確認できます。

サービスの起動状態の一覧表示(systemctl list-units)

現在のサービスの起動状態を一覧で確認する方法です。

$ systemctl list-units --all --type=service

UNIT          LOAD   ACTIVE SUB     DESCRIPTION
…
httpd.service loaded active running The Apache HTTP Server 
…
  • ACTIVE列にてサービス起動状態を確認可能
    • active : サービスが起動した状態である
    • inactive : サービスが停止した状態である
    • failed : サービスが何らかエラーの状態である(サービス起動失敗等)
    • (その他) reloading, activating, deactivating


  • SUB列でもサービス起動状態を確認可能(typeがサービスの場合)
    • running: プロセスが起動した状態である
    • exited: 処理を終えてプロセスが終了した状態である

--type serviceはサービスのみを表示するためのオプションです。省略するとサービス以外のUnitも表示されます。
特定のサービスのみ表示させる場合は、$ systemctl list-units httpd*のようにパターン指定するか、$ systemctl list-units | grep httpdのように実行します。

ACTIVE列とSUB列の違いは微妙ですが、プロセスが常時起動するサービスの場合、基本的にACTIVE列がactiveのときはSUB列はrunningになっているはずです。対して、処理の実行後、プロセスが終了する類の特殊なサービスはACTIVE列がactiveかつSUB列がexitedになります。

参考までに、コマンド実行時に以下の説明が表示されます。

ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type. 

サービスの自動起動設定の一覧表示(systemctl list-unit-files)

サービスが自動起動する設定かどうかを確認する方法です。

$ systemctl list-unit-files --type service

UNIT FILE                                     STATE   
…
httpd.service                                enabled 
…
  • STATE列にてサービスの自動起動設定を確認可能
    • enabled : 自動起動が有効
    • disabled : 自動起動が無効
    • static : 単体では自動起動しない (staticはsystemctlで有効化、無効化できないもの。他サービスとの依存関係に従い起動するもの等)

サービスの起動/停止/再起動/リロード(systemctl start / stop / restart / reload)

サービスの起動や停止等の操作方法です。

(例としてhttpdサービスに対するコマンドを記載)

  • サービス起動
    # systemctl start httpd

  • サービス停止
    # systemctl stop httpd

  • サービス再起動
    # systemctl restart httpd

  • サービスリロード
    # systemctl reload httpd

reloadは、設定ファイルの変更点を反映する際に使用されます。

例えばhttpdであれば、httpd.confの変更点の反映などです。そのサービスの詳細仕様によりますが、reloadはrestartと異なり、基本的にサービス停止せず設定反映できます。ただし、サービスによってはreloadに対応していない場合があります(ユニットファイルにExecReloadが定義されていない場合)。

補足として、httpdの場合は reload により、内部的には httpd -k graceful が実行されるはずです。詳細はhttpdのマニュアルやユニットファイル (後述) を参照願います。

サービスの状態確認(systemctl status)

現在のサービスの起動状態を確認する方法です。

(例としてhttpdサービスに対するコマンドを記載)

$ systemctl status httpd  (★マークは説明用の目印です)

● httpd.service - The Apache HTTP Server
  Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled★; vendor preset: disabled)
  Active: active (running)★ since Thu 2022-05-01 02:02:02 UTC; 2min 2s ago
    Docs: man:httpd(8)
          man:apachectl(8)
Main PID: 5001 (httpd)
  Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
  CGroup: /system.slice/httpd.service
          ├─5002 /usr/sbin/httpd -DFOREGROUND
          ├─5003 /usr/sbin/httpd -DFOREGROUND
 …

Loaded:行は、Unitファイルのパスと、サービスの自動起動設定(enabled or disabled)が表示されます。前述のサービスの自動起動設定の一覧表示と同様の内容です。

Active:行は、サービスの起動状態(active or inactive等)が表示されます。前述のサービスの起動状態の一覧表示(systemctl list-units)と同様の内容です。

Main PID:行、CGroup:行は、それぞれメインプロセスと、メインプロセスからフォークされた子プロセスです。

詳細

もう少し詳しい内容です。

Unitの構成、種類

systemdはサービス等をUnitの単位で扱います。

ここでは、Unitの構成や配置について簡単に説明します。

ユニットファイル

Unitはファイル形式で定義されます。

そのファイル名の書式はunit_name.type_extensionです。

unit_nameは、そのユニットの名前(サービスであればサービス名)です。
type_extensionは、.service(サービスを定義するもの)、.target(複数のサービスをまとめるためのもの)、.device(デバイス)、.timer(cronのように使えるもの)等、他にもあります。
詳細は、man systemd.unitや、 RedHat社のマニュアルが参考になります。

ユニットファイルに関する主なパス

ユニットファイルの主な格納パスは以下です。

  • /usr/lib/systemd/system/:パッケージマネージャによって配置
  • /etc/systemd/system/:システム管理者によって配置

前者が、RPM等にデフォルトで含まれるユニットファイルが格納されるパスです。後者は、システム管理者が個別にユニットファイルを用意して格納するためのパスです。

同名のユニットファイルが /usr/lib/systemd/system//etc/systemd/system/ の両方に配置された場合、/etc/systemd/system 内のファイルが優先されます。

詳細は、 man systemd.unit の "UNIT FILE LOAD PATH" セクションや、開発元のドキュメントに記載があります。

例:httpdの場合

例えば、httpdの場合、関連するユニットファイルは以下です。

$ ls -l /usr/lib/systemd/system/

(★マークは説明用の目印です)
…
-rw-r--r--  1 root root  314  3月 22 02:27  httpd-init.service
-rw-r--r--  1 root root  944  3月 22 02:27  httpd.service ★
drwxr-xr-x  2 root root   26  4月 13 09:32  httpd.service.d
-rw-r--r--  1 root root  244  3月 22 02:27  httpd.socket
drwxr-xr-x  2 root root   31  4月 13 13:17  httpd.socket.d
-rw-r--r--  1 root root  662  3月 22 02:27  httpd@.service
…

ファイルがたくさんありますが、通常のWebサーバとして使用するhttpdサービスのユニットファイルはhttpd.serviceです。

ユニットを有効化した際の動作

# systemctl enable httpdによりユニットを有効化すると、そのユニットファイル内の定義 (後述の[Install]セクション) に従い動作します。

一般的なサービスであれば、/etc/systemd/system/multi-user.target.wants/配下にシンボリックリンクが作成されます。

このディレクトリ配下にあるユニットファイルは通常のマルチユーザモード(multi-user.target)でのシステム起動時に読み込まれますので、システム起動時にサービス自動起動することになります。

例として、httpd.serviceユニットファイル内の[Install]セクションは以下のように記載されています。

[Install]
WantedBy=multi-user.target

上記の記載により、このユニットを有効化すると、multi-user.target配下にシンボリックリンクが作成されるということです。

作成されたシンボリックリンクは以下です。
$ ls -l /etc/systemd/system/multi-user.target.wants/

…
lrwxrwxrwx  1 root root 37  4月 14 11:29 httpd.service -> /usr/lib/systemd/system/httpd.service
… 

ユニットファイルをカスタマイズする場合

サービス起動時のオプション変更等、ユニットファイルをカスタマイズしたい場合については、以下の記事にまとめてあります。

happy-nap.hatenablog.com

ユニットファイルの読み方

任意のプログラム等をSystemdのサービスとして登録にまとめて記載してあります。

(補足)テンプレート形式のユニット(name@xxx.service)

httpd@.serviceのように@(アットマーク)がついたサービスは、テンプレートです。例えば仮想コンソール(gettyやvnd等)で複数インスタンス起動するようなサービスの場合に使用されます。
systemctl start name@1.servicesystemctl enable name@1.serviceのように、@の後に任意の文字列を指定できます。(getty@tty1.service等)
@の後に指定した文字列は、ユニットファイル内の%l %i 変数に置き換えられます。

任意のプログラム等をSystemdのサービスとして登録

以下の流れです。

  1. サービスとして実行するプログラムを準備
  2. ユニットファイルを作成
  3. 作成したユニットファイルを読み込み、有効化

1. サービスとして実行するプログラムを準備

任意のプログラムを準備します。
プログラムの例として、簡単なシェルスクリプトを作成します。
# vi /usr/local/bin/sleeping.sh

#!/bin/sh
while true; do echo "zzz..." >> /tmp/sleeping.log; sleep 5 ; done

2. ユニットファイルを作成

/etc/systemd/system/配下にユニットファイルを作成します。各オプションの詳細はman systemd.serviceman systemd.unitで確認できます。
# vi /etc/systemd/system/sleeping.service

[Unit]
Description = just keep sleeping process

[Service]
ExecStart = /usr/local/bin/sleeping.sh
Type = simple

[Install]
WantedBy = multi-user.target

上記はとてもシンプルなユニットファイルの例です。実際の運用に際しては、マニュアルを参照の上、各オプションの精査が必要です。

  • [Unit]セクションのオプション ([Unit]セクションは任意)

    • Description:ユニットの説明
    • After:このAfterオプションで指定したユニットの起動開始後に自身のユニットを起動開始する。
    • Before:Afterの逆。
    • Wants:自身のユニットの起動時に、このWantsオプションで指定したユニットを起動する。緩い依存関係を指定しており、指定したユニットの起動が失敗しても自身のユニットは起動しようとする。
    • Requires:Wantsと同様に依存関係を指定するが、必須の依存関係を指定しており、指定したユニットの起動が失敗した場合に自身のユニットは起動失敗として扱われる。

    After、Beforeはサービス起動の「順序関係」を指定するオプションです。Wants、Requiresは「依存関係」を指定するオプションです。なお、Wants、Requiresを指定しても、起動の「順序」は制御されません。

  • [Service]セクションのオプション ([Service]セクションは必須)
    [Service]セクションは、サービス定義において重要です。いくつか記載しますが、他にも多くのオプションがあります。

    • ExecStart:サービス起動時(systemctl start)に実行するコマンド。
    • ExecStop:サービス停止時(systemctl stop)に実行するコマンド。
    • ExecReload:サービスリロード時(systemctl reload)に実行するコマンド。
    • Restart:サービスのプロセス停止時の挙動を指定。デフォルトはno(再起動しない)。例えばalwaysに指定するとプロセスが終了時には再起動される。
    • Type:サービスの起動方法。この指定に従いサービスが正常起動したかを判定する。例えば、プログラム単体を実行し続けるものであればsimpleを指定、子プロセスがそのサービスのメインプロセスになるものであればforkingを指定する。より詳細にサービスの起動判定を行いたい場合はnotify(やdbus)の指定が推奨される。
      • simple:ExecStartで指定したコマンドがサービスのメインプロセスである場合に使用する。プロセス生成した時点でサービス起動完了と判定する。ただし、プロセス生成後にExecStartで指定したコマンドを正常に実行できなくてもサービス起動が成功した扱いとなる(例:Userオプションで指定したユーザが存在しない場合でもサービス起動成功となる、等)。
      • forking:ExecStartで指定したコマンドにより実行されたプロセス(親)から起動(フォーク)された子プロセスがサービスとして動作する場合に使用する。親プロセスが終了した時点で起動完了と判定する。PIDFileオプションの使用が推奨される。なお、man systemd.serviceには、近年PIDFileが使用されないため、特に必要性が無ければType=notifyかType=simpleを使用するよう記載がある。
      • notify:simpleと同様、ExecStartで指定したコマンドがサービスのメインプロセスである場合に使用するが、そのプロセスがsystemdのライブラリ関数sd_notify()に対応している場合に使用する。プロセスは自身の起動完了をsd_notify()にてsystemdに通知する。
      • oneshot:simpleと同様、ExecStartで指定したコマンドがサービスのメインプロセスである場合に使用するが、そのプロセスが終了した時点で起動完了と判定する。その後、(RemainAfterExit=yesを指定しない限り)activeになることはなく、そのままサービスは停止(deactivatingやdead)となる。なお、RemainAfterExit=yesを指定した場合、コマンド終了後もサービスはactiveな状態となる。
    • PIDFile:PIDファイルのパスを指定する。主に、Type=forkingのサービスではこのオプションでメインプロセスのPIDファイルを指定することが推奨される。
       
  • [Install]セクションのオプション ([Install]セクションは任意)
    • WantedBy:このWantedByオプションで指定したユニットの起動時、自身のユニットを起動する。

    [Install]セクションでは、systemctl enablesystemctl disableでユニットを有効化、無効化した際の処理を定義します。例えば、enable時にはWantedByで指定したユニットの.wantsディレクトリに自身のユニットを登録する等です。 前述のWantsの逆でWantedBy、Requiresの逆でRequiredByというオプションがあります。これらは、そのオプションで指定したユニットの起動時に自身のユニットを起動するものです。

3. 作成したユニットファイルを読み込み、有効化

ユニットファイルを作成後、以下のように反映、有効化することでシステム起動時に自動起動するサービスとして設定完了です。

ユニットファイルの変更後は以下のようにsystemdにて読み込みが必要です。
# systemctl daemon-reload

作成したユニットファイルのサービスを有効化します。
# systemctl enable sleeping

手動でサービスを起動する際には以下のコマンドを実行します。
# systemctl start sleeping

上記のシェルスクリプトは、ファイル/tmp/sleeping.logに文字列を出力するものなので、ファイルの中身を確認すると、その動作を確認できます。
# tail -f /tmp/sleeping.log

参考

サービス起動時のエラー等

systemctlコマンドによるサービス起動が失敗した際には以下のようなメッセージが表示されます。
# systemctl start httpd

(サービス起動失敗時のメッセージ例)
Job for httpd.service failed because the control process exited with error code.
See "systemctl status httpd.service" and "journalctl -xe" for details. 

メッセージの指示に従い、# systemctl status httpd.service and journalctl -xeにてログを確認することが可能です。あるいは、messagesにもログが出力されている場合があります。

ユニットファイルの例

備忘用に、httpdデフォルトのユニットファイルを記載しておきます(RHEL8系)。

httpd.service (httpd本体)

/usr/lib/systemd/system/httpd.service

# See httpd.service(8) for more information on using the httpd service.

# Modifying this file in-place is not recommended, because changes
# will be overwritten during package upgrades.  To customize the
# behaviour, run "systemctl edit httpd" to create an override unit.

# For example, to pass additional options (such as -D definitions) to
# the httpd binary at startup, create an override unit (as is done by
# systemctl edit) and enter the following:

#       [Service]
#       Environment=OPTIONS=-DMY_DEFINE

[Unit]
Description=The Apache HTTP Server
Wants=httpd-init.service
After=network.target remote-fs.target nss-lookup.target httpd-init.service
Documentation=man:httpd.service(8)

[Service]
Type=notify
Environment=LANG=C

ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
# Send SIGWINCH for graceful stop
KillSignal=SIGWINCH
KillMode=mixed
PrivateTmp=true

[Install]
WantedBy=multi-user.target

httpd-init.service (TLS用の鍵生成をするためのoneshotのサービス)

/usr/lib/systemd/system/httpd-init.service

[Unit]
Description=One-time temporary TLS key generation for httpd.service
Documentation=man:httpd-init.service(8)

ConditionPathExists=|!/etc/pki/tls/certs/localhost.crt
ConditionPathExists=|!/etc/pki/tls/private/localhost.key

[Service]
Type=oneshot
RemainAfterExit=no

ExecStart=/usr/libexec/httpd-ssl-gencerts

httpd\@.service (テンプレート)

/usr/lib/systemd/system/httpd\@.service

# This is a template for httpd instances.
# See httpd@.service(8) for more information.

[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd@.service(8)

[Service]
Type=notify
Environment=LANG=C
Environment=HTTPD_INSTANCE=%i
ExecStartPre=/bin/mkdir -m 710 -p /run/httpd/instance-%i
ExecStartPre=/bin/chown root.apache /run/httpd/instance-%i
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND -f conf/%i.conf
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful -f conf/%i.conf
# Send SIGWINCH for graceful stop
KillSignal=SIGWINCH
KillMode=mixed
PrivateTmp=true

[Install]
WantedBy=multi-user.target

まとめ

本記事では、SystemdによるRHEL、CentOSのサービス管理に関する基本的なポイントをまとめてみました。

参考

開発プロジェクト (アップストリーム)

RHELのマニュアル

関連記事

happy-nap.hatenablog.com

happy-nap.hatenablog.com

happy-nap.hatenablog.com

happy-nap.hatenablog.com