著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。

序章

この2部構成のチュートリアルでは、systemdを使用して、再起動またはクラッシュ後に自動的に再起動するようにLinuxサービスを構成する方法を学習します。

パート1では、initデーモンやランレベルなどの一般的なLinuxサービス管理の概念について説明します。 最後に、systemdでのサービス管理のデモンストレーションを行います。 ここでは、targetswantsrequires、およびunitファイルを調べます。

パート2では、実用的で一般的なsystemdタスクを完了するためのステップバイステップのチュートリアルを提供します。 具体的には、クラッシュまたは再起動後に自動的に起動するようにMySQLデータベースサーバーを構成します。

注:systemctlを使用してsystemdサービスとユニットを制御するための非常に人気のあるチュートリアルを読むことも検討してください

前提条件

このチュートリアルを完了するには、次のものが必要です。

サービス管理デーモンの紹介

Linuxサービスは、initデーモンとも呼ばれるサービス管理デーモンによる処理方法を変更することで、主に自己回復させることができます。

initは、マシンが起動してカーネルがメモリにロードされた後、Linuxシステムで開始される最初のプロセスです。 特に、ユーザープロセスまたはシステムサービスをロードする方法、順序、および自動的に開始するかどうかを決定します。

Linuxが進化するにつれて、initデーモンの動作も進化しました。 もともと、LinuxはUnixで使用されていたものと同じSystem Vinitで始まりました。 それ以来、LinuxはUpstart initデーモン(Ubuntuによって作成された)を実装し、現在はsystemd initデーモン(Fedoraによって最初に実装された)を実装しています。

最近のほとんどのLinuxディストリビューションは、System Vから徐々に移行し、現在systemdを使用しています。 古いスタイルinit(使用されている場合)は、下位互換性のためにのみ保持されます。 UNIXの変種であるFreeBSDは、BSDinitとして知られる別のSystemV実装を使用します。

systemdは、今日のLinuxディストリビューションで使用されている最新の一般的なサービスマネージャーであるため、この記事で取り上げます。 ただし、必要に応じてSystem VとUpstartについても説明し、そこからsystemdがどのように進化したかを確認します。 あなたにアイデアを与えるために:

  • System V は、で使用されている最も古いinitシステムです。
  • Debian6以前
  • Ubuntu9.04以前
  • CentOS5以前
  • UpstartはSystemVの後に登場し、
  • Ubuntu14.04を含むUbuntu9.10からUbuntu14.10
  • CentOS 6
  • systemd は、で使用されている最新のLinuxサービスマネージャーです。
  • Debian7以降
  • Ubuntu15.04以降
  • CentOS7以降

initデーモンを理解するために、runlevelと呼ばれるものから始めましょう。

ランレベル

ランレベルは、Linuxシステムの現在の状態を表します。 たとえば、ランレベルは、Linuxサーバーのシャットダウン状態、シングルユーザーモード、再起動モードなどです。 各モードは、その状態で実行できるサービスを決定します。

一部のサービスは1つ以上のランレベルで実行できますが、他のサービスでは実行できません。 ランレベルは、0〜6の値で示されます。 次のリストは、これらの各レベルの意味を示しています。

  • ランレベル0:システムのシャットダウン
  • ランレベル1:シングルユーザー、レスキューモード
  • ランレベル2、3、4 :ネットワークが有効になっているマルチユーザーのテキストモード
  • ランレベル5:マルチユーザー、ネットワーク対応、グラフィカルモード
  • ランレベル6:システムの再起動

ランレベル2、3、および4は、ディストリビューションによって異なります。 たとえば、一部のLinuxディストリビューションはランレベル4を実装していませんが、他のディストリビューションは実装しています。 一部のディストリビューションでは、これら3つのレベルが明確に区別されています。 一般に、ランレベル2、3、または4は、Linuxがマルチユーザーのネットワーク対応のテキストモードで起動した状態を意味します。

サービスの自動開始を有効にすると、Linuxは実際にそのサービスをランレベルに追加します。 たとえば、System Vでは、OSは特定のランレベルで起動します。 そして、起動すると、そのランレベルに関連付けられているすべてのサービスを起動しようとします。 systemdでは、ランレベルがターゲットになり、サービスが自動開始されると、ターゲットに追加されます。 ターゲットについては、この記事の後半で説明します。

System Vinitデーモンの紹介

