Systemdターゲットの理解:基本概念の解説

systemdターゲット、デフォルトのブートターゲット、ランレベルのマッピング、分離、カスタムターゲット、トラブルシューティングコマンドを理解します。

Systemdターゲットの理解:基本概念の解説

Systemdターゲットは、サービスとして考えない方が理解しやすいです。サービスはプロセスを開始します。ターゲットはユニットを名前付きのシステム状態にグループ化します。マシンが multi-user.target に起動するとき、systemdは「マルチユーザー」というプログラムを開始しているわけではありません。そのターゲットが必要とするユニットが開始されたか、少なくとも開始ジョブが試行された状態に到達しようとしています。

この区別は、起動の問題をデバッグする際に役立ちます。graphical.target が遅い場合、ターゲット自体が問題であることはほとんどありません。そのターゲットにプルされたディスプレイ、ログイン、ネットワーク、マウント、アプリケーションユニットのいずれかが遅いか、失敗しています。ターゲットは地図を提供します。

Systemdターゲットとは?

systemdエコシステムでは、ターゲットは特別なタイプのユニットファイル(.service.socket ファイルなど)であり、重要な組織的役割を果たします。特定のプロセスを開始または停止する方法を定義するサービスユニットとは異なり、ターゲットユニットはシステム状態または一緒にアクティブになるべきユニットのコレクションを定義します。これらは、他のsystemdユニットの論理的なグループ化ポイントおよび同期ポイントとして機能します。

ターゲットをシステムの運用上のマイルストーンと考えてください。systemdが起動するとき、単にサービスを任意に起動するのではなく、特定のターゲットを達成するために動作します。このターゲットは、その状態を満たすために必要なすべてのサービス、ソケット、マウントポイント、およびその他のターゲットをプルします。この依存関係駆動型のアプローチにより、予測可能で効率的な起動プロセスが保証されます。

SysVinitのような古いLinux initシステムに精通している方にとって、systemdターゲットはランレベルの現代版です。SysVinitには固定のランレベルセット(例:マルチユーザーテキストモードのランレベル3、マルチユーザーグラフィカルモードのランレベル5)がありましたが、systemdターゲットはより柔軟です。名前が付けられており、番号ではありません。また、カスタムターゲットを定義できるため、より細かい粒度と拡張性が得られます。

ターゲットの仕組み:グループ化と依存関係

ターゲットは、ユニットファイル内で定義された明示的な依存関係を通じて、グループ化と状態定義機能を実現します。これに使用される主なディレクティブは、Wants=Requires=After=Before= です。

  • Wants=:「弱い」依存関係を指定します。ターゲットAユニットBWants= する場合、ターゲットA がアクティブ化されると、systemdは ユニットB を開始しようとします。ただし、ユニットB の開始に失敗しても、ターゲットA は開始されます。これは、望ましいが必須ではない関連サービスをグループ化するためによく使用されます。
  • Requires=:「強い」依存関係を指定します。ターゲットAユニットBRequires= する場合、ターゲットA がアクティブ化するには ユニットB が正常に開始される必要があります。ユニットB が失敗すると、ターゲットA も失敗するか、開始されません。これは重要な依存関係に使用されます。
  • After=:順序の依存関係を定義します。ターゲットAユニットBAfter= を持つ場合、ターゲットAユニットB が開始された後にのみ開始されます。これは成功への依存関係を意味するのではなく、順序のみを意味します。
  • Before=After= の逆です。ターゲットAユニットBBefore= を持つ場合、ユニットBターゲットA が開始された後にのみ開始されます。
  • Conflicts=:特定のユニットが同時にアクティブにならないようにします。ターゲットAユニットBConflicts= する場合、ターゲットA をアクティブ化すると、実行中の ユニットB が停止され、その逆も同様です。

これらのディレクティブにより、ターゲットは堅牢なオーケストレーターとして機能し、必要に応じてサービスや他のターゲットをプルし、それらが開始される順序を定義できます。たとえば、multi-user.target は通常、network.target やその他のさまざまなサービスを Wants= し、システムがマルチユーザー状態に達したときにそれらがアクティブであることを保証します。

ターゲットユニットファイルの内容を調べて、その依存関係を確認できます。

systemctl cat multi-user.target

