※このブログではサーバー運用、技術の検証等の費用のため広告をいれています。
記事が見づらいなどの問題がありましたらContactからお知らせください。


【Linux】systemctlコマンドでunitを探索する

systemd サービス 自動起動設定 linux systemctl

投稿日:2020年11月3日

このエントリーをはてなブックマークに追加
systemctlコマンドを上手く使いこなすことでsystemd、unitに対しての理解を深め、正しい設定の仕方や問題が起きた際の対処方法を学ぶことができます。この記事ではsystemctlを使ってunitを探索しています。

はじめる前に

注意点

systemctlコマンドはそのOSで動いているsytemdのunitを操作することができます。

unitの中には絶対に止めてはいけないサービスがあります。

例えばGCPのCompute EngineのUbuntu20.04インスタンスで以下のようなコマンドをうったとします。

$ sudo systemctl disabled ssh.service

この様にすると、2度とそのインスタンスにアクセスすることができなくなってしまいます

unitを操作するコマンドを打つときにはそのunitに何の役割があるか、コマンドがどのような影響をもたらすのかを理解する必要があります。


実践

基本的なコマンド

まずはunitに対しての最も基本的なコマンドについて紹介します。

現在のセッションでunitを起動、停止する場合にはstartstopコマンドを使用します。

$ systemctl start nginx.service
$ systemctl stop nginx.service

enableコマンドでunitを有効化するとそのunitはOS起動時にsytemdプロセスによって自動的に起動させることができます。

サーバーなどのプロセスのunitはこの自動起動設定をすると良いでしょう。

disableコマンドで自動起動をOFFにできます。

$ systemctl enable nginx.service # 自動起動ON
$ systemctl disable nginx.service # 自動起動OFF

unitのリスト表示

まずは現在のsystemdのunitを一覧表示してみます。

$ systemctl list-units

出力には次の要素が含まれます。

  • UNIT:systemdにおけるunitの名前。
  • LOAD:unitの設定ファイルがsystemdに読み込まれているかどうか。loadedになっているものはそのunitはメモリ上に保持されます。
  • ACTIVE:unitが有効であるかどうかの大まかな状態。unitが開始できたかどうかはここを確認します。
  • SUB:unitの状態についての詳細な状態。この値はunitのtypeによって値が変わったりします。
  • DESCRIPTION:そのunitを端的に説明したテキスト。

list-unitsで表示されるのは、デフォルトではLOADEDloadedACTIVEactiveのunitだけです。

--allフラグをつけることで全てのunitを表示することができます。

$ systenctl list-units --all

このコマンドではsystemdがload・parseしようとした全てのunitが表示されます。

list-unitsコマンドは--stateフラグや--typeフラグでフィルタリングして表示することができます。

例えば

  • ACTIVE:inactive
  • type:service

のunitを一覧表示するには下のようなコマンドになります。

$ systemctl --type=service --state=inactive --all

unit fileの一覧表示

上のコマンドではparse・loadされメモリに読み込まれようとしたunitだけを表示しています。

それ以外にもunitの定義は存在する場合があります。

unit定義ファイルを一覧表示するコマンドがlist-unit-filesです。

$ systemctl list-unit-files --all

出力はUNIT_FILEというunitの定義ファイル名とSTATEが表示されます。

  • UNIT_FILE:unitの定義ファイル名
  • STATE:unit fileの状態。enabled、disabled、static、maskedの値をとります。

STATEがstaticのunit定義ファイルはinstallの定義が含まれておらず、unitがenabledにできないことを意味します。
このようなunitは一回きりの起動、または他のunitに参照される対象としての定義である事が考えられます。

unit定義ファイルの内容を確認

現在可動中のserviceが正しいものか確認したり、unit定義ファイルの書き方を学ぶために、unit定義ファイルの中身を表示する方法を説明しておきます。

基本的にこれはcatコマンドを使用すればOKです。

試しにここではatd.serviceというサービスの定義ファイルを表示してみます。(atdはコマンドの実行をスケジューリングするservice)

$ systemctl cat atd.service
# /lib/systemd/system/atd.service
[Unit]
Description=Deferred execution scheduler
Documentation=man:atd(8)
After=remote-fs.target nss-user-lookup.target
[Service]
ExecStartPre=-find /var/spool/cron/atjobs -type f -name "=*" -not -newercc /run/systemd -delete
ExecStart=/usr/sbin/atd -f
IgnoreSIGPIPE=false
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target

ちなみにsystemctlコマンドのサービス指定は.serviceなどを省略してsystemctl cat atdとすることもできます。

依存関係の確認

unitは依存関係を組むことができます。

list-dependenciesコマンドはunitの依存関係を表示するコマンドです。

$ systemctl list-dependencies
default.target
● ├─accounts-daemon.service
● ├─apport.service
● ├─display-manager.service
● ├─e2scrub_reap.service
● ├─grub-common.service
● ├─systemd-update-utmp-runlevel.service
● └─multi-user.target
●   ├─apport.service
●   ├─atd.service
●   ├─chrony.service
●   ├─console-setup.service
●   ├─cron.service
●   ├─dbus.service

