Linux管理・運用の基本
システム管理者のための実践ガイド
システム管理者のための実践ガイド
Linuxの管理・運用において、タスクの自動化は欠かせない要素です。これまで、cronやタイマーユニットを使って定期的なジョブを自動化する方法について解説してきました。しかし、特定のイベントが発生したときにだけタスクを実行したい、という場面も多くあります。
今回は、ファイルシステムの変更をトリガーにジョブを起動するパスユニットと、外部ストレージの接続・アクセスを柔軟に管理するマウントユニットに焦点を当てます。これらのユニットを使いこなすことで、よりスマートで効率的なシステム管理を実現する方法を、実践的な設定例とともに詳しく見ていきましょう。
特定のファイルやディレクトリに何らかの変更があったときに、それに反応して特定のサービスやスクリプトを自動で実行したい、そんな場面はありませんか?たとえば、設定ファイルが更新されたら即座にサービスをリロードする、新しいファイルが特定のディレクトリにアップロードされたら、そのファイルを処理するスクリプトを走らせる、といったケースです。
このような場合に威力を発揮するのがパスユニット(.path)です。パスユニットは、ファイルシステムの変更イベント(ファイルの作成、削除、変更など)を監視し、その変更が検知されたときに、関連するサービスユニット(.service)を起動します。
パスユニットは、主に[Unit]と[Path]の2つのセクションで構成されます。
| セクション | 主なオプション | 説明 |
|---|---|---|
[Unit] |
Description |
ユニットの簡単な説明を記述します。 |
Requires |
依存するユニットを指定します。 | |
After |
依存するユニットの後に起動することを指定します。 | |
[Path] |
PathExists |
指定したパスが存在する場合にユニットを起動します。 |
PathExistsGlob |
グロブパターンに一致するパスが存在する場合に起動します。 | |
PathModified |
指定したパスのタイムスタンプ(mtime)が変更されたときに起動します。 | |
DirectoryNotEmpty |
指定したディレクトリが空でない場合に起動します。 | |
Unit |
このパスユニットがトリガーするサービスユニットを指定します。デフォルトでは、パスユニットと同じ名前のサービスユニットが対象となります。 | |
MakeDirectory |
PathExistsなどで指定したディレクトリが存在しない場合に、自動的に作成します。PathModifiedなど、ファイルの内容変更を監視するオプションでは機能しません。 |
ここでは、 /etc/myapp/config.ymlという設定ファイルが変更されたら、myapp.serviceを再起動するパスユニットとサービスユニットの例を見てみましょう。
1. パスユニットファイル (/etc/systemd/system/myapp.path)
[Unit]
Description=Watch for changes to myapp config file
[Path]
# 設定ファイルの更新を監視
PathModified=/etc/myapp/config.yml
Unit=myapp.service
PathModified=/etc/myapp/config.ymlによって、config.ymlが変更されたときにトリガーが発動します。Unit=myapp.serviceによって、myapp.serviceという名前のサービスユニットを起動するよう指示しています。
※ 補足:トリガー時の挙動
パスユニットが起動時にサービスユニットがすでにアクティブだった場合、ExecReloadで指定されたコマンドが実行されます。ExecReloadが設定されていない場合は、ExecStartが再実行されるため、サービスが再起動されます。この挙動を理解しておくことで、意図しない動作を防ぐことができます。
また、パスユニットは大量のファイル変更イベントを処理する際に、イベントを取りこぼす可能性があります。そのため、高頻度でファイル変更が発生する環境での利用には注意が必要です。
2. サービスユニットファイル (/etc/systemd/system/myapp.service)
[Unit]
Description=My Application
After=network.target
[Service]
ExecStart=/usr/bin/myapp-daemon
ExecReload=/bin/kill -HUP $MAINPID
この例では、ExecReloadに再読み込みコマンドを指定しています。パスユニットがトリガーされると、myapp.serviceが起動し、ExecReloadで指定されたコマンドが実行されます。
3. ユニットの有効化と起動
# パスユニットを有効化
sudo systemctl enable myapp.path
# パスユニットを起動
sudo systemctl start myapp.path
これで、 /etc/myapp/config.ymlが変更されるたびに、myapp.serviceが自動でリロードまたは再起動されます。
Linuxシステムでは、USBメモリやネットワークドライブなどの外部ストレージをマウントするために/etc/fstabファイルが使われることが一般的です。しかし、/etc/fstabはシステム起動時に固定的にマウントを行うため、後から接続されるデバイスや、アクセス頻度の低いデバイスには不向きです。
マウントユニット(.mount)は、オンデマンドでのマウントや、特定のサービスに依存したマウントを実現する、より柔軟なマウント管理を提供します。これにより、USBメモリを挿入したときに自動でマウントしたり、特定のサービスが起動する前に必要なストレージをマウントしたりといった、高度な制御が可能になります。
マウントユニットも、[Unit]と[Mount]のセクションで構成されます。
| セクション | 主なオプション | 説明 |
|---|---|---|
[Unit] |
Description |
ユニットの簡単な説明を記述します。 |
After |
依存するユニットの後に起動することを指定します。 | |
[Mount] |
What |
マウントするデバイスやファイルパスを指定します。デバイスファイル、UUID、またはラベルで指定できます。 |
Where |
マウントポイントとなるディレクトリを指定します。 | |
Type |
ファイルシステムの種類(ext4、vfat、nfsなど)を指定します。 |
|
Options |
マウントオプションを指定します(rw、noexec、uid=...など)。複数のオプションはカンマ区切りで記述します。 |
ここでは、USBメモリを挿入したときに、自動で特定のディレクトリにマウントする設定を見てみましょう。
1. マウントユニットファイル (/etc/systemd/system/mnt-usb.mount)
[Unit]
Description=USB drive mount
After=local-fs.target
[Mount]
# USBドライブのUUIDを指定
What=UUID=xxxx-xxxx
Where=/mnt/usb
Type=vfat
Options=defaults,noatime,x-systemd.automount
What=UUID=xxxx-xxxx : マウントするデバイスを指定します。/dev/sdb1のようにデバイスファイルを直接指定することもできますが、USBの差し替えや順序変更でデバイス名が変わることがあるため、blkidコマンドで確認できるUUIDを指定するのがより確実です。Where=/mnt/usb: マウントポイントを指定します。Options=...: x-systemd.automountオプションが重要です。このオプションを付けることで、対応する.automountユニットが自動生成されます(または、自分で作成することもできます)。この.automountユニットは、マウントポイントへの最初のアクセスがあったときに、マウントをトリガーします。これにより、システムの起動時間を短縮し、必要な時だけマウントする「オンデマンドマウント」を実現します。2. ユニットの有効化と起動
# マウントユニットを有効化
sudo systemctl enable mnt-usb.mount
# マウントユニットを起動
sudo systemctl start mnt-usb.mount
これで、USBメモリを挿入し、/mnt/usbディレクトリにアクセスすると、自動的にマウントされるようになります。明示的なアンマウント操作(sudo umount /mnt/usb)を行うと、マウント状態は解除されます。
PathModified=/some/dir/ のようにディレクトリを指定した場合、ディレクトリ直下のファイルやディレクトリの作成・削除は検知しますが、サブディレクトリ内のファイルの変更までは追いません。より詳細な監視が必要な場合は、inotifywaitなどの外部ツールと組み合わせることを検討してください。x-systemd.automountは、マウントポイントへの最初のアクセス時に初めてマウント処理を開始するためです。その後のアクセスは通常通り利用できます。起動直後のスクリプトやバッチ処理で大量アクセスがある場合は、この遅延を考慮して設計する必要があります。[Unit]セクションにAfter=network-online.targetを追加し、ネットワークが利用可能になってからマウントするように設定することが非常に重要です。この設定がないと、ネットワークが確立する前にマウントを試みて失敗する「小さな落とし穴」にはまることがあります。journalctlでユニットごとのログを確認しましょう。
journalctl -u myapp.path:パスユニットの動作ログjournalctl -u mnt-usb.mount:マウントユニットの動作ログまた、systemctl status [ユニット名]でユニットの現在の状態やエラーメッセージを確認することも有効です。
今回は、systemdのパスユニットとマウントユニットという、少し応用的ながらも非常に強力な2つのユニットタイプについて解説しました。
/etc/fstabよりも柔軟で動的なマウント管理を可能にします。特にx-systemd.automountオプションは、オンデマンドでのマウントを実現し、システム起動時のオーバーヘッドを軽減します。
これらのユニットを使いこなすことで、より自動化され、堅牢で効率的なLinuxシステムを構築することができます。
この記事が、パスユニットとマウントユニットの理解を深める一助となれば幸いです。次回は、systemdのログ管理機能であるジャーナル(journald)について、journalctlの高度な使い方を中心に解説します。