このコマンドは、multi-user.target ユニットファイルの内容を出力し、その DescriptionDocumentation、そして重要なことに、マルチユーザー状態を構成するものを定義する Wants=Requires=After= などのディレクティブを表示します。

一般的なSystemdターゲットの説明

Systemdは、特定のシステム状態または機能に対応するさまざまな事前定義されたターゲットを提供します。これらを理解することは、システム管理にとって重要です。

  • default.target:これは最も重要なターゲットであり、システムが起動するデフォルトの状態を定義します。通常、graphical.target(デスクトップ用)または multi-user.target(サーバー用)へのシンボリックリンクです。
  • graphical.target:このターゲットは、通常、グラフィカルデスクトップ環境を持つシステムに使用されます。multi-user.target をプルし、グラフィカルログインマネージャーとディスプレイサーバー(例:GDM、LightDM、Xorg、Wayland)に必要なサービスを追加します。
  • multi-user.target:これは、グラフィカルインターフェースのないマルチユーザーシステムの標準状態です。サーバーで一般的であり、コマンドラインアクセス、ネットワーキング、およびほとんどのデーモン操作に必要なすべてのサービスを提供します。
  • basic.target:基本的な操作に必要な基本的なシステムサービスを含む最小限の状態ですが、multi-user.target の前です。通常、sysinit.target やその他の重要なサービスをプルします。
  • sysinit.target:このターゲットは、起動プロセスの非常に早い段階で到達します。/etc/fstab ファイルシステム(リモートのものを除く)のマウント、スワップのセットアップ、その他のハードウェア関連の初期化など、コアシステムの初期化タスクを担当します。
  • local-fs.target/etc/fstab で指定されたすべてのローカルファイルシステムがマウントされていることを確認します。
  • remote-fs.target/etc/fstab で指定されたすべてのリモートファイルシステム(例:NFS、CIFS)がマウントされていることを確認します。
  • network.target:基本的なネットワーク接続が利用可能であることを示します(例:ネットワークインターフェースが起動している)。完全なインターネット接続やIPアドレスの割り当てを保証するものではありません。
  • network-online.target:ネットワークマネージャーがネットワークをオンラインと見なすまで待機したいサービスのための同期ポイントです。インターネット、DNS、またはリモートAPIに到達可能であることを証明するものではなく、関連するwait-onlineサービスが有効になっている場合にのみ期待どおりに機能します。
  • rescue.target:最小限のサービスが実行され、ローカルファイルシステムがマウントされたシングルユーザーシェルを提供します。システムの回復とトラブルシューティングに役立ちます。
  • emergency.targetrescue.target よりもさらに最小限の環境です。ルートファイルシステム上にシェルを提供し、通常は読み取り専用でマウントされます。他のサービスは開始されません。重大な緊急事態用です。
  • poweroff.targetreboot.targethalt.target:これらのターゲットは、それぞれシステムのシャットダウン、再起動、または停止に使用されます。アクティブ化されると、ほとんどのサービスを停止し、目的の電源状態に備えます。

Systemdターゲットの管理

systemdターゲットとの対話は、主に systemctl コマンドラインユーティリティを使用して行います。

アクティブなターゲットとデフォルトターゲットの表示

システムが現在どのターゲットで実行されているかを確認するには:

systemctl get-default

現在ロードされているすべてのターゲットユニットを一覧表示するには:

systemctl list-units --type=target

このコマンドは、アクティブ、ロード済み、および静的なターゲットを、その説明とともに表示します。

デフォルトのブートターゲットの変更

システムがデフォルトで起動するターゲットを変更できます。たとえば、multi-user.target をデフォルトに設定するには:

sudo systemctl set-default multi-user.target

graphical.target に戻すには:

sudo systemctl set-default graphical.target

このコマンドは、/etc/systemd/system/default.target から目的のターゲットファイルへのシンボリックリンクを作成します。

一時的に別のターゲットに起動する

トラブルシューティングなど、特定のターゲットに1回だけ起動する必要がある場合があります。これは、起動時にカーネルパラメータを追加することで実現できます。GRUBブートメニューが表示されたら、ブートエントリを編集し(通常は e キーを押します)、カーネルコマンドラインに systemd.unit=ターゲット名.target を追加します。

たとえば、レスキューモードで起動するには:

systemd.unit=rescue.target

実行中のターゲットの切り替え

