クラッシュまたは再起動後に自動的に開始するようにLinuxサービスを構成する方法–パート1:実際の例
著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。
序章
この2部構成のチュートリアルでは、systemd
を使用して、再起動またはクラッシュ後に自動的に再起動するようにLinuxサービスを構成する方法を学習します。
パート1では、init
デーモンやランレベルなどの一般的なLinuxサービス管理の概念について説明します。 最後に、systemd
でのサービス管理のデモンストレーションを行います。 ここでは、targets
、wants
、requires
、およびunit
ファイルを調べます。
パート2では、実用的で一般的なsystemd
タスクを完了するためのステップバイステップのチュートリアルを提供します。 具体的には、クラッシュまたは再起動後に自動的に起動するようにMySQLデータベースサーバーを構成します。
注:systemctlを使用してsystemdサービスとユニットを制御するための非常に人気のあるチュートリアルを読むことも検討してください。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- CentOS 8を実行しているサーバーで、sudo権限を持つroot以外のユーザーが含まれます。 ファイアウォールを含め、これらすべてを設定するには、CentOS 8 を実行するDigitalOceanDropletを作成してから、初期サーバーセットアップガイドに従います。
サービス管理デーモンの紹介
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の起動シーケンスを実行してみましょう。
init
デーモンはバイナリファイル/sbin/initから作成されますinit
デーモンが読み取る最初のファイルは/etc/inittabです- このファイルのエントリの1つは、マシンが起動するランレベルを決定します。 たとえば、ランレベルの値が3と指定されている場合、Linuxはネットワークが有効になっているマルチユーザーのテキストモードで起動します。 (このランレベルはデフォルトのランレベルと呼ばれます)
- 次に、
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
スクリプトに次のような行を追加できます。
ms:2345:respawn:/bin/sh /usr/bin/service_name
System Vサービスをシステムの起動時に開始できるようにするには、次のコマンドを実行します。
sudo chkconfig service_name on
無効にするには、次のコマンドを実行します。
sudo chkconfig service_name off
ステータス(実行中または停止中)を確認するには、このコマンドを実行します
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.service
、sshd.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という接尾辞が付いています。 ターゲットユニットは、特定のリソースを表していないため、他のユニットファイルとは異なります。 むしろ、それらはいつでもシステムの状態を表します。 ターゲットユニットは、その状態の一部である必要がある複数のユニットファイルをグループ化して起動することによってこれを行います。 したがって、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の起動シーケンスは、依存関係の長いチェーンに従います。
まず、次のコマンドを実行して、デフォルトのターゲットユニットファイルを一覧表示します。
sudo ls -l /etc/systemd/system/default.target
これは、次のような出力を示しています。
Outputlrwxrwxrwx. 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ファイルが必要とするすべてのサービスを確認します。
sudo ls -l /etc/systemd/system/multi-user.target.wants/*.service
これにより、/ usr / lib / systemd /system/の下にある実際のユニットファイルを指すシンボリックリンクファイルのリストが表示されます。
Outputlrwxrwxrwx. 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.target
やbasic.target
などのさまざまなタイプのターゲットがあります。 マルチユーザーターゲットが依存しているターゲットを確認するには、次のコマンドを実行します。
sudo systemctl show --property "Requires" multi-user.target | fmt -10
出力は次のとおりです。
OutputRequires=basic.target
basic.target
次のコマンドを実行して、basic.targetに必要なユニットがあるかどうかを確認できます。
sudo systemctl show --property "Requires" basic.target | fmt -10
結局のところ、basic.targetにはsysinit.targetが必要です。
OutputRequires=sysinit.target -.mount
また、いくつかのターゲットも必要です。
sudo systemctl show --property "Wants" basic.target | fmt -10
このコマンドは次を返します。
OutputWants=slices.target paths.target timers.target microcode.service sockets.target sysinit.target
再帰的に実行すると、sysinit.targetで他のターゲットも実行する必要があるかどうかを確認できます。
sudo systemctl show --property "Requires" sysinit.target | fmt -10
ありません。 ただし、sysinit.targetが必要とする他のターゲットがあります。
systemctl show --property "Wants" sysinit.target | fmt -10
次のような出力が表示されます。
OutputWants=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用のサービスユニットファイルの内部を見てみましょう。
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サーバーなどの任意の数のサービスを置き換えることができます。