systemd
関連記事
プロジェクトウェブページ より:
- systemd は Linux 環境の基本構成スイートであり、SysV や LSB init スクリプトと互換性のある、Linux 用のシステム・サービスマネージャです。systemd はサービスの起動を積極的に並行化します。また、ソケットや D-Bus のアクティベーションを使用してサービスを起動し、必要なデーモンの開始を行うことができ、Linux の cgroups によるプロセス管理ができます。システム状態のスナップショット作成と復元、(自動) マウントポイントの管理、煩雑な依存関係に基づいたサービスのコントロールを処理します。systemd は sysvinit の代替として SysV や LSB init スクリプトをサポートしています。init としての機能以外にも、ログデーモンやホストネーム・時刻・ロケールなどシステムの基本設定を制御するユーティリティ、ログイン中のユーザーから実行中のコンテナや仮想マシン、システムアカウントまで管理する機能、ネットワーク設定や時刻同期あるいは名前解決などを管理するシンプルなデーモンも含まれています。
目次
- 1 systemctl の基本的な使い方
- 2 ユニットファイル
- 3 ターゲット
- 4 一時ファイル
- 5 タイマー
- 6 マウント
- 7 Journal
- 8 ヒントとテクニック
- 9 トラブルシューティング
- 9.1 systemd のエラーを調査する
- 9.2 ブート問題の診断
- 9.3 特定のサービスの問題を診断
- 9.4 シャットダウン/再起動にものすごく時間がかかる
- 9.5 短いプロセスがログを出力しない
- 9.6 クラッシュしたアプリケーションのダンプのジャーナルを無効にする
- 9.7 再起動やシャットダウン時のエラーメッセージ
- 9.8 少しづつ起動時間が長くなっている
- 9.9 起動時に systemd-tmpfiles-setup.service の実行に失敗する
- 9.10 systemctl enable で /etc/systemd/system にシンボリックリンクが作成されない
- 9.11 起動時に表示される systemd のバージョンがインストールしているパッケージのバージョンと違う
- 9.12 リモートマシンで緊急モードを無効化
- 10 参照
systemctl の基本的な使い方
systemd を管理したり内部情報を見るために使うメインのコマンドが systemctl
です。システムの状態を確かめたりシステムやサービスを管理するために使うのは使い方の一部です。詳しくは systemctl(1) を見て下さい。
システムの状態を分析する
システムの状態を表示:
$ systemctl status
実行中のユニットを一覧する:
$ systemctl
または:
$ systemctl list-units
失敗したユニットを一覧する:
$ systemctl --failed
実行可能なユニットファイルは /usr/lib/systemd/system/
や /etc/systemd/system/
にあります (後者が優先的に使われます)。インストールされたユニットを一覧するには:
$ systemctl list-unit-files
ユニットを使う
ユニットには、例えば、サービス (.service
) やマウントポイント (.mount
)、デバイス (.device
)、ソケット (.socket
) などがあります。
systemctl
を使うとき、一般的には拡張子 (suffix) を含むユニットファイルの完全な名前を指定する必要があります。例えば、sshd.socket
のように。しかし、以下のような場合には省略形が存在します:
- 拡張子が指定されない場合、systemctl は
.service
とみなします。例えばnetctl
とnetctl.service
は同じように扱われます。 - マウントポイントは自動的に対応する
.mount
ユニットとして扱われます。例えば、/home
を指定することはhome.mount
の指定と同じです。 - マウントポイントと同じく、デバイスも自動的に対応する
.device
ユニットとして扱われます。従って、/dev/sda2
の指定はdev-sda2.device
と同じです。
詳細は systemd.unit(5) を見てください。
いますぐユニットを実行:
# systemctl start unit
いますぐユニットを停止:
# systemctl stop unit
ユニットを再始動:
# systemctl restart unit
ユニットに設定を再読み込みするように通知:
# systemctl reload unit
ユニットの状態を表示(動いているかどうかなど):
$ systemctl status unit
有効化(起動時に自動で実行するよう設定)されているかどうか表示:
$ systemctl is-enabled unit
起動時に実行されるように有効化する:
# systemctl enable unit
ユニットを有効化して今すぐ起動する:
# systemctl enable --now unit
システム起動時に実行されないように無効化する:
# systemctl disable unit
ユニットをマスクすることで起動しないようにできます:
# systemctl mask unit
ユニットのマスクを解除:
# systemctl unmask unit
ユニットに関連する(ユニットファイルによってサポートされている)マニュアルページを参照する:
$ systemctl help unit
systemd をリロードし、新しい、もしくは変化のあったユニットをスキャンする:
# systemctl daemon-reload
電源管理
電源管理には polkit
が必要です。
ローカルの systemd-logind
のユーザーセッション中で、他のセッションがアクティブでなければ、ルート権限なしで以下のコマンドが使えます。そうでなければ (他のユーザが tty でログインしている場合など)、systemd は自動的に root のパスワードを要求するでしょう。
再起動:
$ systemctl reboot
シャットダウンしてパワーオフ:
$ systemctl poweroff
サスペンド(待機):
$ systemctl suspend
ハイバネート(休止):
$ systemctl hibernate
ハイブリッドスリープ (もしくは suspend-to-both):
$ systemctl hybrid-sleep
ユニットファイル
systemd の ユニットファイル の構文は XDG の Desktop Entry Specification である .desktop から影響を受けています。そして .desktop は Microsoft Windows の .ini ファイルからインスパイアされています。ユニットファイルは複数の場所に配置されます (配置場所のリストを確認するには systemctl show --property=UnitPath
を実行してください)。優先度が低い方から説明すると:
/usr/lib/systemd/system/
: インストールしたパッケージに含まれているユニット/etc/systemd/system/
: システムの管理者がインストールしたユニット
依存関係を解決する
systemd ではユニットファイルを適切に書くことで依存関係を解決します。一番典型的なケースは、ユニット A
が走る前に、ユニット A
がユニット B
を必要としている場合です。この場合、A
の [Unit]
セクションに Requires=B
と After=B
を加えます。依存が必然ではない場合、代わりに Wants=B
と After=B
を加えます。Wants=
と Requires=
は After=
を含まないことに注意してください、もし After=
を明記しなかったときは、2つのユニットは並行して実行されます。
基本的に、依存関係はターゲットではなくサービスに記述します。例えば、network.target
はネットワークインターフェースを設定する全てのサービスによって使われるので、カスタムユニットを起動させる順番は network.target
が起動し終わってからにする必要があります。
タイプ
カスタムサービスファイルを書くときにどのスタートアップタイプを使うべきか考える必要があります。タイプは [Service]
セクションの Type=
パラメータで設定します。より詳しい説明は systemd.service(5) を見て下さい。
Type=simple
(デフォルト): systemd はプロセスを起動した時点でサービスが立ち上がったとみなします。プロセスをフォークすることはできません。ソケットアクティベーション以外で他のサービスが必要な場合に、このタイプを使ってはいけません。Type=forking
: 起動したプロセスが一旦フォークし、親プロセス側が終了したときに、 systemd はサービスが立ち上がったとみなします。このタイプでなくてもかまわないとき以外は、古典的なデーモンにはこのタイプを使って下さい。またPIDFile=
を指定することで systemd はメインプロセスの情報を追い続けます。Type=oneshot
: シングルジョブを行い終了するスクリプト用のタイプです。またRemainAfterExit=yes
を設定することで systemd はプロセスが終了した後もサービスがアクティブだとみなします。Type=notify
:Type=simple
と同じですが、利用可能になったときにデーモンが systemd に信号を送るように条件がつけられます。この通知のリファレンス実装はlibsystemd-daemon.so
によって提供されています。Type=dbus
: 指定のBusName
が DBus のシステムバスに乗ったときに使うことができるサービス。Type=idle
: idle の挙動はType=simple
と非常に似ています。ただし、サービスバイナリの実行は全てのジョブが処理されるまで待たされます。これを使えば、コンソールに状態を出力するシェルサービスで、出力が混じってしまうのを避けることができます。
ユニットファイルの編集
パッケージに入っているユニットファイルを編集する方法は2つあります: 新しいユニットファイルで完全に置き換えるか、ドロップインファイルを作成して既存のユニットファイルに上書きして適用させるかです。どちらの方法でも、変更を加えた後はユニットをリロードする必要があります。systemctl edit
でユニットを編集するか (自動でユニットがリロードされます) または次のコマンドで全てのユニットをリロードしてください:
# systemctl daemon-reload
ユニットファイルを置換する
ユニットファイル /usr/lib/systemd/system/unit
を置き換えたいときは、/etc/systemd/system/unit
ファイルを作成してユニットを再有効することでシンボリックリンクをアップデートします:
# systemctl reenable unit
もしくは、次を実行:
# systemctl edit --full unit
このコマンドはテキストエディタで /etc/systemd/system/unit
を開いて (ファイルが存在しない場合はインストールされているユニットがコピーされます)、編集を終えた時に自動的にユニットをリロードします。
ドロップインファイル
ユニットファイル /usr/lib/systemd/system/unit
のドロップインファイルを作成するには、/etc/systemd/system/unit.d/
という名のディレクトリ (例: /etc/systemd/system/httpd.service.d/
) を作成してその中に *.conf
を配置します。このファイルを使ってオプションを上書きしたり追加してください。systemd が *.conf
ファイルをパースして元のユニットファイルの一番上に設定を適用します。
ドロップインファイルを作成する一番簡単な方法は次のコマンドを実行することです:
# systemctl edit unit
テキストエディタで /etc/systemd/system/unit.d/override.conf
ファイルが開かれ (必要であればファイルが作成されます)、編集を終えた時に自動でユニットがリロードされます。
初期状態にリバート
systemctl edit
を使って変更したユニットを元に戻したい場合、以下のコマンドを実行:
# systemctl revert unit
サンプル
例えば、ユニットに依存するデーモンを追加したい場合、以下のファイルを作成することができます:
/etc/systemd/system/<unit>.d/customdependency.conf
[Unit] Requires=<new dependency> After=<new dependency>
oneshot
タイプでないユニットの ExecStart
ディレクティブを置き換えるには、以下のファイルを作成します:
/etc/systemd/system/unit.d/customexec.conf
[Service] ExecStart= ExecStart=new command
サービスが自動的に再起動されるようにするには:
/etc/systemd/system/unit.d/restart.conf
[Service] Restart=always RestartSec=30
ターゲット
Systemd ではランレベルに似たものとしてターゲットを使っています。ただしその挙動には少し違いがあります。それぞれのターゲットはナンバリングされる代わりに名前がつけられ、ある特定の目的のために作られ、複数のターゲットを同時に有効にできるようになっています。ターゲットによっては、他のターゲットのサービスを全て引継ぎ、そこにサービスを追加するよう実装されています。一般的な SystemVinit ランレベルに擬態する systemd ターゲットもあり、親しみのある telinit RUNLEVEL
コマンドを使って使用するターゲットを切り替えることが可能です。
現在のターゲットを獲得
systemd では runlevel
の代わりに次のコマンドが使われます:
$ systemctl list-units --type=target
カスタムターゲットを作る
標準の Fedora インストールではランレベルごとに特定の目的が設定されています; 0, 1, 3, 5, 6 のランレベルには特定の sytemd ターゲットと一対一の対応関係が存在します。残念ながら、ユーザー定義のランレベル (2 や 4 など) で同じことをする良い方法はありません。もしあなたがそうしたいならば、既に存在しているランレベルをベースに新しい systemd ターゲットを /etc/systemd/system/<your target>
として作り (/usr/lib/systemd/system/graphical.target
がサンプルになるかもしれません)、/etc/systemd/system/<your target>.wants
ディレクトリを作って、有効にしたいサービスに /usr/lib/systemd/system/
からシンボリックリンクを貼ることが示唆されています。
SysV ランレベルと systemd ターゲットの対応表
SysV ランレベル | systemd ターゲット | 説明 |
---|---|---|
0 | runlevel0.target, poweroff.target | システムを停止。 |
1, s, single | runlevel1.target, rescue.target | シングルユーザーモード。 |
2, 4 | runlevel2.target, runlevel4.target, multi-user.target | ユーザー定義・サイト指定ランレベル。デフォルトでは、3 と同一。 |
3 | runlevel3.target, multi-user.target | マルチユーザー、非グラフィカル。一般的にマルチコンソールやネットワークを介してログインするのに使われます。 |
5 | runlevel5.target, graphical.target | マルチユーザー、グラフィカル。通常、ランレベル 3 の全てのサービスにグラフィカルログインを付加。 |
6 | runlevel6.target, reboot.target | 再起動 |
emergency | emergency.target | 緊急シェル |
現在のターゲットを変更する
systemd ではターゲットは"ターゲットユニット"を通して扱うことができます。ターゲットを変えるには次のようにします:
# systemctl isolate graphical.target
これは現在のターゲットを変えるだけで、次の起動時には影響がありません。SysVinit での、telinit 3
や telinit 5
のようなコマンドと同じです。
起動時のデフォルトターゲットを変更する
標準のターゲットは default.target
で、デフォルトで (昔のランレベル 5 に大体対応している) graphical.target
にエイリアスされています。起動時のデフォルトターゲットを変更するには、以下のカーネルパラメータのどれかをブートローダに加えてください:
systemd.unit=multi-user.target
(昔のランレベル 3 とほぼ同じ)。systemd.unit=rescue.target
(昔のランレベル 1 とほぼ同じ)。
また、ブートローダには修正を加えずに default.target
を変えることもできます。systemctl
を使います:
# systemctl set-default multi-user.target
一時ファイル
Systemd-tmpfiles は /usr/lib/tmpfiles.d/
と /etc/tmpfiles.d/
下にある設定ファイルを読み、通常 /run
や /tmp
などのディレクトリに存在している一時ファイル・ディレクトリの作成、内容の消去、削除などを行います。それぞれの設定ファイル名は /etc/tmpfiles.d/<program>.conf
です。/usr/lib/tmpfiles.d/
に同名の設定ファイルがある場合上書きされます。
tmpfiles は一時ファイルを必要とするデーモンのサービスファイルに同梱されます。例えば Samba デーモンは /run/samba
を一時ディレクトリとして使用するため、正しいパーミッションに設定されていることを期待します。これを表す tmpfile は以下のようになります:
/usr/lib/tmpfiles.d/samba.conf
D /run/samba 0755 root root
tmpfiles は起動時にファイルに値を書き込むのにも使われることがあります。例えば、/etc/rc.local
を使って USB デバイスからの wakeup を無効化する echo USBE > /proc/acpi/wakeup
は、tmpfile では以下のように書けます:
/etc/tmpfiles.d/disable-usb-wake.conf
w /proc/acpi/wakeup - - - - USBE
詳細は systemd-tmpfiles(8) や tmpfiles.d(5) の man ページを参照してください。
タイマー
タイマーは ".timer" で終わる名前を持つユニット設定ファイルで、時間に基づく実行を行うために、systemd で制御・管理するタイマーの情報をエンコードしています。systemd/タイマー を参照してください。
マウント
systemd は System V init を置き換えるため、/etc/fstab
に指定されたマウントも処理します。起動時、またはシステムマネージャの設定の再読込時に systemd-fstab-generator(8) によって /etc/fstab
のエントリが systemd ユニットに変換されます。
fstab の通常機能だけでなく、x-systemd.
が前に付く特殊なマウントオプションを利用することが可能です。拡張機能を使用する具体的な例として Fstab#systemd による自動マウントには必要に応じて自動マウントする方法が書かれています。拡張機能のドキュメントは [2] を参照してください。
Journal
systemd は、バージョン 38 から自前のログシステムである journal を搭載しています。従って、syslog デーモンを起動する必要はもはやありません。ログを読むには:
# journalctl
デフォルトで (/etc/systemd/journald.conf
内で Storage=
が auto
に設定されているとき)、journal は /var/log/journal/
へ書き込みを行います。Arch Linux では /var/log/journal/
ディレクトリは systemd の一部であり、あなたや何らかのプログラムがディレクトリを削除した場合、systemd は自動で再作成しませんが、systemd のアップデートがあるとディレクトリは作りなおされます。それまでログは代わりに /run/systemd/journal
に書き込まれます。ただし再起動時にこのログは消失してしまいます。
Systemd ジャーナルはメッセージをプライオリティレベルとファシリティで分類します。古典的な Syslog プロトコルと対応しています (RFC 5424)。
プライオリティレベル
メッセージの重要度は syslog の重大度コード (systemd ではプライオリティと呼ばれます) を使って示されます RFC 5424 Section 6.2.1:
値 | 重大度 | キーワード | 説明 | 例 |
---|---|---|---|---|
0 | Emergency | emerg | システムは利用不可能 | 重大なカーネルのバグ/systemd によってコアダンプが作成された。アプリケーションが使用するレベルではありません。 |
1 | Alert | alert | 即時対応が必要 | 重要なサブシステムが機能していない/データが消失している。kernel: BUG: unable to handle kernel paging request at ffffc90403238ffc 。
|
2 | Critical | crit | 緊急状態 | クラッシュ/コアダンプ。systemd-coredump[25319]: Process 25310 (plugin-containe) of user 1000 dumped core 。X11 などのシステムにとって重要なアプリケーションが機能を失っている。
|
3 | Error | err | エラー状態 | 重大度は低いエラー: kernel: usb 1-3: 3:1: cannot get freq at ep 0x84 ,systemd[1]: Failed unmounting /var. , libvirtd[1720]: internal error: Failed to initialize a valid firewall backend )。
|
4 | Warning | warning | エラーが発生する前に対応が必要 | ルートファイルシステム以外のファイルシステムの空き領域が 1GB しかない。org.freedesktop. Notifications[1860]: (process:5999): Gtk-WARNING **: Locale not supported by C library. Using the fallback 'C' locale 。
|
5 | Notice | notice | 通常ではないイベントが発生しているがエラー状態ではない | systemd[1]: var.mount: Directory /var to mount over is not empty, mounting anyway , gcr-prompter[4997]: Gtk: GtkDialog mapped without a transient parent. This is discouraged 。
|
6 | Informational | info | 何も対応が必要な通常のメッセージ | lvm[585]: 7 logical volume(s) in volume group "archvg" now active 。
|
7 | Debug | debug | アプリケーションをデバッグするのに役立つ情報 | kdeinit5[1900]: powerdevil: Scheduling inhibition from ":1.14" "firefox" with cookie 13 and reason "screen" 。
|
上記のレベルで問題が確認できない場合、上下のプライオリティレベルも調べてみてください。厳しくルールが決められているわけではありません。発生する確率が高いエラーは開発者によってプライオリティが低く設定されている可能性があります。逆に、緊急度が高いメッセージが大量に出力されることもありますが、必ずしも切羽詰まった状況を表しているとは限りません。
ファシリティ
メッセージを出力したプログラムのタイプは syslog のファシリティコードで指定されます RFC 5424 Section 6.2.1:
ファシリティコード | キーワード | 説明 | 情報 |
---|---|---|---|
0 | kern | カーネルメッセージ | |
1 | user | ユーザーレベルメッセージ | |
2 | メールシステム | 詳しくは mail(1) を見てください。 | |
3 | daemon | システムデーモン | systemd やサブシステムを含む全てのデーモン |
4 | auth | セキュリティ/認証メッセージ | ファシリティ10もあります。 |
5 | syslog | syslogd の内部メッセージ | syslogd 用のファシリティなので systemd は使用していません (ファシリティ3を使います)。 |
6 | lpr | ラインプリンターサブシステム (旧式のサブシステム) | |
7 | news | ネットワークニュースサブシステム (旧式のサブシステム) | |
8 | uucp | UUCP サブシステム (旧式のサブシステム) | |
9 | クロックデーモン | systemd-timesyncd | |
10 | authpriv | セキュリティ/認証メッセージ | ファシリティ4もあります。 |
11 | ftp | FTP デーモン | |
12 | - | NTP サブシステム | |
13 | - | log audit | |
14 | - | log alert | |
15 | cron | スケジューリングデーモン | |
16 | local0 | ローカル使用 0 (local0) | |
17 | local1 | ローカル使用 1 (local1) | |
18 | local2 | ローカル使用 2 (local2) | |
19 | local3 | ローカル使用 3 (local3) | |
20 | local4 | ローカル使用 4 (local4) | |
21 | local5 | ローカル使用 5 (local5) | |
22 | local6 | ローカル使用 6 (local6) | |
23 | local7 | ローカル使用 7 (local7) |
意味のあるファシリティは次の7つになります: 0, 1, 3, 4, 9, 10, 15。
フィルタリング
journalctl
を使って出力にフィルタをかけることができます。表示したりフィルタリングをするメッセージが大量にある場合、かなり時間がかかります。コマンドの出力は相当の時間がたってから表示されるかもしれません。
例:
- 起動時からの全てのメッセージを表示:
# journalctl -b
場合によっては最新のブートメッセージではなく、以前のブートのメッセージを読みたいことがあります (例えば復旧できないシステムクラッシュが起こった場合)。-b
フラグに任意のパラメータを付けることでメッセージをオフセットして読むことが可能です:journalctl -b -0
は最新のブートのメッセージを、journalctl -b -1
は一つ前のブートのメッセージを表示しjournalctl -b -2
は二つ前、と続きます。journalctl --list-boots
を使うことで数字を確認できます。詳しくは journalctl(1) を見て下さい、セマンティックスはより強力です。 - 特定の日付 (任意で時間も指定可能) からのメッセージを全て表示:
# journalctl --since="2012-10-30 18:17:16"
- 20分前からのメッセージを全て表示:
# journalctl --since "20 min ago"
- 新しいメッセージを表示:
# journalctl -f
- 特定の実行ファイルによる全てのメッセージを表示:
# journalctl /usr/lib/systemd/systemd
- 特定のプロセスによる全てのメッセージを表示:
# journalctl _PID=1
- 特定のユニットによる全てのメッセージを表示:
# journalctl -u netcfg
- カーネルのリングバッファを表示:
# journalctl -k
- プライオリティレベルがエラー・クリティカル・アラートのメッセージだけを表示:
# journalctl -p err..alert
journalctl -p 3..1
と数字を使うこともできます。journalctl -p 3
のようにひとつだけ指定した場合、指定されたプライオリティよりも高いレベルのメッセージも表示されます。 - syslog の facility をフィルタリングすることで
auth.log
と同等の内容を表示:# journalctl SYSLOG_FACILITY=10
詳しくは journalctl(1), systemd.journal-fields(7) や Lennart のブログ記事 を見て下さい。
journal のサイズ制限
journal が永続的(不揮発性)の場合、デフォルトではファイルシステムの容量の 10% に制限されます (4 GiB が上限)。例えば、/var/log/journal
が 20GiB の root パーティションにのっている場合、2GiB がログデータの上限になります。/etc/systemd/journald.conf
の SystemMaxUse
を変更すれば、最大サイズを変更できます。例えば制限を 50Mib にする場合、適切な行を次のようにアンコメント・編集します:
SystemMaxUse=50M
上記のように設定ファイルを編集する代わりにドロップインファイルを使用する方法もあります。その場合 [Journal]
ヘッダーを使って以下のように記述してください:
/etc/systemd/journald.conf.d/00-journal-size.conf
[Journal] SystemMaxUse=50M
詳細は journald.conf(5) を参照してください。
ジャーナルファイルを手動で消去
journal のファイルは /var/log/journal
に存在します。rm
で消去することもできますが、journalctl
を使って消去することも可能です。例:
- 使用ディスク容量が 100M 以下になるまで journal ファイルを削除する:
# journalctl --vacuum-size=100M
- 2週間以上前のデータを含んでいる journal ファイルを削除する:
# journalctl --vacuum-time=2weeks
詳しくは journalctl(1) を見て下さい。
journald と syslog の結合
古典的な syslog との互換性は、すべてのメッセージがソケット /run/systemd/journal/syslog
に転送されることで実現されます。syslog を使うには、/dev/log/
の代わりにこのソケットを指定します (公式アナウンス)。
systemd 216 からオーバーヘッドを減らすために journald.conf
のソケットの転送はデフォルトで無効になっています (ForwardToSyslog=no
)。rsyslog や syslog-ng (3.6 以降) は 自力で journal からメッセージを取得するためです。
設定の詳細は Syslog-ng#概要, Syslog-ng#syslog-ng と systemd journal, rsyslog を見て下さい。
journald を /dev/tty12 に転送する
ドロップインディレクトリ /etc/systemd/journald.conf.d
を作成して、ディレクトリの中に fw-tty12.conf
ファイルを作成してください:
/etc/systemd/journald.conf.d/fw-tty12.conf
[Journal] ForwardToConsole=yes TTYPath=/dev/tty12 MaxLevelConsole=info
次を実行して journald を再起動してください:
# systemctl restart systemd-journald
別のジャーナルを指定して表示
ライブ環境から起動して本番環境を修復する場合など、トラブルが発生した他のシステムのログを確認する必要があるような場合、/mnt
などにディスクをマウントしてから、ジャーナルのパスを -D
/--directory
で指定することができます:
$ journalctl -D /mnt/var/log/journal -xe
ヒントとテクニック
インストールされたユニットをデフォルトで有効にする
Arch Linux の /usr/lib/systemd/system-preset/99-default.preset
には disable *
と記述されています。systemctl プリセットがデフォルトで全てのユニットを無効化するようになり、新しいパッケージがインストールされたときも、ユーザーが手動でユニットを有効化する必要があります。
自動的に有効化させたい場合、/etc/systemd/system-preset/99-default.preset
から /dev/null
にシンボリックリンクを作成して設定ファイルを上書きしてください。systemctl プリセットの設定ディレクトリで指定しないかぎり、インストールされた全てのユニットが有効化されるようになります。詳しくは systemd.preset(5) の man ページを参照。
アプリケーション環境のサンドボックス化
ユニットファイルをサンドボックスとして作成して堅牢な仮想環境にアプリケーションやプロセスを分離させることが可能です。systemd は名前空間やケイパビリティのホワイトリスト・ブラックリスト、Cgroups を活用して 実行環境を設定 しプロセスをコンテナ化します。
既存の systemd ユニットファイルを使ってアプリケーションをサンドボックス化するには strace, stderr, journalctl などでエラーや出力を確認しながら試行錯誤が必要です。まずは上流のドキュメントを検索して先例がないか確認すると良いでしょう。
CapabilityBoundingSet
では許可されるケイパビリティのホワイトリストを定義できますが、特定のケイパビリティをブラックリストに追加する用途で使うこともできます。例: CapabilityBoundingSet=~ CAP_SYS_ADMIN
。
トラブルシューティング
systemd のエラーを調査する
例えば、systemd-modules-load
サービスのエラーを調べるとします:
1. 起動に失敗している systemd サービスを探しましょう:
$ systemctl --state=failed
systemd-modules-load.service loaded failed failed Load Kernel Modules
もしくは systemd のライブログメッセージを確認します:
$ journalctl -fp err
2. Ok, systemd-modules-load
サービスに問題が発生していることがわかりました。詳しく見てみましょう:
$ systemctl status systemd-modules-load
systemd-modules-load.service - Load Kernel Modules Loaded: loaded (/usr/lib/systemd/system/systemd-modules-load.service; static) Active: failed (Result: exit-code) since So 2013-08-25 11:48:13 CEST; 32s ago Docs: man:systemd-modules-load.service(8). man:modules-load.d(5) Process: 15630 ExecStart=/usr/lib/systemd/systemd-modules-load (code=exited, status=1/FAILURE)
Process ID
が載っていない場合は、systemctl restart systemd-modules-load
で失敗したサービスを再実行してください。
3. エラーを細かく調べるためのプロセス ID (PID) を入手しました。Process ID
を使って (ここでは: 15630) 以下のコマンドを実行してください:
$ journalctl _PID=15630
-- Logs begin at Sa 2013-05-25 10:31:12 CEST, end at So 2013-08-25 11:51:17 CEST. -- Aug 25 11:48:13 mypc systemd-modules-load[15630]: Failed to find module 'blacklist usblp' Aug 25 11:48:13 mypc systemd-modules-load[15630]: Failed to find module 'install usblp /bin/false'
4. カーネルモジュールに間違った設定がなされているようです。よって /etc/modules-load.d/
下の設定を見てみましょう:
$ ls -Al /etc/modules-load.d/
... -rw-r--r-- 1 root root 79 1. Dez 2012 blacklist.conf -rw-r--r-- 1 root root 1 2. Mär 14:30 encrypt.conf -rw-r--r-- 1 root root 3 5. Dez 2012 printing.conf -rw-r--r-- 1 root root 6 14. Jul 11:01 realtek.conf -rw-r--r-- 1 root root 65 2. Jun 23:01 virtualbox.conf ...
5. エラーメッセージ Failed to find module 'blacklist usblp'
はおそらく blacklist.conf
内に間違った設定があることを示しています。手順 3 で見つけたオプションの前に # を挿入して無効化してみましょう:
/etc/modules-load.d/blacklist.conf
# blacklist usblp # install usblp /bin/false
6. では、systemd-modules-load
を起動してみることにします:
$ systemctl start systemd-modules-load
成功した場合、何も表示されないはずです。何かエラーが表示される場合は、手順 3 に戻って下さい。そして新しい PID を使って残った問題を解決してください。
全て問題ないならば、サービスが正しく起動したか次のコマンドで確認することができます:
$ systemctl status systemd-modules-load
systemd-modules-load.service - Load Kernel Modules Loaded: loaded (/usr/lib/systemd/system/systemd-modules-load.service; static) Active: active (exited) since So 2013-08-25 12:22:31 CEST; 34s ago Docs: man:systemd-modules-load.service(8) man:modules-load.d(5) Process: 19005 ExecStart=/usr/lib/systemd/systemd-modules-load (code=exited, status=0/SUCCESS) Aug 25 12:22:31 mypc systemd[1]: Started Load Kernel Modules.
この種の問題は上のように解決できます。より詳しい調査をする場合は次のブート問題の診断を見て下さい。
ブート問題の診断
カーネルコマンドラインに次のパラメータをつけて起動してください: systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M
。
特定のサービスの問題を診断
ある systemd サービスが上手く動作せず、どうなっているのか詳しい情報が欲しい場合、環境変数 SYSTEMD_LOG_LEVEL
を debug
に設定してください。以下は systemd-networkd デーモンをデバッグモードで動かす例です:
# systemctl stop systemd-networkd # SYSTEMD_LOG_LEVEL=debug /lib/systemd/systemd-networkd
もしくは同じようにサービスファイルを修正してください:
/lib/systemd/system/systemd-networkd.service
[Service] ... Environment=SYSTEMD_LOG_LEVEL=debug ....
シャットダウン/再起動にものすごく時間がかかる
シャットダウンに非常に長い時間がかかる(もしくはフリーズする)場合、サービスが存在していないことが問題かもしれません。Systemd はサービスを kill する前に終了するのを待ちます。なにが原因か知るには この記事 を見て下さい。
短いプロセスがログを出力しない
journalctl -u foounit.service
が短いプロセスについてなにも表示しない場合、かわりに PID を見て下さい。例えば、systemd-modules-load.service
が失敗したとき、systemctl status systemd-modules-load
によってそれが PID 123 として動いているとわかったら、その PID の journal の出力を見ることができます、journalctl -b _PID=123
。journal の _SYSTEMD_UNIT
や _COMM
などのメタデータは非同期に収集され /proc
ディレクトリにプロセスが存在している時だけ表示されます。これを修正するには、SCM_CREDENTIALS
のように、ソケット接続を使ってデータを流すようカーネルを変更する必要があります。
クラッシュしたアプリケーションのダンプのジャーナルを無効にする
/etc/systemd/coredump.conf
ファイルを編集して次の行を追加してください:
Storage=none
そして設定をリロードしてください:
# systemctl daemon-reload
再起動やシャットダウン時のエラーメッセージ
cgroup : option or name mismatch, new: 0x0 "", old: 0x4 "systemd"
この警告は kernel/cgroup.c
のカーネルコードから来ています:
/* Don't allow flags or name to change at remount */ if (((opts.flags ^ root->flags) & CGRP_ROOT_OPTION_MASK) || (opts.name && strcmp(opts.name, root->name))) { pr_err("option or name mismatch, new: 0x%x \"%s\", old: 0x%x \"%s\"\n", opts.flags & CGRP_ROOT_OPTION_MASK, opts.name ?: "", root->flags & CGRP_ROOT_OPTION_MASK, root->name); ret = -EINVAL; goto out_unlock; }
つまり、何かが cgroups を別の名前で再マウントしようとしてカーネルがそれに抵抗しているというわけです。ローカルの設定ファイルのエラーではなく、エラーメッセージ以外には何も症状が現れません。これが systemd のバグなのか、Arch の systemd パッケージに問題があるのかは判っていません [4]。2014年11月現在、Arch の systemd パッケージにバグレポートは送られていないようです。
watchdog watchdog0: watchdog did not stop!
このスレッドを見て下さい。
少しづつ起動時間が長くなっている
systemd-analyze
を使用して、以前と比べて起動時間が明らかに伸びていると複数のユーザーが報告しています。systemd-analyze blame
を使って NetworkManager が起動するのに異常に長い時間かかるようになったという報告もあります。
問題の原因として /var/log/journal
が巨大になりすぎている可能性があります。そのような場合、フォルダ内のファイルを全て削除して journal のファイルサイズをここに書かれているように制限するよう設定すれば解決します(できればファイルを削除する前に、どこかに一時的にバックアップしてください)。
起動時に systemd-tmpfiles-setup.service の実行に失敗する
systemd 219 から、/usr/lib/tmpfiles.d/systemd.conf
は /var/log/journal
下のディレクトリに対して ACL 属性を指定しており、それによって、ジャーナルが存在するファイルシステムで ACL のサポートを有効にしなくてはならなくなっています。
/var/log/journal
が存在するファイルシステムで ACL を有効化する方法はアクセス制御リスト#ACL の有効化を見て下さい。
systemctl enable で /etc/systemd/system にシンボリックリンクが作成されない
/etc/systemd/system/foo.service
がシンボリックリンクの場合、systemctl enable foo.service
を実行しても以下のエラーで失敗します:
Failed to issue method call: No such file or directory
これは systemd の 仕様 です。絶対パスで有効にすることで回避できます:
# systemctl enable /absolute/path/foo.service
起動時に表示される systemd のバージョンがインストールしているパッケージのバージョンと違う
initramfs を再生成することでバージョンが一致するようになるはずです。
リモートマシンで緊急モードを無効化
リモートマシン (例えば Azure や Google Cloud でホストしている仮想マシン) の緊急モードは無効化すると良いでしょう。緊急モードが起動すると、ネットワークからマシンに接続できなくなってしまうからです。無効化するには以下のコマンドを実行:
# systemctl mask emergency.service # systemctl mask emergency.target
参照
- 公式ウェブサイト
- Wikipedia の記事
- Manual Pages
- systemd Optimizations
- FAQ
- Tips And Tricks
- systemd for Administrators (PDF)
- Fedora プロジェクトによる systemd の説明
- systemd の問題をデバッグする方法
- [5] [6] The H Open マガジンに記載された二部からなる紹介記事
- Lennart のブログ記事
- ステータスアップデート
- ステータスアップデート 2
- ステータスアップデート 3
- 近況
- Fedora の SysVinit と systemd のチートシート
- Emacs の Systemd ファイルのシンタックスハイライト
- digital ocean のチュートリアル