SystemVはinittabファイルを使用します。このファイルは、後のinitメソッドが下位互換性のために保持しています。 SystemVの起動シーケンスを実行してみましょう。

  1. initデーモンはバイナリファイル/sbin/initから作成されます
  2. initデーモンが読み取る最初のファイルは/etc/inittabです
  3. このファイルのエントリの1つは、マシンが起動するランレベルを決定します。 たとえば、ランレベルの値が3と指定されている場合、Linuxはネットワークが有効になっているマルチユーザーのテキストモードで起動します。 (このランレベルはデフォルトのランレベルと呼ばれます)
  4. 次に、initデーモンは/etc / inittabファイルをさらに調べて、そのランレベルで実行する必要のあるinitスクリプトを読み取ります。

したがって、initデーモンは、特定のランレベルで実行する必要のあるinitスクリプトを見つけると、実際に起動する必要のあるサービスを見つけます。 これらのinitスクリプトは、個々のサービスの起動動作を構成できる場所です。

initスクリプトは、SystemVの特定のサービスを制御するものです。 サービス用のinitスクリプトは、アプリケーションのベンダーによって提供されたか、Linuxディストリビューション(ネイティブサービス用)に付属しています。 カスタム作成されたサービス用に独自のinitスクリプトを作成することもできます。

MySQLサーバーなどのプロセスまたはサービスがSystemVで起動する場合、そのバイナリプログラムファイルをメモリにロードする必要があります。 サービスの構成方法によっては、このプログラムはバックグラウンドを継続的に実行する(そしてクライアント接続を受け入れる)場合があります。 このバイナリアプリケーションの開始、停止、または再読み込みのジョブは、サービスのinitスクリプトによって処理されます。 サービスを初期化するため、initスクリプトと呼ばれます。

System Vでは、initスクリプトはシェルスクリプトです。 rc(コマンド実行)スクリプトとも呼ばれます。 スクリプトは/etc/init.dディレクトリの下にあります。 これらのスクリプトは、/etc/rcディレクトリにシンボリックリンクされています。 /etcディレクトリ内には、いくつかのrcディレクトリがあり、それぞれの名前に番号が付いています。 数字はさまざまなランレベルを表しています。 つまり、/etc/rc0.d/etc/rc1.d/etc/rc2.dなどがあります。

クラッシュまたは再起動後にサービスを再起動するには、通常、initスクリプトに次のような行を追加できます。

  1. ms:2345:respawn:/bin/sh /usr/bin/service_name

System Vサービスをシステムの起動時に開始できるようにするには、次のコマンドを実行します。

  1. sudo chkconfig service_name on

無効にするには、次のコマンドを実行します。

  1. sudo chkconfig service_name off

ステータス(実行中または停止中)を確認するには、このコマンドを実行します

  1. sudo service service_name status

Upstartデーモンの紹介

System V initでジョブとサービスをロードするシリアル化された方法がより時間がかかり複雑になるにつれて、OSのロードを高速化し、クラッシュしたサービスを適切にクリーンアップし、システム間の依存関係を予測できるようにするために、Upstartデーモンが導入されました。サービス。

Upstart initは、いくつかの点でSystem Vinitよりも優れていました。

  • サービスをロードおよび管理するための難解なシェルスクリプトは処理しませんでした。 代わりに、理解と変更が容易な単純な構成ファイルを使用します
  • System Vのようにサービスがシリアルにロードされなかったため、システムの起動時間が短縮されました
  • 柔軟なイベントシステムを使用して、さまざまな状態でのサービスの処理方法をカスタマイズしました
  • Upstartには、クラッシュしたサービスがどのようにリスポーンするかを処理するためのより良い方法がありました。
  • すべて同じスクリプトを指す、冗長なシンボリックリンクを多数保持する必要はありませんでした。

物事を単純にするために、UpstartはSystemVと下位互換性があります。 /etc/init.d/rcスクリプトは、ネイティブSystemVサービスを管理するために引き続き実行されます。 その主な違いは、複数のイベントをサービスに関連付ける方法です。 このイベントベースのアーキテクチャにより、Upstartは柔軟なサービスマネージャーになることができました。 Upstartを使用すると、各イベントは、そのイベントを処理するシェルスクリプトを起動できます。 これらのイベントには次のものが含まれます。

  • 起動
  • 開始
  • 停止
  • 停止

これらのイベントの合間に、サービスは、待機、事前開始、開始、実行、事前停止、停止など、さまざまな状態になる可能性があります。 Upstartは、これらの各状態に対してもアクションを実行し、非常に柔軟なアーキテクチャを作成できます。

