systemd はシステムの準備を担っているプロセスで、プロセス 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/ をお読みください。
systemdWindows Subsystem for Linux (WSL) は Microsoft Windows オペレーティングシステムの中で Linux アプリケーションおよびディストリビューションを動作させることができる仕組みです。既定の WSL は systemd ではなく独自の init プログラムを使用しますので、 WSL 内で動作している openSUSE Leap で systemd を使用したい場合は、まず wsl_systemd パターンをインストールします。これにより、必要な設定を自動的に行うことができます:
>sudozypper 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 , ...) 。サービス管理コマンドの書式は下記のとおりです:
systemdsystemctl reload|restart|start|status|stop|... サービス名_(複数可)
rcサービス名 reload|restart|start|status|stop|...
systemd では、複数のサービスを一括で管理することができます。 System V init ではそれぞれの init スクリプトを別々に動作させる必要がありましたが、 systemd では下記のように実行するだけです:
>sudosystemctl start 1_つめのサービス名 2_つめのサービス名
システムで利用可能な全てのサービスを一覧表示するには、下記のように実行します:
>sudosystemctl 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 | lesssystemd は 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 という名前のディレクトリを作成します。
>sudomkdir /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 サービスを再起動するだけです。
>sudosystemctl 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.servicesystemd-analyze cat-config デーモン名またはパス: systemd デーモンに対する設定ファイルとドロップインの内容をコピーします。たとえば下記のように実行します:
> systemd-analyze cat-config systemd/journald.confxinetd から 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=socketsystemd の 「ソケット」 および 「サービス」 ファイルの全オプションを知りたい場合は、それぞれ 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 の設定を再読み込みし、新しいターゲットが利用できるようにします:
>sudosystemctl 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 タイマーの状態を取得するには、下記のように実行します:
>sudosystemctl 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 で終わらなければなりません。
>sudosystemctl snapshot スナップショット名.snapshot
>sudosystemctl delete スナップショット名.snapshot
>sudosystemctl show スナップショット名.snapshot
>sudosystemctl 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 で実行します):
>sudosystemctl daemon-reload>sudosystemctl enable before
なお、サービスファイルを変更したあとは、下記を実行してください:
>sudosystemctl 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 は既定のシグナルです。
>sudosystemctl kill サービス名
-s オプションを使用して、送信すべきシグナルを指定します。
>sudosystemctl kill -s シグナル名 サービス名
既定では、 kill サブコマンドは指定した cgroup 内の 「全ての」 プロセスに対してシグナルを送信しますが、 control (制御プロセスのみ) または main (メインプロセスのみ) のオプションを指定して、特定のプロセスのみに送信することもできます。 main は特に、 SIGHUP を送信して設定ファイルを再読み込みさせるような場合に便利です:
>sudosystemctl 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 パラメータを指定します:
>sudosystemctl status chronyd>sudosystemctl --lines=20 status chronyd
サービスメッセージを 「リアルタイムに」 表示したい場合は、 --follow オプションを指定します。これは tail -f に似た動作になります:
>sudosystemctl --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 というファイル名で保存してください。ユニットファイルが正しく設定できているかどうかを確認するには、下記のようなコマンドを実行します:
>sudosystemd-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/