[...]

この出力によると、全てのunitがdefault.targetを起点に起動しているようです。

次にatdサービスの依存関係をみてみます。

コマンドの引数にサービス名を与えることでそのサービスの依存関係を表示することができます。

$ systemctl list-dependencies atd.service
atd.service
● ├─system.slice
● └─sysinit.target
●   ├─apparmor.service
●   ├─blk-availability.service
●   ├─dev-hugepages.mount
●   ├─dev-mqueue.mount
●   ├─finalrd.service
●   ├─keyboard-setup.service

[...]

atd.serviceがどのunitに依存しているか、つまりどのunitを先に起動しているべきかを表すツリーが表示できました!

再帰的な依存関係の表示はデフォルトではtargetタイプしか表示されていませんが、実は他のタイプのunitもそれぞれ依存しているunitが存在するはずです。

実際に依存するunitの依存関係を再帰的に表示しまうと表示が煩雑になってしまうことは容易に想像できますね。

このコマンドは親切設計のためにデフォルトではtargetタイプのunitの依存関係だけを表示しているのです。

全ての依存関係を表示する場合には--allフラグをつけます。

$ systemctl list-dependencies atd.service --all

またこのunitが何のunitに依存されているのかを確認したい場合は--reverseフラグをつけます。

$ systemctl list-dependencies atd.service --reverse
atd.service
● └─multi-user.target
●   └─graphical.target

全ての依存関係を見た時の結果と一致していますね!

--before--afterオプションはどのunitより前に起動しているべきか、どのunitより後に起動しているべきかを一覧表示できます。

$ systemctl list-dependencies atd.service --before
atd.service
$ systemctl list-dependencies atd.service --before
atd.service

unitのプロパティを確認

unitのプロパティを表示するにはshowコマンドをつかいます。

$ systemctl show atd.service
Type=simple
Restart=on-failure
NotifyAccess=none
RestartUSec=100ms
TimeoutStartUSec=1min 30s
TimeoutStopUSec=1min 30s
TimeoutAbortUSec=1min 30s
RuntimeMaxUSec=infinity
WatchdogUSec=0

[...]

catコマンドで確認できるunit設定ファイルと比較してみましょう。

ただし、いまのままだとプロパティの数が多すぎて少し見づらいですね。

-pオプションを使うと特定のプロパティだけを表示できるので、これを使ってみましょう!

ここでは例としてDocumentationのプロパティの値を比較してみます。

$ systemctl cat sshd.service
# /lib/systemd/system/ssh.service
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
Alias=sshd.service
$ systemctl show sshd.service -p Documentation
Documentation=man:sshd(8) man:sshd_config(5)

一致していますね。

ここで次のunitのマスクに進む前に調べる対象のサービスとしてnginxをインストールしておきましょう。

$ sudo apt update
$ sudo apt install nginx

ComputeEngineのコンソールの外部IPにアクセスしてnginxのサンプルページが表示されることを確認しておきます。

▲nginxのサンプルページ

unitのマスク

unitのmaskとはそのunitの有効化をできなくする事です。

maskしたunitは/dev/nullのシンボリックリンクが作成されます。

disabledと違い、再度unitを起動、または自動起動化するにはそのmaskを解除しなければできません。

$ systemctl mask nginx.service # nginxをマスク
$ systemctl start nginx 
Failed to start nginx.service: Unit nginx.service is masked

マスクができています。ls -la /etc/systemd/systemで確認してみるとnginx.serviceから/dev/nullへのシンボリックリンクが作成されていることがわかるでしょう。

マスクを解除するにはunmaskコマンドを使用します。

$ systemctl unmask nginx.service

unitの定義ファイルの編集

editコマンドは対象のサービスの定義を編集するコマンドです。

もちろん、unitの定義ファイルはnanoやviなどのエディタで直接定義ファイルを編集することもできます。

しかし、その方法では誤った定義ファイルにした時注意点でも説明した様にOSの動作に意図しない問題を起こしてしまう可能性があります。

それを防ぐためにeditコマンドでは対象unitの差分だけを作成します。

systemctl edit nginx.service
差分ファイル
[Unit]
Description=A high performance web server and a reverse proxy server

編集が完了すると、対象unit定義ファイル.dというディレクトリが作成され、その中にoverride.confという名前で差分の内容が入ったファイルが作成されます。

次回unitが読み込まれた時、このoverride.confの内容が元の定義ファイルの内容にマージされます。

ちなみに手動で再読込する場合はsudo sytemctl daemon-reloadというコマンドを使います。

もし、編集した差分に間違いがあった場合などにはその.dディレクトリを削除すれば元のデフォルトファイルに戻すことができます。

$ sudo rm -r /etc/systemd/system/nginx.service.d
$ sudo systemctl reload-daemon # 設定の再読込

リファレンス

参考URL

参考書籍

このエントリーをはてなブックマークに追加


関連記事

記事へのコメント