起動時に、UpstartはSystem Vinitスクリプトを通常どおり実行します。 次に、/etc/initディレクトリの下を調べ、各サービス構成ファイルでシェルコマンドを実行します。 特に、これらのファイルはサービスの起動動作を制御していました。

ファイルの命名スタイルはservice_name.confであり、スタンザと呼ばれるさまざまなセクションを持つプレーンテキストコンテンツが含まれています。 各スタンザは、サービスのさまざまな側面とその動作方法を説明します。 クラッシュまたは再起動後にサービスを自動的に開始するには、以下にcronサービスについて示すように、サービス構成ファイルにrespawnコマンドを追加できます。

/etc/init/cron.conf

...

description "regular background program processing daemon"

start on runlevel [2345]

stop on runlevel [!2345]

expect fork

**respawn**

exec cron

systemdデーモンのご紹介

Linuxinitデーモンの最新版はsystemdです。 実際、これはinitデーモン以上のものです。systemdは、最新のLinuxシステムの多くのコンポーネントを網羅するフレームワークです。

その機能の1つは、Linuxのシステムおよびサービスマネージャーとして機能することです。 この容量では、systemdは、サービスがクラッシュしたり、マシンがリブートした場合のサービスの動作を制御します。 ここでsystemdのsystemctlについて読むことができます。

systemdは、SystemVコマンドおよび初期化スクリプトと下位互換性があります。 つまり、SystemVサービスもsystemdで実行されます。 これが可能なのは、ほとんどのUpstartおよびSystemV管理コマンドがsystemdで機能するように変更されているためです。

systemd構成ファイル:ユニットファイル

systemdの中心にはユニットファイルがあります。 各ユニットファイルは、特定のシステムリソースを表します。 リソースに関する情報は、ユニットファイルで追跡されます。 サービスユニットファイルは、宣言型構文の単純なテキストファイル(Upstart .confファイルなど)です。 これにより、ファイルの理解と変更が容易になります。

systemdと他の2つのinitメソッドの主な違いは、systemdがサービスデーモンと、デバイスのオペレーティングシステムパス、マウントポイント、ソケットなどの他のタイプのリソースの初期化を担当することです。 ユニットファイルの命名スタイルはservice_name.unit_typeです。 したがって、dbus.servicesshd.socket、またはhome.mountのようなファイルが表示されます。

ディレクトリ構造

CentOSのようなRedHatベースのシステムでは、ユニットファイルは2つの場所にあります。 主な場所は/lib/systemd/system/です。 カスタム作成されたユニットファイルまたはシステム管理者によって変更された既存のユニットファイルは、/etc/systemd/systemの下にあります。

同じ名前のユニットファイルが両方の場所に存在する場合、systemdは/etcの下にあるものを使用します。 サービスが起動時またはその他のターゲット/ランレベルで開始できるようになっているとします。 その場合、/etc/systemd/systemの適切なディレクトリの下に、そのサービスユニットファイルのシンボリックリンクが作成されます。 /etc/systemd/systemの下のユニットファイルは、実際には/lib/systemd/systemの下の同じ名前のファイルへのシンボリックリンクです。

systemd initシーケンス:ターゲットユニット

特殊なタイプのユニットファイルは、ターゲットユニットです。

ターゲットユニットのファイル名には、.targetという接尾辞が付いています。 ターゲットユニットは、特定の1つのリソースを表していないため、他のユニットファイルとは異なります。 むしろ、それらはいつでもシステムの状態を表します。 ターゲットユニットは、その状態の一部である必要がある複数のユニットファイルをグループ化して起動することによってこれを行います。 したがって、systemdターゲットは、同じではありませんが、SystemVランレベルと大まかに比較できます。

各ターゲットには、番号ではなく名前があります。 たとえば、runlevel 3の代わりにmulti-user.targetを使用したり、runlevel 6の代わりにreboot.targetを使用したりします。 Linuxサーバーがmulti-user.targetで起動すると、基本的にサーバーはrunlevel 2, 3, or 4になります。これは、ネットワークが有効になっているマルチユーザーテキストモードです。

サーバーをその段階に引き上げる方法が違いです。 System Vとは異なり、systemdはサービスを順番に起動しません。 途中で、他のサービスやリソースの存在を確認し、それらのロードの順序を決定できます。 これにより、サービスを並行してロードできるようになります。

ターゲットユニットとランレベルのもう1つの違いは、System Vでは、Linuxシステムは1つのランレベルにしか存在できないことです。 ランレベルを変更することはできますが、システムはその新しいランレベルにのみ存在します。 systemdを使用すると、ターゲットユニットを包括的にすることができます。つまり、ターゲットユニットがアクティブになると、他のターゲットユニットがその一部としてロードされるようになります。

