systemd
デーモン #Edit sourcesystemd
はシステムの準備を担っているプロセスで、プロセス ID 1 のプロセスでもあります。 systemd
はカーネルから直接起動され、通常であればプロセスを強制終了させるシグナル 9 を受けても耐えられる仕組みを備えています。 systemd
以外のプログラムは systemd
から直接起動されるか、直接起動されたプロセスの子プロセスとして起動されます。また、 systemd
は System V init デーモンの代替として提供され、 System V init との完全な互換性もあります (init スクリプトを動作させることができます) 。
systemd
を使用する主なメリットとして、サービスの起動を同時並行で行うことができることによる起動時間の短縮があげられます。これに加えて、 systemd
では必要な場合にのみサービスを開始する仕組みも存在しています。これにより、システムの起動時には必要のないサービスの起動を省略することができるようになっています。また、 systemd
ではカーネルコントロールグループ (cgroups) にも対応しているほか、スナップショットやシステムの状態の保存と復元なども行うことができます。詳しくは https://www.freedesktop.org/wiki/Software/systemd/ をお読みください。
systemd
Windows Subsystem for Linux (WSL) は Microsoft Windows オペレーティングシステムの中で Linux アプリケーションおよびディストリビューションを動作させることができる仕組みです。既定の WSL は systemd
ではなく独自の init プログラムを使用しますので、 WSL 内で動作している openSUSE Leap で systemd
を使用したい場合は、まず wsl_systemd
パターンをインストールします。これにより、必要な設定を自動的に行うことができます:
>
sudo
zypper in -t pattern wsl_systemd
手作業で行いたい場合は、 /etc/wsl.conf
ファイルを開いて下記のような行を記述します:
[boot] systemd=true
なお、 WSL 内での systemd
へのサポートは部分的なものであることに注意してください。具体的には、 systemd
のユニットファイル側で必要なプロセス管理処理を行わなければなりません。
systemd
の考え方 #Edit source本章では、 systemd
の裏側にある考え方について説明しています。
systemd
は Linux 向けのシステムとセッションのマネージャです。 System V および LSB の init スクリプトとの互換性があります。主な機能は下記のとおりです:
並行動作機能の提供
サービス開始のためのソケットや D-Bus 機能
必要に応じたデーモンの起動
Linux cgroups を利用したプロセスの追跡
システム状態のスナップショット採取と復元
マウント/自動マウントのポイント管理
入念な依存関係ベースのサービス制御ロジックの実装
ユニットファイルには、サービスやソケット、デバイスやマウントポイント、自動マウントポイントやスワップファイル/パーティション、起動ターゲットや監視対象のファイルシステムパス、タイマー制御や systemd による監督制御、一時的なシステム状態のスナップショットやリソース管理スライス、外部生成されたプロセスのグループなど、様々なものに対する情報が含まれています:
systemd
では 「ユニットファイル」 という用語が多く現れますが、下記のような意味があります:
サービス: プロセス (たとえばデーモン) に関する情報が含まれています。ファイル名は .service
で終わります。
ターゲット: ユニットのグループ化や起動時の同期ポイントで使用されます。ファイル名は .target
で終わります。
ソケット: inetd
のように、ソケットベースの有効化を行うための IPC やネットワークソケット、ファイルシステム FIFO などの情報が含まれています。ファイル名は .socket
で終わります。
パス: たとえばファイルが変更されたときにサービスを開始するなど、他のユニットのトリガーとして使用するものが含まれています。ファイル名は .path
で終わります。
タイマー: タイマー制御の情報やタイマーベースの有効化に関する情報が含まれています。ファイル名は .timer
で終わります。
マウントポイント: 通常は fstab 生成器で自動生成されるものです。ファイル名は .mount
で終わります。
自動マウントポイント: ファイルシステムの自動マウントポイントに関する情報が含まれています。ファイル名は .automount
で終わります。
スワップ: スワップデバイスやメモリページングのためのファイルに関する情報が含まれています。ファイル名は .swap
で終わります。
デバイス: sysfs/udev(7) のデバイスツリーで開示されるデバイスユニットに関する情報が含まれています。ファイル名は .device
で終わります。
スコープ/スライス: プロセスのグループを階層構造的にリソース管理するための考え方です。ファイル名は .scope
または .slice
で終わります。
systemd
のユニットファイルについてさらに詳しく知るには、 https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html をお読みください。
System V init システムには、サービスを管理するためのいくつかのコマンドが用意されていました。 insserv
, telinit
などがそれにあたります。 systemd
ではサービスの管理を簡単にするために、これらの機能を systemctl
という 1 つのコマンドにまとめて、覚えやすくしています。このコマンドは、 git
や zypper
のように、 「サブコマンド」 を指定して各種の処理を行います。
systemctl 一般オプション サブコマンド サブコマンドのオプション
詳しい説明をご希望の場合は、 man 1 systemctl
をお読みください。
出力先が端末であり、パイプやファイルなどではない場合、 systemd
が長い出力を行う際には既定でページ制御機能を起動する仕組みを備えています。ページ制御機能を無効化するには、 --no-pager
オプションを指定します。
systemd
では bash の補完機能も用意されています。これにより、サブコマンドの冒頭部分だけを入力して <Tab> を押すと、自動的に残りを補完することができます。この機能は bash
シェル内でのみ利用可能な機能で、 bash-completion
パッケージをインストールする必要があります。
サービスを管理するためのサブコマンドは、 System V init でサービスを管理するためのサブコマンドとほぼ同じです (start
, stop
, ...) 。サービス管理コマンドの書式は下記のとおりです:
systemd
systemctl reload|restart|start|status|stop|... サービス名_(複数可)
rcサービス名 reload|restart|start|status|stop|...
systemd
では、複数のサービスを一括で管理することができます。 System V init ではそれぞれの init スクリプトを別々に動作させる必要がありましたが、 systemd では下記のように実行するだけです:
>
sudo
systemctl start 1_つめのサービス名 2_つめのサービス名
システムで利用可能な全てのサービスを一覧表示するには、下記のように実行します:
>
sudo
systemctl list-unit-files --type=service
下記の表では、 systemd
と System V init における主要なサービス管理コマンドについて、その比較を行っています:
処理 |
|
System V init のコマンド |
---|---|---|
開始: | start | start |
停止: | stop | stop |
再起動: サービスを一旦停止し、その後起動し直します。その時点でサービスが動作していない場合は、単純に起動します。 | restart | restart |
条件付き再起動: 現在動作中の場合にのみサービスを再起動します。その時点でサービスが動作していない場合は、何も行いません。 | try-restart | try-restart |
再読み込み: サービスの運用を止めることなく、サービスに対して設定ファイルを読み込み直すように指示します。使用例: Apache に対して修正された | reload | reload |
再読み込みまたは再起動: 再読み込みに対応するサービスの場合は、再読み込みを行います。対応していない場合は再起動を行います。サービスが動作していない場合は、起動を行います。 | reload-or-restart | 無し |
条件付き再読み込みまたは再起動: 再読み込みに対応するサービスの場合は、再読み込みを行います。対応していない場合は、サービスが動作している場合に限って再起動を行います。サービスが動作していない場合は、何も行いません。 | reload-or-try-restart | 無し |
状態に関する詳細な情報の取得: サービスの状態に関する情報を一覧表示します。 | status | status |
状態に関する簡潔な情報の取得: サービスが動作中かどうかを表示します。 | is-active | status |
前のセクション内で説明しているサービス管理コマンドを利用することで、現在のセッションに対してサービスを制御することができます。 systemd
ではサービスを恒久的に有効化したり無効化したりすることで、必要に応じて起動したり、もしくは常に利用できないようにしたりすることができます。これは YaST で行うことができるほか、コマンドラインでも実施することができます。
下記の表には、それぞれ systemd
と System V init で有効化したり無効化したりするためのコマンドを示しています。
コマンドラインからサービスを有効化しても、サービスは自動では起動しません。時間のシステムの起動時や、ランレベル/ターゲットの変更時に起動されるよう設定されるだけです。有効化したあとにサービスを起動するには、 systemctl start サービス名
や rc サービス名 start
を明示的に実行する必要があります。
処理 |
|
System V init のコマンド |
---|---|---|
有効化: |
|
|
無効化: |
|
|
確認: サービスを有効化しているかどうかを表示します。 |
|
|
再有効化: このコマンドは、サービスを再起動するのと同様に、いったんサービスを無効化して有効化し直します。サービスを既定値に戻したい場合に便利です。 |
|
(無し) |
マスク: サービスを 「無効化」 したあとでも、手作業でサービスを開始することができます。マスクを実施すると、サービスを完全に無効化することができます。注意してお使いください。 |
|
(無し) |
マスク解除: マスクを設定したサービスは、マスクを解除しないと再度使用することができなくなります。 |
|
(無し) |
システムの起動やシャットダウンは、いずれも systemd
が管理しています。この観点からすると、カーネルは裏で動作するバックグラウンド (背景) プロセスであり、 CPU 時間と他のプログラムからのハードウエアアクセス要求を処理する存在であると言えます。
System V init では、システムは 「ランレベル」 と呼ばれる状態に対して起動を行います。ランレベルは、どのようにシステムを起動するのかと、どのサービスを起動するのかを定義するものです。ランレベルは番号で設定されていて、よく知られているものは 0
(システムのシャットダウン), 3
(ネットワーク付きのマルチユーザ環境), 5
(ネットワークとディスプレイマネージャ付きのマルチユーザ環境) の 3 種類です。
systemd
では 「ターゲットユニット」 と呼ばれる新しい考え方が導入されています。しかしながら、従来のランレベルの考え方と完全な互換性をもっています。ターゲットユニットには、番号ではなく名前が設定され、特定の用途ごとに用意されています。たとえば local-fs.target
や swap.target
などでは、ローカルのファイルシステムやスワップ領域をマウントします。
また、ターゲット graphical.target
はネットワークとディスプレイマネージャ機能付きのマルチユーザ環境を表すターゲットで、これがランレベルで言うところの 5 に相当します。 graphical.target
などは複雑なターゲットとして扱われていて、これは複数の他のターゲットを組み合わせた 「メタ」 ターゲットとして動作します。このように、既存の複数のターゲットを組み合わせることで、独自のターゲットを作成するだけの柔軟性を提供しています。
下記の一覧には、最も重要な systemd
のターゲットユニットを一覧で示しています。完全な一覧は、 man 7 systemd.special
をご覧ください。
systemd
ターゲットユニット #default.target
既定で起動されるターゲットです。 「実際の」 ターゲットではなく、 graphic.target
などの他のターゲットに対するシンボリックリンクになっています。これは YaST を利用して恒久的な変更を行うことができます (詳しくは 10.4項 「YaST を利用したサービスの管理」 をお読みください) 。一時的に変更したい場合は、起動プロンプトのカーネルのパラメータに systemd.unit=ターゲット名.target
のように指定してください。
emergency.target
コンソール上に最小限の機能のみが用意された緊急用の root
シェルを起動するターゲットです。起動プロンプトで systemd.unit=emergency.target
のように指定して使用します。
graphical.target
ネットワーク機能付きでマルチユーザ対応、そしてディスプレイマネージャが有効化されるターゲットです。
halt.target
システムをシャットダウンします。
mail-transfer-agent.target
電子メールを送受信するのに必要な全てのサービスを開始するターゲットです。
multi-user.target
ネットワーク機能付きのマルチユーザ環境を開始するターゲットです。
reboot.target
システムを再起動します。
rescue.target
ネットワーク機能の無いシングルユーザモードの root
セッションを開始します。システム管理用の基本的なツールのみが利用できます。 rescue
ターゲットは一般ユーザでのログインが失敗するような場合や、ディスプレイドライバに問題があるような場合の解決時に利用します。
System V init のランレベルシステムとの互換性を維持するため、 systemd
には runlevelX.target
という名前の特殊なターゲットが用意されています。ここで、 X には対応するランレベルの番号が入ります。
現在のターゲットを知りたい場合は、下記のコマンドを実行します: systemctl get-default
systemd
のターゲットユニット #
System V ランレベル |
|
目的 |
---|---|---|
0 |
|
システムのシャットダウン |
1, S |
|
シングルユーザモード |
2 |
|
リモートネットワーク無しでのローカルマルチユーザ環境 |
3 |
|
ネットワーク機能付きの完全マルチユーザ環境 |
4 |
|
未使用もしくはユーザ定義 |
5 |
|
ネットワークとディスプレイマネージャを起動する完全マルチユーザ環境 |
6 |
|
システムの再起動 |
systemd
は /etc/inittab
を無視する問題についてSystem V init システムでは、ランレベルを /etc/inittab
で管理してきましたが、 systemd
ではこの設定ファイルを 使用していません 。独自の起動可能なターゲットを作成する方法について、詳しくは 10.5.5項 「独自のターゲットの作成」 をお読みください。
ターゲットユニットの運用には、下記のコマンドを使用します:
処理 |
|
System V init のコマンド |
---|---|---|
現在のターゲット/ランレベルの変更 |
|
|
既定のターゲット/ランレベルの変更 |
|
(無し) |
現在のターゲット/ランレベルの取得 |
|
もしくは
|
既定のランレベルの恒久的な変更 |
サービスマネージャ を使用するか、下記のコマンドを実行します:
|
サービスマネージャ を使用するか、
"\n \n" |
現在の起動処理に対する既定のランレベルの変更 |
起動プロンプトで下記のオプションを指定します:
|
起動プロンプトで設定したいランレベル番号を入力します。 |
ターゲット/ランレベルの依存関係の表示 |
「Requires」 ではハード依存関係 (解決しなければならないもの) を一覧表示します。「Wants」 ではソフト依存関係 (可能であれば解決すべきもの) を一覧表示します。 |
(無し) |
systemd
では、システムの起動処理を分析する機能を提供しています。全てのサービスの一覧とその状態を (/var/log/
などを処理することなく) 確認することができます。また systemd では、起動処理で時間のかかっている箇所を検出することもできます。
システム起動以降に開始されたサービスの完全な一覧を表示するには、 systemctl
と入力して実行します。このコマンドを実行すると、下記のような出力が現れます (ただし、下記では多くの行を省略しています) 。特定のサービスに対して、より詳しい状態を取得したい場合は、 systemctl status サービス名
と入力して実行します。
#
systemctl
UNIT LOAD ACTIVE SUB JOB DESCRIPTION
[...]
iscsi.service loaded active exited Login and scanning of iSC+
kmod-static-nodes.service loaded active exited Create list of required s+
libvirtd.service loaded active running Virtualization daemon
nscd.service loaded active running Name Service Cache Daemon
chronyd.service loaded active running NTP Server Daemon
polkit.service loaded active running Authorization Manager
postfix.service loaded active running Postfix Mail Transport Ag+
rc-local.service loaded active exited /etc/init.d/boot.local Co+
rsyslog.service loaded active running System Logging Service
[...]
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
161 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
開始に失敗したサービスのみを出力したい場合は、 --failed
オプションを追加します:
#
systemctl --failed
UNIT LOAD ACTIVE SUB JOB DESCRIPTION
apache2.service loaded failed failed apache
NetworkManager.service loaded failed failed Network Manager
plymouth-start.service loaded failed failed Show Plymouth Boot Screen
[...]
システムの起動にかかった時間をデバッグするために、 systemd
では systemd-analyze
というコマンドが用意されています。これは起動にかかった時間の合計のほか、起動にかかった時間順で並べたサービス一覧を表示することができます。また、必要であれば SVG の画像を生成して、起動にかかった時間とサービス同士の関係性を表示することもできます。
#
systemd-analyze
Startup finished in 2666ms (kernel) + 21961ms (userspace) = 24628ms
#
systemd-analyze blame
15.000s backup-rpmdb.service
14.879s mandb.service
7.646s backup-sysconfig.service
4.940s postfix.service
4.921s logrotate.service
4.640s libvirtd.service
4.519s display-manager.service
3.921s btrfsmaintenance-refresh.service
3.466s lvm2-monitor.service
2.774s plymouth-quit-wait.service
2.591s firewalld.service
2.137s initrd-switch-root.service
1.954s ModemManager.service
1.528s rsyslog.service
1.378s apparmor.service
[...]
#
systemd-analyze plot > jupiter.example.com-startup.svg
上述のコマンドを実行することで、起動されたサービスとそれらにかかった時間を一覧表示することができます。より詳しい状況を知りたい場合は、起動プロンプトのパラメータに下記を追加することで、 systemd
に対して完全な起動処理のログを出力させることができます:
systemd.log_level=debug systemd.log_target=kmsg
上記のパラメータ指定により、 systemd
はカーネルのリングバッファにログメッセージを出力するようになります。リングバッファを表示するには、 dmesg
を使用します:
>
dmesg -T | less
systemd
は System V との互換性があるため、既に System V init スクリプトがある場合は、それらを使用することができます。ただし、 1 つだけ大きな問題があります。それは、 System V init スクリプトをそのまま systemd
で動作させようとしても、動作しない場合があるという問題です。 init スクリプト内で su
や sudo
を利用してユーザを切り替えてサービスを起動している場合、スクリプトの実行が失敗して 「Access denied」 (アクセスが拒否されました) というエラーを発生させてしまいます。
su
や sudo
を利用してユーザを切り替える場合、 PAM のセッションが起動されることになります。このセッションは init スクリプトが完了したときに終了されますので、 init スクリプトから開始されたサービスについても、終了してしまいます。このエラーを回避するには、下記のようにしてください:
init スクリプトと同じ名前で、ファイル名の拡張子が .service
になっているサービスラッパーファイルを作成します:
[Unit] Description=説明 After=network.target [Service] User=ユーザ Type=forking1 PIDFile=PID_ファイルのパス1 ExecStart=init_スクリプトのパス start ExecStop=init_スクリプトのパス stop ExecStopPost=/usr/bin/rm -f PID_ファイルのパス1 [Install] WantedBy=multi-user.target2
それぞれ 日本語 で書かれた箇所に必要な値を記入します。
あとは systemctl start アプリケーション
でデーモンを開始するだけです。
基本的なサービス管理機能は、 YaST サービスマネージャ モジュールでも実施することができます。サービスの開始や停止のほか、有効化や無効化も設定することができます。また、サービスの状態を表示したり、既定のターゲットを変更したりすることもできます。この YaST モジュールは、
› › で起動することができます。システムを起動する際のターゲットを変更するには、
のプロップダウンボックスで、ターゲットを選択します。最もよく使用するのは (グラフィカルなログイン画面を表示するターゲット) と (コマンドラインモードでのシステムの開始) です。一覧からサービスを選択します。このとき、
の列には、現在動作中かどうかが表示されます ( であれば動作中、 であれば停止していることを表します) 。開始または停止を行うには、サービスを選択したあと または ボタンを押します。サービスの開始または停止は、現時点での変更のみに影響します。システムを再起動した際に開始または停止を行いたい場合は、有効化または無効化を実施してください。
サービスはシステムの起動時に開始させることができるほか、手動で開始させるように設定することもできます。一覧内の
の列には、 または として起動動作が示されています。起動動作を変更するには、 を押してください。現時点での起動状態を変更したい場合は、上述の開始もしくは停止の手順を行ってください。
サービスの状態メッセージを表示するには、一覧からサービスを選んで systemctl
-l
status サービス名 と同じ内容になります。
systemd
のカスタマイズ #Edit source本章では、 systemd
のユニットファイルに対するカスタマイズ方法を説明しています。
SUSE 製品に同梱される systemd
ユニットファイルは /usr/lib/systemd/
に、カスタマイズしたユニットファイルやユニットファイルの ドロップイン は /etc/systemd/
にそれぞれ配置されます。
systemd
のカスタマイズは /etc/systemd/
内で行うものとし、 /usr/lib/systemd/
内では行わないでください。 /usr/lib/systemd/
でカスタマイズを行ってしまうと、次回の systemd
の更新でそれらが上書きされて消えてしまいます。
ドロップイン・ファイル (または単に ドロップイン と記述する場合もあります) はユニットファイルの一部分のみを記述したファイルで、元のユニットファイルの一部分のみを修正するためのファイルです。ドロップインは元のユニットファイルより優先して解釈されます。たとえば systemctl edit サービス名
を実行すると、 /etc/systemd/system/サービス名.service.d/
ディレクトリを作成してその中に override.conf
というファイルを作成し、既定のテキストエディタを起動してそのファイルを編集することができます。また、テキストエディタを終了すると、動作中の systemd
プロセスに対して変更を通知します。
例として、 MariaDB の起動時に待機する時間をカスタマイズしてみることにします。 sudo systemctl edit mariadb.service
コマンドを実行し、下記の内容を記述します:
# 起動または停止の際の待機時間 TimeoutSec=300
なお、 TimeoutSec
の値は適宜変更して保存してください。変更をシステムに適用するには、 sudo systemctl daemon-reload
コマンドを実行します。
詳しくは man 1 systemctl
コマンドで表示されるマニュアルページを参照してください。
systemctl edit --full サービス名
のように --full
オプションを指定すると、元のユニットファイルをコピーしてから編集を行うようになりますが、元のユニットファイルは SUSE 側の更新によって内容が変化する可能性があるため、このような方式でのカスタマイズは推奨しません。カスタマイズを行う場合は、 /etc/systemd/system/
ディレクトリにカスタマイズしたい箇所のみを記述するようにしてください。またこれに加えて SUSE 製品では、ディストリビューションが独自にドロップイン・ファイルを提供する場合もあることに注意してください。この場合も --full
で作成したドロップイン・ファイルが最優先で処理されます。このような理由から、混乱を防ぐために --full
の使用は避けてください。
systemctl edit
コマンドとは別に、ドロップイン・ファイルを独自に作成して優先順位を任意に調整することもできます。これらのドロップイン・ファイルは、元のユニットファイルを編集したり変更したりすることなく、ユニットやデーモンの設定を自由に変更することができるようになります。このような独自のユニットファイルは、それぞれ下記のディレクトリに配置します:
/etc/systemd/*.conf.d/
, /etc/systemd/system/*.service.d/
システム管理者が追加したりカスタマイズしたりする場合のドロップイン用ディレクトリです。
/usr/lib/systemd/*.conf.d/
, /usr/lib/systemd/system/*.service.d/
提供元の設定を書き換えるためのカスタマイズパッケージが使用するドロップイン用ディレクトリです。たとえば SUSE では systemd-default-settings 等があります。
ドロップインの検索パスの完全な一覧については、 man 5 systemd.unit
で表示されるマニュアルページをお読みください。
たとえば systemd-journald
の既定で設定されている流量制限を無効化したい場合は、下記のような手順を実施します:
/etc/systemd/journald.conf.d
という名前のディレクトリを作成します。
>
sudo
mkdir /etc/systemd/journald.conf.d
ディレクトリ名はドロップイン・ファイルを作成したいサービス名の後ろに .conf.d
を付けて指定します。
このディレクトリ内に /etc/systemd/journald.conf.d/60-rate-limit.conf
というファイルを作成して、その中に書き換えたい内容を記述します。たとえば下記のようになります:
>
cat /etc/systemd/journald.conf.d/60-rate-limit.conf
# 流量制限の無効化 RateLimitIntervalSec=0
あとは作成したファイルを保存して systemd
サービスを再起動するだけです。
>
sudo
systemctl restart systemd-journald
ドロップイン・ファイルと SUSE が提供するファイルとの間で名前の衝突が起こらないように注意してください。一般的には、全てのドロップイン・ファイルのファイル名を 2 桁の数値とハイフンで始めてください。たとえば 80-override.conf
のようになります。
なお、下記の数値範囲が予約されています:
0-19
: systemd
の提供元が使用します。
20-29
: systemd
向けに SUSE が独自に使用します。
30-39
: systemd
以外の SUSE パッケージが使用します。
40-49
: その他のサードパーティ製パッケージが使用します。
50
: systemctl set-property
で作成されるドロップイン・ファイルが使用します。
上記に示した範囲よりも大きい 2 桁の数値を指定することで、 SUSE や systemd
の提供元が設定する値を上書きできるようになります。
なお、ドロップイン・ファイルでの上書き結果を表示したい場合は、 systemctl cat $UNIT
コマンドを実行してください。
なお、 systemd
のコンポーネントに対する設定はファイルシステム内の様々なディレクトリに分散して存在しているため、全体の概要を知るのは難しいのが通常です。 systemd
コンポーネントの設定を調査するには、下記のコマンドを使用してください:
systemctl cat ユニットパターン
: 1 つもしくは複数の systemd
ユニットファイルの設定内容を出力します。たとえば下記のように実行します:
>
systemctl cat atd.service
systemd-analyze cat-config デーモン名またはパス
: systemd
デーモンに対する設定ファイルとドロップインの内容をコピーします。たとえば下記のように実行します:
>
systemd-analyze cat-config systemd/journald.conf
xinetd
から systemd
へのサービス変換 #Edit sourceopenSUSE Leap 15 のリリース以降では、 xinetd
のインフラストラクチャが削除されています。この章では、独自の xinetd
サービスファイルを systemd
のソケットファイルに変換する方法を説明しています。
それぞれの xinetd
サービスファイルに対して、 2 つのsystemd
ユニットファイルが必要になります。 1 つはソケットファイル ( *.socket
) で、もう 1 つはサービスファイル ( *.service
) になります。ソケットファイルでは systemd
に対して、作成すべきソケットを指示し、サービスファイルでは起動すべきプログラムを指定しています。
たとえば下記のような xinetd
サービスファイルがあるものとします:
#
cat /etc/xinetd.d/example
service example
{
socket_type = stream
protocol = tcp
port = 10085
wait = no
user = user
group = users
groups = yes
server = /usr/libexec/example/exampled
server_args = -auth=bsdtcp exampledump
disable = no
}
systemd
に変換するには、下記の 2 つのファイルを作成します:
#
cat /usr/lib/systemd/system/example.socket
[Socket]
ListenStream=0.0.0.0:10085
Accept=false
[Install]
WantedBy=sockets.target
#
cat /usr/lib/systemd/system/example.service
[Unit]
Description=example
[Service]
ExecStart=/usr/libexec/example/exampled -auth=bsdtcp exampledump
User=user
Group=users
StandardInput=socket
systemd
の 「ソケット」 および 「サービス」 ファイルの全オプションを知りたい場合は、それぞれ systemd.socket と systemd.service のマニュアルページをお読みください (man 5 systemd.socket
, man 5 systemd.service
) 。
System V init の SUSE システムでは、ランレベル 4 は未使用で、管理者が独自のランレベル設定を作成できるようになっていました。 systemd
では、必要に応じて任意の数のターゲットを作成することができます。作成するにあたっては、 graphical.target
などの既存のターゲットから始めることをお勧めします。
まずは設定ファイル /usr/lib/systemd/system/graphical.target
を /etc/systemd/system/ターゲット名.target
にコピーして、必要な編集を施します。
上記の手順でコピーしたファイルには、ターゲットに対する必須の ( 「ハード」 ) 依存関係が既に設定されています。 「ソフト」 依存関係を設定したい場合は、まず /etc/systemd/system/ターゲット名.target.wants
ディレクトリを作成してください。
ソフト依存関係を設定するには、 /usr/lib/systemd/system
内から /etc/systemd/system/MY_TARGET.target.wants
にシンボリックリンクを作成します。
ターゲットの設定が終わったら、 systemd
の設定を再読み込みし、新しいターゲットが利用できるようにします:
>
sudo
systemctl daemon-reload
下記の章では、システム管理者向けの高度な使い方を説明しています。さらに高度な systemd
のドキュメンテーションについては、 Lennart Pöttering 氏による管理者向けドキュメンテーション https://0pointer.de/blog/projects/ (英語) をお読みください。
systemd
では、一時 (テンポラリ) ディレクトリを定期的にクリーニングする機能が用意されています。また、以前のバージョンのシステムに存在していた設定は、自動的に移行され有効化されます。 tmpfiles.d
という一時ディレクトリの管理用ファイル、具体的には /etc/tmpfiles.d/*.conf
, /run/tmpfiles.d/*.conf
, /usr/lib/tmpfiles.d/*.conf
の各設定ファイルを利用しています。 /etc/tmpfiles.d/*.conf
内にある設定は、残りの 2 つのディレクトリの設定を上書きするために用意されているディレクトリです (通常は /usr/lib/tmpfiles.d/*.conf
内にパッケージ側の設定ファイルが配置されます) 。
設定の書式は 1 行に 1 つずつアクションとパスを指定する形式で、必要であればモードや所有者、世代やアクションに応じたその他のパラメータなどを指定します。下記の例では、 X11 のロック (施錠) ファイルを削除しています:
Type Path Mode UID GID Age Argument r /tmp/.X[0-9]*-lock
tmpfile タイマーの状態を取得するには、下記のように実行します:
>
sudo
systemctl status systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.timer; static) Active: active (waiting) since Tue 2018-04-09 15:30:36 CEST; 1 weeks 6 days ago Docs: man:tmpfiles.d(5) man:systemd-tmpfiles(8) Apr 09 15:30:36 jupiter systemd[1]: Starting Daily Cleanup of Temporary Directories. Apr 09 15:30:36 jupiter systemd[1]: Started Daily Cleanup of Temporary Directories.
一時ファイルの処理方法について、より詳しく知るには man 5 tmpfiles.d
をお読みください。
10.6.9項 「サービスのデバッグ」 では、特定のサービスに対してログメッセージを閲覧する方法を説明しています。しかしながら、ログメッセージはサービスに限ったものではありません。 systemd
自身が生成した完全なログメッセージにアクセスしたり、それを検索したりすることもできます。 systemd
では、ログメッセージを総称して 「ジャーナル」 と読んでいます。 journalctl
コマンドを使用すると、最も古い記録から順に完全なログメッセージを表示することができます。フィルタの適用や出力形式の変更など、様々なオプションについては、 man 1 journalctl
をお読みください。
systemd
では、現在の状態を名前付きのスナップショットとして保存し、後から isolate
サブコマンドで復元できる機能が用意されています。これは、任意の時点の状態にいつでも戻れるという機能から、サービスや独自のターゲットをテストする際に便利な機能です。ただし、スナップショットは現在のセッションに対してのみ有効で、システムを再起動すると自動的に削除されます。また、スナップショットの名前は .snapshot
で終わらなければなりません。
>
sudo
systemctl snapshot スナップショット名.snapshot
>
sudo
systemctl delete スナップショット名.snapshot
>
sudo
systemctl show スナップショット名.snapshot
>
sudo
systemctl isolate スナップショット名.snapshot
systemd
では、 /etc/modules-load.d
内に存在する設定ファイルに従って、システムの起動時に自動的にカーネルモジュールを読み込みます。ファイル名は モジュール名.conf という名前でなければならず、下記のような内容を記述します:
# モジュール を起動時に読み込む モジュール名
特定のパッケージが、カーネルモジュールを読み込ませるために設定ファイルをインストールすると、そのファイルは /usr/lib/modules-load.d
内に保存されます。また、同じ名前の設定ファイルが /etc/modules-load.d
内にも存在すると、 /etc/modules-load.d
内に存在するもののほうが優先的に処理されます。
詳しくは modules-load.d(5)
のマニュアルページをお読みください。
System V init では、サービスを読み込む際に何らかの処理を行う必要がある場合、/etc/init.d/before.local
内に記述を行っていました。 systemd
ではこのようなファイルには対応していませんが、サービスの開始前に何らかの処理をする必要がある場合は、下記のようにして行います:
/etc/modules-load.d
ディレクトリ内にドロップ・インファイルを作成します (書式については man modules-load.d
をお読みください) 。
/etc/tmpfiles.d
ディレクトリ内にドロップイン・ファイルを作成します (書式については man tmpfiles.d
をお読みください) 。
下記のようにしてシステムサービスファイルを作成します (たとえば /etc/systemd/system/before.service
という名前で作成します):
[Unit] Before=あらかじめ開始しておくべきサービスの名前 [Service] Type=oneshot RemainAfterExit=true ExecStart=コマンド # 注意: 上記のコマンドは、シェル経由ではなく直接実行されます。詳しい書式は # systemd.service と systemd.unit の各マニュアルページをお読みください [Install] # サービスを開始するターゲット WantedBy=multi-user.target #WantedBy=graphical.target
サービスファイルを作成したら、後は下記のコマンドを実行します (root
で実行します):
>
sudo
systemctl daemon-reload>
sudo
systemctl enable before
なお、サービスファイルを変更したあとは、下記を実行してください:
>
sudo
systemctl daemon-reload
従来の System V init システムでは、サービスとして起動したプロセスを明示的には管理していませんでした。ただし、 Apache のようなサービスでは、 Apache 自身が必要な多数のプロセス (CGI や Java プロセスなど) を起動して管理していました。このような方法では、プロセスからサービスを探るのが難しくなってしまうか、場合によっては全く不可能になってしまっていました。これに加えて、サービスが正しく終了しなかった場合、子プロセスが残ったままになってしまう場合もありました。
systemd
では、このような問題を cgroup で解決しています。 cgroup はカーネルの機能で、プロセスをまとめ、生成された子プロセスを階層構造型のグループとして管理する仕組みです。 systemd
では、それぞれのサービスを別々の名前付き cgroup として管理しています。なお、非特権プロセスに対しては cgroup からの 「脱退」 は認められていませんので、サービスが起動した全てのプロセスを、効率的に名前で管理できるようになっています。
サービスに属する全てのプロセスを一覧表示するには、 systemd-cgls
コマンドを使用します。たとえば下記のようになります:
#
systemd-cgls --no-pager
├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 20
├─user.slice
│ └─user-1000.slice
│ ├─session-102.scope
│ │ ├─12426 gdm-session-worker [pam/gdm-password]
│ │ ├─15831 gdm-session-worker [pam/gdm-password]
│ │ ├─15839 gdm-session-worker [pam/gdm-password]
│ │ ├─15858 /usr/lib/gnome-terminal-server
[...]
└─system.slice
├─systemd-hostnamed.service
│ └─17616 /usr/lib/systemd/systemd-hostnamed
├─cron.service
│ └─1689 /usr/sbin/cron -n
├─postfix.service
│ ├─ 1676 /usr/lib/postfix/master -w
│ ├─ 1679 qmgr -l -t fifo -u
│ └─15590 pickup -l -t fifo -u
├─sshd.service
│ └─1436 /usr/sbin/sshd -D
[...]
cgroup についての詳細は、 第10章 「カーネルコントロールグループ」 をお読みください。
10.6.6項 「カーネルコントロールグループ (cgroups)」 でも説明しているとおり、 System V init のシステムでは、プロセスとサービスとの関係性の管理が確実にできるという保証がありませんでした。これにより、サービスを終了させて全ての子プロセスを確実に終了させるということも難しくなっていました。サービスが正しく終了できない場合、子プロセスがゾンビとして残ってしまうこともありました。
それぞれのサービスを cgroup に閉じこめる、という systemd
の考え方により、サービスの全ての子プロセスを明確に管理できるようになるほか、これによってこれらのプロセスそれぞれに対して、シグナルを送信できる仕組みも提供できるようになっています。サービスに対してシグナルを送信するには、 systemctl kill
コマンドを使用します。利用可能なシグナルの一覧については、 man 7 signals
をお読みください。
SIGTERM
の送信SIGTERM
は既定のシグナルです。
>
sudo
systemctl kill サービス名
-s
オプションを使用して、送信すべきシグナルを指定します。
>
sudo
systemctl kill -s シグナル名 サービス名
既定では、 kill
サブコマンドは指定した cgroup 内の 「全ての」 プロセスに対してシグナルを送信しますが、 control
(制御プロセスのみ) または main
(メインプロセスのみ) のオプションを指定して、特定のプロセスのみに送信することもできます。 main
は特に、 SIGHUP
を送信して設定ファイルを再読み込みさせるような場合に便利です:
>
sudo
systemctl kill -s SIGHUP --kill-who=main サービス名
D-Bus サービスは systemd
クライアントと systemd マネージャ (プロセス ID=1) との間のメッセージバスとなるサービスです。 dbus
は単独のデーモンではありますが、初期化インフラストラクチャでは必須の構成部品です。
動作中のシステムで dbus
を終了したり再起動したりする行為は、 PID 1 の終了や再起動と同様であり、 systemd
のクライアント/サーバ間通信を破壊してしまい、 systemd
が正しく動作しなくなってしまいます。
そのため、 dbus
の終了や再起動は非推奨であるほか、サポートの対象外となっています。
dbus
それ自身や dbus
に関連するパッケージを更新した場合、システムの再起動が必要となります。システムの再起動が必要となっているかどうかを調べたい場合は、 sudo zypper ps -s
と入力して実行してください。表示されているサービスの中に dbus
が存在する場合、システムの再起動が必要となります。
なお自動更新の設定で、システムの再起動を必要とするパッケージの更新を行わないようにしている場合でも、 dbus
は更新されてしまうことに注意してください。
既定では、 systemd
はそれほど多くの出力を行いません。サービスが問題なく起動できた場合は、全く出力を返しません。失敗した場合にのみ、短いエラーメッセージを表示します。しかしながら、 systemctl status
コマンドを使用すると、サービスの起動や動作に関して様々なデバッグメッセージを取得することができます。
systemd
には独自のログ記録機構 (「ジャーナル」 と呼びます) が備えられています。これにより、サービスのメッセージと状態に関するメッセージの両方を取得することができます。 status
サブコマンドは tail
コマンドに似た仕組みであるほか、異なる形式でログメッセージを表示することができるなど、パワフルなデバッグツールとして便利な存在になっています。
サービスの起動に失敗した場合は、 systemctl status サービス名
を実行することで、詳細なエラーメッセージを取得することができます:
#
systemctl start apache2 Job failed. See system journal and 'systemctl status' for details.#
systemctl status apache2 Loaded: loaded (/usr/lib/systemd/system/apache2.service; disabled) Active: failed (Result: exit-code) since Mon, 04 Apr 2018 16:52:26 +0200; 29s ago Process: 3088 ExecStart=/usr/sbin/start_apache2 -D SYSTEMD -k start (code=exited, status=1/FAILURE) CGroup: name=systemd:/system/apache2.service Apr 04 16:52:26 g144 start_apache2[3088]: httpd2-prefork: Syntax error on line 205 of /etc/apache2/httpd.conf: Syntax error on li...alHost>
status
サブコマンドは、既定では最新の 10 件のメッセージのみを表示します。表示する件数を変更したい場合は、 --lines=N
パラメータを指定します:
>
sudo
systemctl status chronyd>
sudo
systemctl --lines=20 status chronyd
サービスメッセージを 「リアルタイムに」 表示したい場合は、 --follow
オプションを指定します。これは tail
-f
に似た動作になります:
>
sudo
systemctl --follow status chronyd
--output=モード
オプションを指定すると、サービスメッセージの出力形式を変更することができます。最もよく使用するモードは下記のとおりです:
short
既定の出力形式です。ログメッセージを読みやすいタイムスタンプ表示と共に出力します。
verbose
全ての項目を出力する形式です。
cat
タイムスタンプ表示のない簡潔な出力形式です。
systemd
タイマーユニット #Edit sourcesystemd
のタイマーユニットは cron と同等の機能を提供するもので、 Linux でジョブのスケジュールを行うことができる仕組みです。 systemd
のタイマーユニットは cron と同じ目的で提供されるものですが、いくつかの追加機能があります。
別の systemd
サービスに依存する形でジョブをスケジュールすることができます。
タイマーユニットの取り扱いが systemd
のサービスと同じであるため、 systemctl
を利用して管理することができます。
タイマーはリアルタイムタイマーと単調タイマーのいずれか、もしくは両方を指定することができます。
タイマーユニットは systemd
のジャーナル内に記録されるため、監視やトラブルシューティングが容易です。
systemd
のタイマーユニットのファイル名は、拡張子が .timer
になっているため、簡単に識別することができます。
systemd
タイマーの種類 #Edit sourceタイマーユニットでは、間隔の指定だけでなく、具体的な日時を指定することもできます。
cron のジョブと同様に、リアルタイムタイマーは特定の日時に到達することで実行するタイマーです。リアルタイムタイマーは、 OnCalendar
と呼ばれるオプションで指定します。
単調タイマーは、起動してからの経過時間を元に実行します。起動はシステムの起動のほか、ユニットの有効化が基準となります。単調タイマーの場合には複数のオプションが提供されていて、それぞれ OnBootSec
, OnUnitActiveSec
, OnTypeSec
を使用します。単調タイマーはシステムの再起動が発生するとリセットされ、間隔が維持されなくなります。
systemd
とサービスユニット #Edit sourcesystemd
のタイマーユニットにはそれぞれ対応するユニットファイルが存在しています。言い換えると、 .timer
ファイルは、対応する .service
ファイルを有効化し、管理する役割を担っていることになります。タイマーとしてユニットファイルを使用する場合は、 .service
ファイル内に [Install]
セクションを指定する必要はありません。これは、タイマー側で管理するためです。
systemd
のタイマーユニットの基本を理解するため、例として foo.sh
というシェルスクリプトをタイマーユニットで起動する場合を想定してみます。
最初に systemd
のサービスユニットファイルを作成します。このファイルがシェルスクリプトの制御を行うことになります。テキストエディタを起動して、下記のような内容でサービスユニットファイルの設定を作成してください:
[Unit] Description="Foo shell script" [Service] ExecStart=/usr/local/bin/foo.sh
このファイルを、 /etc/systemd/system/
ディレクトリ内の foo.service
という名前で保存します。
次にタイマーユニットを作成します。テキストエディタで下記のような内容を記述します:
[Unit] Description="Run foo shell script" [Timer] OnBootSec=5min OnUnitActiveSec=24h Unit=foo.service [Install] WantedBy=multi-user.target
上記の例では、 [Timer]
セクションで対応するサービスユニットファイルを指定 ( foo.service
) し、起動間隔を指定しています。この例では OnBootSec
を指定していますので、まずはシステムの起動後を基準として 5 分間隔でシェルスクリプトを起動することになります。また、 OnUnitActiveSec
の指定も存在することから、ユニットの有効化から 24 時間が経過するタイミングでも起動することになります (つまり 1 日 1 回) 。また、 WantedBy
の指定では、システムがマルチユーザターゲットに到達している場合にタイマーを開始すべきである旨を示しています。
単調タイマーの代わりに、 OnCalendar
でリアルタイムタイマーを指定することもできます。たとえば下記のように指定すると、月曜日の 12:00 を開始時点として、週 1 回の間隔で対応するサービスを起動することができます。
[Timer] OnCalendar=weekly Persistent=true
ここでは Persistent=true
を指定していますが、これはシステムが直前の起動時間を判断できない場合 (たとえばシステムの電源を落としていた場合) に、タイマーを即時に起動することを示しています。
このほか、 OnCalendar
では 曜日 年-月-日 時:分:秒
のような書式で指定することで、特定の日時に起動を行うこともできます。たとえば下記のように指定すると、毎日 AM5:00 にサービスを起動することになります:
OnCalendar=*-*-* 5:00:00
cron と同様にアスタリスク記号で任意の数値を、カンマ区切りで複数の数値を指定することもできます。また、 2 つの値の間に .. を入れることで、連続した値を指定することもできます。たとえば下記の例は、毎月最初の金曜日の PM6:00 に起動する意味になります:
OnCalendar=Fri *-*-1..7 18:00:00
複数の日時を指定したい場合は、 OnCalendar
の項目を複数に分割してください:
OnCalendar=Mon..Fri 10:00 OnCalendar=Sat,Sun 22:00
上記の例では、月曜日から金曜日までの AM10:00 と、週末の PM10:00 にそれぞれ起動する意味になります。
タイマーユニットファイルを作成したら、 /etc/systemd/system/
ディレクトリ内に foo.timer
というファイル名で保存してください。ユニットファイルが正しく設定できているかどうかを確認するには、下記のようなコマンドを実行します:
>
sudo
systemd-analyze verify /etc/systemd/system/foo.*
上記のコマンドを実行しても何も出力されなければ、問題なくユニットファイルが設定できていることを示しています。
タイマーを開始するには sudo systemctl start foo.timer
を、システムの起動時にタイマーを有効化するには sudo systemctl enable foo.timer
をそれぞれ実行してください。
systemd
タイマーの管理 #Edit sourceタイマーは systemd
のユニットとして扱われるため、管理も systemctl
コマンドで行います。タイマーを起動するには systemctl start
を、タイマーを有効化するには systemctl enable
をそれぞれ実行してください。これに加えて、 systemctl list-timers
を実行すると、現在有効なタイマーの一覧を表示することができます。有効になっていないタイマーも含めたい場合は、 systemctl list-timers --all
を実行してください。
systemd
について、より詳しく知りたい場合は、下記のオンラインリソースをお読みください:
systemd
for administratorssystemd
の作者のうちの 1 人である Lennart Pöttering 氏が投稿したブログ記事 (本章記述時点で 13 個, いずれも英語): https://0pointer.de/blog/projects/