第557回 では、systemdユニットの依存関係を読む方法を紹介しました。 今回は、systemdユニットの設定を変更する方法を紹介します。
事前準備
systemdユニットの設定変更は最悪の場合、システムが正常に起動しなくなる恐れもあります。したがって手順を実際に試す際には、壊れても大丈夫なように検証用の仮想マシンなどを用意してください 。
また、本稿では題材としてApacheの設定を変更する手順を解説しますので、以下のようにインストールしておきます。
$ sudo apt -y install apache2
systemdユニットの設定の在り処
さて、apache2
パッケージのインストールが完了したら、systemdユニットを見てみましょう。ここは第557回のおさらいです。 インストール直後の状態だと以下のように表示されているはずです。
$ systemctl cat apache2.service
# /lib/systemd/system/apache2.service
[Unit]
Description=The Apache HTTP Server
(略)
ユニットの設定ファイルのパスとして/lib/systemd/system/apache2.service
が表示されています。これを変更すれば……と思った方はちょっと待ってください! そもそも、/lib/systemd/system/apache2.service
はどこから来たものなのでしょうか? 答えは以下のコマンドで確認できます。
$ dpkg -S /lib/systemd/system/apache2.service
apache2: /lib/systemd/system/apache2.service
この結果は/lib/systemd/system/apache2.service
ファイルは先ほどインストールしたapache2
パッケージにより配置されたものであることを示しています。 つまり、この設定ファイルをせっかくカスタマイズしても、apache2
パッケージが更新されるたびにパッケージのデフォルト設定に置き換えられてしまうため、設定を維持できません 。
このようにUbuntuでは[1] /lib/systemd/system/
配下にはパッケージ由来のユニット設定ファイルを置くというルールになっており、これらを直接変更することはしません。
[1] 他のディストリビューションではパッケージ由来のユニット設定ファイルが置かれる場所は違う可能性があります。例えば、Red Hat Enterprise Linux(RHEL)ではパッケージ由来のユニット設定ファイルは/usr/lib/systemd/system
に配置されます。
ユニット設定の変え方
では、ユニット設定を変えたい場合、どのような方法があるのでしょうか?
具体的な方法は、ユニット設定ファイルをまるごと上書きする方法と、drop-inファイルで一部を書き換える方法の2つがあります。それぞれ順に説明します。
ユニット設定ファイルをまるごと上書きする
/lib/systemd/system/
のほかにもsystemdがユニット設定ファイルを読み込むパスの1つとして/etc/systemd/system
があります[2] 。そして、systemdは同名のユニット設定ファイルがある場合/lib/systemd/system/
よりも/etc/systemd/system
を優先して読み込みます。
そのため、/lib/systemd/system/apache2.service
ファイルを/etc/systemd/system/apache2.service
としてコピーして、後者をお好み通りに書き換えることで、ユニット設定をまるごと上書きする(差し替える)ことができます。
それでは、実際にやってみましょう。 ユニットの説明を記載するDescription=
ディレクティブは変更しても無害と考えられますので、今回はこれを変更します。
まずは改めて変更前の状態を確認します。
$ systemctl cat apache2.service
# /lib/systemd/system/apache2.service
[Unit]
Description=The Apache HTTP Server
(略)
$ systemctl status apache2
● apache2.service - The Apache HTTP Server
(略)
この結果より以下がわかります。
systemdはapache2.service
の設定ファイルとして/lib/systemd/system/apache2.service
を読み込んでいる。
systemctl status
で表示されるユニット情報は/lib/systemd/system/apache2.service
に記載されているとおりapache2.service - The Apache HTTP Server
となっている。
それでは、このユニット設定を書き換えます。どこパスのファイルを読み込んでいるかをわかりやすくするため、Description=
に(This unit file is in /etc/systemd/system)
を追記します。
$ sudo cp /lib/systemd/system/apache2.service /etc/systemd/system/apache2.service
$ sudo vi /etc/systemd/system/apache2.service # Desciprion= の内容を書き換える
$ diff /lib/systemd/system/apache2.service /etc/systemd/system/apache2.service # 変更差分を確認する
2c2
< Description=The Apache HTTP Server
---
> Description=The Apache HTTP Server(This unit file is in /etc/systemd/system)
$ sudo systemctl daemon-reload # ユニット設定をリロードする
同じく、上書き後の状態を確認します。
$ systemctl cat apache2.service
# /etc/systemd/system/apache2.service
[Unit]
Description=The Apache HTTP Server(This unit file is in /etc/systemd/system)
(略)
$ systemctl status apache2
● apache2.service - The Apache HTTP Server(This unit file is in /etc/systemd/system)
(略)
この結果から以下のことがわかります。
systemdはapache2.service
の設定ファイルとして/etc/systemd/system/apache2.service
のみを読み込んでいる。
systemctl status
で表示されるユニット情報は/etc/systemd/system/apache2.service
に記載されている通りapache2.service - The Apache HTTP Server(This unit file is in /etc/systemd/system)
となっている。
ユニットのマスク 〜特殊な上書き〜
ユニット設定の書き換えというわけではないですが、ここまでに紹介したまるごと上書きの特殊例として、ユニットのマスクを紹介します。
systemctl disable
コマンドを使うことで、ユニットの無効化ができますが、この状態でも例えば手動で起動できます。 このdisable
コマンドより強力なものとしてmask
コマンドがあります。これは手動での起動やユニットの有効化も不可にするコマンドです。
実際に試してみましょう。
$ sudo systemctl mask apache2.service
Created symlink /etc/systemd/system/apache2.service → /dev/null.
/etc/systemd/system/apache2.service
というパスで/dev/null
へのシンボリックリンクが張られました[3] 。ここまでの解説同様、/dev/null
へのシンボリックリンクとなっている/etc/systemd/system/apache2.service
で/lib/systemd/system/apache2.service
をまるごと上書きしていると言えます。
なお、マスクされたユニットは有効化することも手動で起動することもできません。 ユニットのマスクを解除するにはsystemctl unmask
を使います。
drop-inファイルで一部を書き換える
続いて、drop-inファイルを使ってユニット設定の一部を変更する方法を紹介します。
drop-inファイルを使う方法では、ユニット設定全体ではなく、変更したい設定箇所だけを上書きできます。 drop-inファイルは/etc/systemd/system/ユニット名.d/
内に作成された.conf
という拡張子を持つファイルです。このdrop-inファイルではユニット設定ファイルの記述と同じ階層構造・形式([]
でセクションを区切る、ディレクティブ=値
で記載する)で設定変更箇所を記入します。
まずは、先ほど作業した/etc/systemd/system/apache2.service
は掃除して、設定を読み込み直しておきます。
$ sudo rm /etc/systemd/system/apache2.service
$ sudo systemctl daemon-reload
それでは実際にdrop-inファイルを作ってみます。
$ sudo mkdir /etc/systemd/system/apache2.service.d # drop-inファイルを配置するディレクトリを作成する
$ sudo vi /etc/systemd/system/apache2.service.d/description.conf # drop-inファイルを作成する
$ cat /etc/systemd/system/apache2.service.d/description.conf
[Unit]
Description=The Apache HTTP Server(Overridden by drop-in file)
$ sudo systemctl daeamon-reload
状況を確認します。 読み込まれている設定ファイルを確認します。
$ systemctl cat apache2.service
# /lib/systemd/system/apache2.service
[Unit]
Description=The Apache HTTP Server
(略)
# /etc/systemd/system/apache2.service.d/description.conf
[Unit]
Description=The Apache HTTP Server(Overridden by drop-in file)
このように/lib/systemd/system/apache2.service
と/etc/systemd/system/apache2.service.d/description.conf
の両方が読み込まれていることを確認できます。
では実際にどちらのDescription=
が有効になっているかを確認します。 再びsystemctl status
を使っても良いのですが、今回はsystemdが認識しているユニット情報を表示するsystemctl show
コマンドで確認してみます[4] 。
[4] 今回はあまり関係ありませんが、ユニットの種類ごとに決められた暗黙的な依存関係(implicit dependencies)など「設定ファイルには書かれてないけど適用されている設定」もあるため、systemdがユニットをどう認識しているかを確認するには、詳細を表示できるsystemctl show
コマンドを使うとより正確です(逆に言うと情報量がかなり多いですが) 。
$ systemctl show apache2.****service --property Description
Description=The Apache HTTP Server(Overridden by drop-in file)
この結果からわかるとおり、Description=
はdrop-inファイルの設定で書き換えられています。
確認の結果をまとめると、以下のとおりです。
systemdはapache2.service
の設定ファイルとして/lib/systemd/system/apache2.service
とdrop-inファイル/etc/systemd/system/apache2.service.d/description.conf
の両方を読み込んでいる。
Description=
は/etc/systemd/system/apache2.service.d/description.conf
の内容が優先され、Description=The Apache HTTP Server(Overridden by drop-in file)
となっている。
drop-inファイルに関するTips
ユニット設定のうち、複数回繰り返すことでリストにできる設定は、同じようにdrop-inすると変更ではなく追加 されます。 ゼロから設定し直したい場合は、一度設定を空にしてから、再設定する必要があります。
リストにできる設定の有名な例がExecStart=
[5] で、具体的には以下のように設定を一度クリアすることで、ゼロから設定できます。
[5] とはいえ、複数回ExecStart=
を指定できるのはType=oneshot
のもののみです。また、ExecStart=
を書き換えるくらいなら、ダミーの.service
ユニットを作るのが良いとは思われます。
[Service]
ExecStart=
ExecStart=/bin/echo 'Hello world from drop-in!'
なお、依存関係やアクティベート順序もリストにできる設定ですが、これらは空の値を許容しません。そのため上記の手法のように、drop-inでいったん消してゼロから再設定することはできませんので、まるごと上書きする方法を使ってください[6] 。
また、必要とされる場面は多くないと考えられるものの、/etc/systemd/system
のユニット設定ファイルとdrop-inファイルは併用できます。 今回の記事の手順でいえば、/etc/systemd/system/apache2.service
の掃除せずにdrop-inファイルで書き換える作業を始めてしまった人は、以下のようにdrop-inのほうが優先されていることがわかります。
$ systemctl cat apache2.service
# /etc/systemd/system/apache2.service
[Unit]
Description=The Apache HTTP Server(This unit file is in /etc/systemd/system)
(略)
# /etc/systemd/system/apache2.service.d/description.conf
[Unit]
Description=The Apache HTTP Server(Overridden by drop-in file)
$ systemctl status apache2
● apache2.service - The Apache HTTP Server(Overridden by drop-in file)
(略)
なお、drop-inファイルは複数配置することが可能です。しかし、パスではなくファイル名の辞書順で読み込まれます[7] 。
[7] パスではなく、ファイル名と説明しているのは例えば、/lib/systemd/system配下にもdrop-inを配置することが可能なためです。Ubuntuのインストール時のデフォルトでも/lib/systemd/system配下にいくつかのdrop-inファイルが存在するため、気になる方は実際に確認してみてください。
まるごと上書きとdrop-inの比較
最後に、ユニット設定ファイルをまるごと置き換えるユニット設定の上書きと変更したい箇所だけをdrop-inファイルで変更する方法を、おさらいも兼ねて比較します。
/etc/systemd/system
に同名のユニット設定ファイルを置いてまるごと上書きする方法は、パッケージで提供されるユニット設定ファイルの影響をまったく受けないという点が特徴です。 また、前述のとおり、依存関係やアクティベート順序をゼロから設定しなおしたい場合は、こちらの方法を使うしかありません。 裏を返せばパッケージで提供されるユニット設定ファイルで仮に「より良い設定[8] 」が施された場合などに恩恵を受けられないというデメリットがあります。
drop-inファイルを使う方法の特徴は、まるごと上書きする方法をひっくり返したものとなります。 つまり、drop-inファイルを使う方法では(多くの場合)パッケージ由来のユニット設定ファイルのうち、指定した箇所のみを変更します。そのため、その他の設定はパッケージ由来のユニット設定ファイルのまま使うことができます。 こちらも裏を返せばパッケージ由来のユニット設定ファイルの影響を受けるため、パッケージの更新に伴いユニット設定ファイルが変更された場合、drop-inファイルで変更した内容と矛盾が生じる可能性があるのはデメリットです。 また、依存関係やアクティベート順序は追加のみが可能でゼロから設定しなおすことはできません。
基本的に、どちらの方法が優れているというわけではなく、どちらがより都合が良いかという観点で考えて、使い分けるのがいいでしょう。
なにはともあれ、「 パッケージ由来のユニット設定ファイルを直接書き換えてしまい、パッケージの更新でせっかくのカスタマイズが飛んでしまう」という例がすこしでもなくなれば、筆者としては幸いです。