たとえば、グラフィカルユーザーインターフェイスで起動するLinuxシステムでは、graphical.targetがアクティブ化されます。これにより、multi-user.targetも自動的にロードされ、アクティブ化されます。 System Vの用語では、ランレベル3と5を同時にアクティブ化するようなものです。

次の表は、ランレベルとターゲットを比較しています。

ランレベル(System V init) ターゲットユニット(Systemd)
ランレベル0 poweroff.target
ランレベル1 resuce.target
ランレベル2、3、4 multi-user.target
ランレベル5 graphics.target
ランレベル6 restart.target

systemd default.target

systemd default.targetは、SystemVのデフォルトのランレベルと同等です。

System Vには、inittabというファイルで定義されたデフォルトのランレベルがありました。 systemdでは、そのファイルはdefault.targetに置き換えられます。 デフォルトのターゲットユニットファイルは、/ etc / systemd/systemディレクトリにあります。 これは、/ lib / systemd/systemの下にあるターゲットユニットファイルの1つへのシンボリックリンクです。

デフォルトのターゲットを変更すると、基本的にそのシンボリックリンクが再作成され、システムのランレベルが変更されます。

System Vのinittabファイルは、Linuxがinitスクリプトを実行するディレクトリも指定しました。これはrcn.dディレクトリのいずれでもかまいません。 systemdでは、デフォルトのターゲットユニットによって、起動時にロードされるリソースユニットが決まります。

ユニットがアクティブ化されると、それらはすべて並行して、またはすべて順番にアクティブ化されます。 リソースユニットのロード方法は、必要または必要な他のリソースユニットによって異なる場合があります。

systemdの依存関係:必要なものと必要なもの

systemd wantsおよびrequiresは、systemdがサービスデーモン間の依存関係に対処する方法を制御します。

前述のように、Upstartは、構成ファイルを使用したサービスの並列ロードを保証します。 System Vでは、サービスは特定のランレベルで開始できますが、別のサービスまたはリソースが使用可能になるまで待機させることもできます。 同様の方法で、systemdサービスを1つ以上のターゲットにロードするか、別のサービスまたはリソースがアクティブになるまで待機することができます。

systemdでは、別のユニットを必要とするユニットは、必要なユニットがロードされてアクティブ化されるまで起動しません。 最初のユニットがアクティブなときに必要なユニットが何らかの理由で故障した場合、最初のユニットも停止します。

これにより、システムの安定性が確保されます。 したがって、特定のディレクトリが存在する必要があるサービスは、そのディレクトリへのマウントポイントがアクティブになるまで待機させることができます。 一方、別のユニットが必要なユニットは、そのような制限を課しません。 発信者がアクティブなときに目的のユニットが停止しても停止しません。 この例としては、グラフィカルターゲットモードで表示される必須ではないサービスがあります。

実用例:systemdの起動シーケンスを理解する

systemdでのサービスの起動動作を理解するために、CentOS8.3ドロップレットを使用しています。 可能な限り.targetrabbit-trailをたどります。 systemdの起動シーケンスは、依存関係の長いチェーンに従います。

まず、次のコマンドを実行して、デフォルトのターゲットユニットファイルを一覧表示します。

  1. sudo ls -l /etc/systemd/system/default.target

これは、次のような出力を示しています。

Output
lrwxrwxrwx. 1 root root 37 Dec 4 17:42 /etc/systemd/system/default.target -> /lib/systemd/system/multi-user.target

ご覧のとおり、デフォルトのターゲットは、実際には/ lib / systemd /system/の下にあるマルチユーザーターゲットファイルへのシンボリックリンクです。 したがって、システムはmulti-user.targetで起動することになっています。これは、SystemVinitのランレベル3に似ています。

multi-user.target.wants