systemctl isolate コマンドを使用して、システムの実行中に別のターゲットに切り替えることができます。このコマンドは、新しいターゲットに必要のないすべてのサービスを停止し、必要なすべてのサービスを開始します。

警告systemctl isolate を使用すると、特にデスクトップマシンで graphical.target から multi-user.target など、はるかに低レベルのターゲットに切り替える場合、システムの動作を妨害する可能性があります。注意して使用してください。

graphical.target から multi-user.target に切り替えるには:

sudo systemctl isolate multi-user.target

graphical.target に戻すには(以前の状態であった場合):

sudo systemctl isolate graphical.target

カスタムターゲットの作成

systemdは多くの便利なターゲットを提供しますが、カスタムターゲットを作成することが有益な状況もあります。これは、複雑なアプリケーションデプロイメントで、常に一緒に起動および停止する必要があるいくつかのサービスをグループ化したり、アプリケーションに特定の環境を定義したりする場合に特に当てはまります。

カスタムターゲットを作成するには:

  1. .target ファイルを作成する/etc/systemd/system/ に配置します。例:my-application.target
    # /etc/systemd/system/my-application.target
    [Unit]
    Description=My Custom Application Target
    Wants=my-database.service my-webserver.service
    After=my-database.service my-webserver.service
    
    • Description:人間が読める説明。
    • Wants=:このターゲットがプルするサービスまたは他のターゲットをリストします。
    • After=:順序を定義します。ターゲットはこれらのユニットの後に開始されます。
  2. サービスを作成するmy-database.servicemy-webserver.service(またはリストしたサービス)が存在し、適切に設定されていることを確認します。
  3. systemdをリロードする:新しいユニットファイルについてsystemdに通知します。
    
    