次に、次のコマンドを実行して、multi-user.targetファイルが必要とするすべてのサービスを確認します。

  1. sudo ls -l /etc/systemd/system/multi-user.target.wants/*.service

これにより、/ usr / lib / systemd /system/の下にある実際のユニットファイルを指すシンボリックリンクファイルのリストが表示されます。

Output
lrwxrwxrwx. 1 root root 38 Dec 4 17:38 /etc/systemd/system/multi-user.target.wants/auditd.service -> /usr/lib/systemd/system/auditd.service lrwxrwxrwx. 1 root root 39 Dec 4 17:39 /etc/systemd/system/multi-user.target.wants/chronyd.service -> /usr/lib/systemd/system/chronyd.service lrwxrwxrwx. 1 root root 37 Dec 4 17:38 /etc/systemd/system/multi-user.target.wants/crond.service -> /usr/lib/systemd/system/crond.service lrwxrwxrwx. 1 root root 42 Dec 4 17:39 /etc/systemd/system/multi-user.target.wants/irqbalance.service -> /usr/lib/systemd/system/irqbalance.service lrwxrwxrwx. 1 root root 37 Dec 4 17:41 /etc/systemd/system/multi-user.target.wants/kdump.service -> /usr/lib/systemd/system/kdump.service ...

multi-user.target以外にも、system-update.targetbasic.targetなどのさまざまなタイプのターゲットがあります。 マルチユーザーターゲットが依存しているターゲットを確認するには、次のコマンドを実行します。

  1. sudo systemctl show --property "Requires" multi-user.target | fmt -10

出力は次のとおりです。

Output
Requires=basic.target

basic.target

次のコマンドを実行して、basic.targetに必要なユニットがあるかどうかを確認できます。

  1. sudo systemctl show --property "Requires" basic.target | fmt -10

結局のところ、basic.targetにはsysinit.targetが必要です。

Output
Requires=sysinit.target -.mount

また、いくつかのターゲットも必要です。

  1. sudo systemctl show --property "Wants" basic.target | fmt -10

このコマンドは次を返します。

Output
Wants=slices.target paths.target timers.target microcode.service sockets.target sysinit.target

再帰的に実行すると、sysinit.targetで他のターゲットも実行する必要があるかどうかを確認できます。

  1. sudo systemctl show --property "Requires" sysinit.target | fmt -10

ありません。 ただし、sysinit.targetが必要とする他のターゲットがあります。

  1. systemctl show --property "Wants" sysinit.target | fmt -10

次のような出力が表示されます。

Output
Wants=systemd-random-seed.service dev-mqueue.mount rngd.service systemd-modules-load.service proc-sys-fs-binfmt_misc.automount local-fs.target sys-fs-fuse-connections.mount systemd-sysusers.service systemd-update-done.service systemd-update-utmp.service systemd-journal-flush.service dev-hugepages.mount dracut-shutdown.service swap.target systemd-udevd.service import-state.service sys-kernel-debug.mount nis-domainname.service systemd-journald.service selinux-autorelabel-mark.service kmod-static-nodes.service loadmodules.service ldconfig.service cryptsetup.target systemd-sysctl.service systemd-ask-password-console.path systemd-journal-catalog-update.service systemd-udev-trigger.service systemd-tmpfiles-setup.service systemd-hwdb-update.service sys-kernel-config.mount systemd-binfmt.service systemd-tmpfiles-setup-dev.service systemd-machine-id-commit.service systemd-firstboot.service

systemdユニットファイルの調査

さらに一歩進んで、sshd用のサービスユニットファイルの内部を見てみましょう。

  1. sudo vi /etc/systemd/system/multi-user.target.wants/sshd.service

次のようになります。

/etc/systemd/system/multi-user.target.wants/sshd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.target
Wants=sshd-keygen.target

[Service]
Type=notify
EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config
EnvironmentFile=-/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

サービスユニットファイルがクリーンでわかりやすいことがわかります。

最初の重要な部分は、[Unit]セクションのAfter句です。 これは、network.targetとsshd-keygen.targetがロードされた後にsshdサービスをロードする必要があることを示しています。

[Install]セクションは、サービスがmulti-user.targetによって必要とされていることを示しています。 これは、multi-user.targetがsshdデーモンをロードすることを意味しますが、ロード中にsshdが失敗しても、シャットダウンまたはクラッシュすることはありません。

multi-user.targetがデフォルトのターゲットであるため、sshdデーモンは起動時に起動することになっています。 [Service]セクションでは、Restartパラメーターの値はon-failureです。 この設定により、sshdデーモンがクラッシュしたり、終了がクリーンでない場合に再起動できます。

結論

この記事では、System V、Upstart、およびsystemdサービス管理デーモンについて学習しました。 起動スクリプトと構成ファイル、重要なパラメーター、起動シーケンス、およびサービスの起動動作を制御するコマンドについて説明しました。

この記事のパート2では、これらのスキルを実際の例に適用し、systemdを使用してMySQLを構成します。 完了すると、MySQLインスタンスは再起動またはクラッシュ後に自動的に再起動します。 また、サンプルアプリケーションとしてMySQLを使用しますが、NginxやApacheWebサーバーなどの任意の数のサービスを置き換えることができます。