sudo systemctl daemon-reload 4. **有効化して開始する**:カスタムターゲットを有効化して開始できるようになり、それにより必要なサービスが開始されます。 bash sudo systemctl enable my-application.target sudo systemctl start my-application.target ```

これにより、関連するサービスのグループを単一の論理ユニットとして管理でき、複雑なアプリケーションデプロイメントが簡素化されます。

ランレベルとターゲット(曖昧さなし)

SysVinitから移行した場合、おおまかなマッピングは次のとおりです。

古いランレベルの概念 一般的なsystemdターゲット
シングルユーザー修復モード rescue.target
マルチユーザーテキストモード multi-user.target
マルチユーザーグラフィカルモード graphical.target
再起動 reboot.target
電源オフ poweroff.target

これを完全なモデルではなく、翻訳の補助として扱ってください。SysVランレベルは、番号が付けられた小さな固定状態のセットでした。Systemdターゲットは、依存関係を持つ名前付きユニットであり、多数存在する可能性があります。パッケージは独自のターゲットをインストールできます。デプロイメントワークフロー用に作成することもできます。一部のターゲットは分離されることを意図しています。その他は、起動中に使用される単なるグループ化ポイントです。

どのターゲットが分離を許可しているかは、次のコマンドで確認できます。

systemctl show multi-user.target -p AllowIsolate
systemctl show basic.target -p AllowIsolate

これは重要です。なぜなら、systemctl isolate は無害な「ビューを切り替える」コマンドではないからです。新しいターゲットトランザクションの一部ではないユニットを停止します。デスクトップで multi-user.target を分離すると、通常、グラフィカルセッションが停止します。リモートサーバーで間違ったターゲットを分離すると、ネットワーキングやログインサービスが停止し、ロックアウトされる可能性があります。

サービスがターゲットの一部になる方法

ほとんどの日常的なターゲットメンバーシップは、サービスファイルの [Install] セクションから来ます。

[Install]
WantedBy=multi-user.target

次のコマンドを実行すると:

sudo systemctl enable myapp.service

systemdは、次のようなディレクトリの下にシンボリックリンクを作成します。

/etc/systemd/system/multi-user.target.wants/myapp.service

このシンボリックリンクにより、multi-user.target が起動時にサービスを必要とするようになります。サービスファイルは、有効化されていなくても存在し、完全に有効である可能性があります。その場合、multi-user.target を開始しても、自動的にプルされることはありません。

これが、systemctl start myapp.servicesystemctl enable myapp.service が異なる問題を解決する理由です。start は今すぐ実行します。enable は将来のブートターゲットに配線します。enable --now は両方を行います。

サービスがターゲットに対して有効化されているかどうかを確認するには:

systemctl is-enabled myapp.service
systemctl list-dependencies multi-user.target | grep myapp

サービスが手動では開始されるが、起動時には開始されない場合、これは最初に確認すべきことの1つです。

実際に役立つ小さなカスタムターゲット

カスタムターゲットは、オペレーターが関連ユニットのグループに対して1つのコマンドを提供する場合に最も役立ちます。単純なアプリケーションスタックを想像してください。

app-api.service
app-worker.service
app-scheduler.service

次のように作成できます。

# /etc/systemd/system/app-stack.target
[Unit]
Description=Application stack
Wants=app-api.service app-worker.service app-scheduler.service
After=network-online.target
Wants=network-online.target
AllowIsolate=no

次に、各サービスをターゲットに追加します。

[Install]
WantedBy=app-stack.target

daemon-reload の後、目的の動作に応じてサービスまたはターゲットを有効化します。

sudo systemctl daemon-reload
sudo systemctl enable app-api.service app-worker.service app-scheduler.service
sudo systemctl start app-stack.target

これにより、ターゲットがプロセススーパーバイザーであるかのように装うことなく、読み取り可能なグループ化が提供されます。app-worker.service が失敗した場合は、そのサービスを調査します。ターゲットは単なるグループ化ポイントです。

ターゲットを停止すると、すべてのスタックサービスが停止するようにするには、各サービスに PartOf=app-stack.target を追加します。

[Unit]
PartOf=app-stack.target

これで、systemctl stop app-stack.target がメンバーサービスに伝播します。これは、カスタムターゲットの例で欠けている部分であることがよくあります。

ターゲットを使用したトラブルシューティング

ターゲットは、起動の問題やサービスの障害のトラブルシューティングにも非常に役立ちます。

  • 依存関係の特定:サービスが開始に失敗した場合、それが属するターゲットを調べると、欠落または失敗した依存関係が明らかになることがあります。systemctl status <サービス名> および systemctl list-dependencies <ターゲット名> を使用します。
  • 最小限のターゲットに起動する:システムが graphical.target または multi-user.target に起動できない場合は、カーネルパラメータ方式を使用して rescue.target または emergency.target に起動してみてください。これにより、多くの実行中のサービスの複雑さなしに問題を診断できる最小限の環境が提供されます。
  • ログを確認する:ターゲットまたはサービスの開始を試みた後は、必ず journalctl ログでエラーを確認してください。
    journalctl -b -u <ターゲット名またはサービス名>
    

ベストプラクティスとヒント

  • network-online.target を慎重に使用する:サービスが起動前にネットワーク設定を必要とする場合は、After=network-online.targetWants=network-online.target を組み合わせ、適切なwait-onlineユニットが有効になっていることを確認してください。それでも、リモート依存関係についてはアプリケーションに再試行ロジックを保持してください。
  • 起動順序を理解するsysinit.target から basic.target、次に multi-user.target/graphical.target への一般的な流れを理解してください。これは、起動プロセスの早い段階で失敗するサービスのデバッグに役立ちます。
  • default.target には注意するdefault.target を変更すると、システムの起動動作が大幅に変わる可能性があります。カスタム設定は、最初に非本番環境でテストしてください。
  • 重要でない依存関係には Wants= を使用する:ターゲットが「稼働中」と見なされるために厳密に必要ではないが、役立つサービスの場合は、Requires= の代わりに Wants= を使用します。これにより、単一のオプションサービスの障害が連鎖してターゲット全体のアクティブ化を妨げるのを防ぎます。

維持すべきメンタルモデル

ターゲットは名前付きの状態であり、デーモンではありません。default.target は通常の起動先を決定します。multi-user.target は通常のサーバー状態です。graphical.target はディスプレイスタックを追加します。rescue.targetemergency.target は修復ツールです。カスタムターゲットは、操作を明確にする場合のグループ化ツールです。

ターゲット関連の何かが壊れた場合、最初にターゲットを責めないでください。どのユニットがプルされたか、どの順序ルールが遅延させたか、どの依存関係が失敗したかを尋ねてください。systemctl catsystemctl list-dependenciessystemctl show、および journalctl -b は、通常、一般的な起動図を読むよりも速くこれらの質問に答えます。