ブログに戻る

再起動またはシステムクラッシュ後にLinuxサービスを自動起動するように設定する方法:パート2(理論的解説)

再起動またはシステムクラッシュ後にLinuxサービスを自動起動するように設定する方法:パート2(理論的解説)

2部構成のチュートリアルの第2部では、Linux サービスが再起動またはシステムクラッシュ後に自動起動するように設定する方法について、init システムを詳しく説明します。詳細については、以下を参照してください:シリーズの第1部:再起動またはシステムクラッシュ後に Linux サービスを自動起動するように設定する方法:実践例はこちら.

今回のチュートリアルは理論的な内容が多くなります。そのため、Linuxでinitシステムがどのように動作するのかをより深く理解するためのリファレンスとしてご利用ください。このチュートリアルの第1回目では、起動時にinitシステムが読み込むコードスニペットやスタートアップスクリプトをいくつか紹介しました。また、以下も使用しました:MySQL を例として、クラッシュや再起動後に Linux サービスを自動起動するように有効化および無効化する方法を学びます。この2部構成のチュートリアルの第1部で学んだように、Linux のさまざまなディストリビューションで使用されている init システムには、System V、Upstart、Systemd の3つがあります。詳細については、特定の init システムを使用するように構成されているディストリビューションとバージョンを理解するために、このチュートリアルの第1部を参照してください.

このチュートリアルでは、第1部で使用したコードについて説明します。init システムが使用するコマンドと設定ファイルについて詳しく解説します。それでは始めましょう!

前提条件

この2部構成のチュートリアルの第1部の最後で、3つのテストサーバーを実行したままにしておく必要があると言及しました。もし削除してしまった場合は、戻って再作成してください。これにより、チュートリアルを進めやすくなります。用意しておくべき3つのテストサーバーは以下の通りです。

コマンドを実行するために使用する各サーバーに、sudo権限を持つユーザーが存在する必要があります。この Linuxのsudoersファイルの設定に関するチュートリアルが参考になります.

注意:  チュートリアルのコマンドはシステムサービスに干渉します。そのため、稼働中の本番サーバーには適用しないでください。

ランレベル

ある ランレベル は、利用可能なサービスに関連してLinuxシステムの現在の状態を表す動作レベルです。この概念はSystem V initに由来します。Linuxシステムが起動すると、カーネルを初期化し、1つのランレベルに入り、そのランレベルに関連付けられたスタートアップスクリプトを実行します。起動時に実行できるランレベルは1つだけです。

ランレベルのその他の例としては、シャットダウン状態、再起動モード、シングルユーザーモードなどがあります。各レベルは、その状態でどのサービスを実行するかを決定します。一部のサービスは複数のレベルで実行できますが、実行できないサービスもあります。

ランレベルは0から6までの7つ存在します。以下はこれら7つのランレベルの定義です。

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

ランレベルは必ずしも順次実行されるとは限りません。ランレベル2、3、および4は、実行しているLinuxディストリビューションによって異なります。一部のディストリビューションではランレベル4を実装できますが、他のディストリビューションでは実装できない場合があります。パート1で説明したように、サービスを自動起動するように有効にしたとき、実際にはそれをランレベルに追加したことになります。System Vでは、OSは特定のランレベルで起動し、起動中にそのランレベルに関連付けられているすべてのサービスを開始しようとします。ランレベルはSystemdにおけるターゲットであり、これについてはSystemdのセクションで説明します。

InitとPID 1

initシステムは、Linuxシステムが起動し、カーネルがメモリにロードされるときに実行される最初のプロセスです。ユーザープロセスやシステムサービスがどのように、どのような順序でロードされるか、また自動的に起動すべきかどうかを決定することを含む、さまざまなタスクを実行します。すべてのLinuxディストリビューションにおいて、すべてのプロセスはプロセスID(PID)によって識別され、initのPIDは1です。これは、システムの起動に伴って順次起動する他のすべてのプロセスの親となります。

initの歴史

近年のLinuxディストリビューションに見られるinitシステムは、オリジナルのものを改良したものです。初期のバージョンのLinuxディストリビューションではSystem V initが使用されており、これは同様にUnixシステムでも使用されていました。Linuxが進化するにつれて、Upstart initデーモンが実装されました。これはUbuntuによって作成されました。現在(このチュートリアルを執筆している2021年時点)では、Systemd initデーモンが使用されています。これは、最初にFedoraによって実装されました。Linuxシステムが進化し続けるにつれて、より新しいinitシステムが登場する可能性があります。このチュートリアルでは、System V、Upstart、Systemdのこれら3つについて説明します。

最近のLinuxバージョンには、デフォルトでSystemd initシステムが付属しています。しかし、後方互換性のために、他の古いinitシステムも残されています。他のLinuxのバリアントで使用できるSystem Vの異なる実装があります。例えば、 UNIXのバリアントであるFreeBSDはBSD initを使用しています。古いバージョンのDebianはSysVinitを使用しています。どちらもSystem Vに由来しています。

各バージョンのinitデーモンがサービスを管理する方法は異なります。各バージョンに加えられた改善は、サービス、デバイス、ポート、その他のリソースなど、Linuxシステムが必要とするすべてのものを処理できる堅牢なサービス管理ツールを目指したものでした。リソースを並列にロードでき、システムクラッシュからエレガントに回復できる強力なシステムが必要とされていました。

System V Initシーケンス

System Vは、初期化命令を保持するためにinittabファイルを使用します。Upstartは後方互換性のためにinittabファイルを保持します。System Vの起動フローは次のとおりです。

  • initシステムは、バイナリファイルから提供されます:/sbin/init.
  • initシステムがメモリにロードされると、最初に次のファイルを読み込みます:/etc/inittab.
  • このファイルのエントリの1つが、マシンが起動するランレベルを決定します。たとえば、ランレベルの値として5が指定されている場合、Linuxはネットワークが有効なマルチユーザーのグラフィカルモードで起動します(デスクトップ向けに設計されたディストリビューションで一般的です)。ここで指定されたランレベルは、常に使用されるものであるため、デフォルトのランレベルとして知られています。
  • その後、initシステムはさらに以下を調べます:/etc/inittab ファイルを参照し、そのランレベルで実行する必要があるinitスクリプトを読み込みます。

指定されたランレベルで実行するスクリプトを特定することで、initシステムは起動する必要があるサービスを検出します。これらのinitスクリプトは、通常、このチュートリアルの最初の部分でMySQLサービスを設定したのと同じように、個々のサービスの起動動作を設定する場所です。

System V initスクリプトの構造

このセクションでは、initスクリプトについて詳しく見ていきます。System Vの設定ファイルまたはinitスクリプトは、サービスを制御するものです。initスクリプトは、サービスを初期化(initialize) します。そのため、initスクリプトという名前が付けられています。

各サービスには、それぞれ独自のinitスクリプトがあります。例えば、MySQLのinitスクリプトはMySQLサーバーを制御します。アプリケーションベンダーは特定のアプリケーション用のinitスクリプトを提供し、ネイティブのLinuxサービスはオペレーティングシステムのインストールに付属しています。カスタムアプリケーションを作成する場合は、そのアプリケーション用の独自のカスタムinitスクリプトを作成することもできます。

MySQLサーバーのようなサービスを起動するには、まずそのバイナリプログラムがメモリにロードされます。設定によっては、クライアントからの接続を受け入れ続けるために、プログラムがバックグラウンドで実行され続ける場合があります。サービスのinitスクリプトは、バイナリアプリケーションの起動、停止、または再読み込みの処理を担当します。System Vのinitスクリプトはシェルスクリプトです。それらの別名はrc(run command)スクリプトです。

System Vのディレクトリ構造

initスクリプトの親ディレクトリは、/etcディレクトリです。 /etc/init.d ディレクトリは、initシェルスクリプトの実際のディレクトリです。スクリプトはrcディレクトリにシンボリックリンクされています。

次のディレクトリ内にはいくつかのrcディレクトリがあります:/etc ディレクトリ。各ディレクトリ名には数字が含まれています。これらの数字は異なるランレベルを表しています。ディレクトリの内容をリストすると、次のような名前が表示されます:/etc/rc0.d, /etc/rc1.d, /etc/rc2.dなど。

各rcディレクトリの内容を表示すると、次で始まるファイルが表示されます:K または Sがファイル名に含まれ、その後に2桁の数字が続きます。これらのファイルには、実際のプログラムの実際のinitシェルスクリプトを指し示すシンボリックリンクが含まれています。文字のKSは略語です。KはKill またはStopを意味し、SはStartを表します。ファイル名の中の2桁の数字は実行順序を表します。もし、K05script_nameという名前のファイルがあれば、それは以下の名前のファイルよりも先に実行されます:K09script_name.

起動

起動シーケンスを進めながら、initスクリプトがどのように呼び出されるかを見てみましょう。

SおよびKスクリプトは、initシステムから直接呼び出されるわけではありません。代わりに、別のスクリプトである/etc/init.d/rcスクリプト。/etc/inittabファイルは、デフォルトでシステムがどのランレベルで起動すべきかをinitデーモンに指示します。指定されたランレベルに応じて、/etc/inittabファイル内の行が/etc/init.d/rcスクリプトを呼び出し、デフォルトのランレベルをパラメータとして渡します。このパラメータを使用して、スクリプトは対応する/etc/rcN.dディレクトリ配下のファイルを呼び出します。ここでNはランレベルを表します。例えば、サーバーがランレベル5で起動する場合、対応する/etc/rc5.dディレクトリ配下のファイルが呼び出されます。

Inside the rcディレクトリ内では、すべてのKスクリプトが数値順に実行されます。その際の引数はstop、一方、すべてのSスクリプトは同様にstartという引数を付けて実行されます。/etc/rcN.d配下のファイルがシンボリックリンクしているプログラムに対応する実際のinitシェルスクリプトが、stopおよびstart パラメータでそれぞれ呼び出されます。

簡単に言うと、Linuxシステムが特定のランレベルに入ったり切り替わったりするたびに、特定のスクリプトが実行されて一部のサービスが停止され、他のスクリプトが実行されて別のサービスが開始されます。このプロセスにより、特定のLinux状態において実行されるべきではないプロセスは確実に停止され、実行されるべきプロセスは自動的に開始されます。

System V 自動起動

サービスを起動時に自動起動するように有効にすると、init の動作を直接変更することになります。例えば、ランレベル2でサービスを自動起動するように設定すると、init プロセスは適切なシンボリックリンクを次の場所に作成します:/etc/rc2.d ディレクトリ。理解を深めるために、例を用いて説明します。

System V の例

具体的な例として、パート1の MySQL サービス設定を使用します。したがって、ssh(Windows の場合は putty)を使用して、sudo/root ユーザーで Debian 6 VPS にログインし、次の手順に進んでください。

ステップ 1: inittab ファイルを開いて確認する

まず、ターミナルで次のコマンドを入力して inittab ファイルの内容を表示します。

ファイルの内容は次のようになっているはずです。

数字の 2 は、システムが起動するランレベルを示しています。この場合、ランレベル 2 がデフォルトであるため、この Debian システムはマルチユーザー、テキストモードのランレベル 2 で起動します。確認するには、次のコマンドを実行します。

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

ステップ 2: rc ディレクトリの確認

次に、rc ディレクトリの一覧を表示するには、次のコマンドを実行します。

出力のスクリーンショットは以下の通りです。

root screenshot

先ほど inittab ファイルで確認したように、システムは ランレベル 2 で起動するように設定されているため、/etc/rc2.dはシステム起動時に実行されます。次のコマンドを使用して、このディレクトリの内容を一覧表示できます:

出力からわかるように、これらのファイルは、次の場所の下にある実際のスクリプトファイルを指すシンボリックリンクにすぎません:/etc/init.d。以下は出力の抜粋です:

service crash 1

このディレクトリにはKスクリプトはなく、S(スタート)スクリプトのみが存在します。これらのスクリプトは、ここにリンクされている次のようなサービスを起動します:rsync。また、次のサービスが表示されていることにも気づくでしょう:mysqlサービス。これについては次のサブトピックで説明します。

ステップ 3: Initスクリプトの確認

System Vに準拠したサービスがインストールされると、/etc/init.dディレクトリの下にシェルスクリプトが作成されます。次のコマンドを入力することで、MySQLシェルスクリプトが利用可能かどうかを確認できます。

以下のような出力が表示されます:

screenshot output

ファイルはかなり大きいです。次のコマンドを入力して、その内容を表示できます。

ステップ 4: chkconfigまたはsysv-rc-confの使用

Chkconfig は、次のようなRHELベースのディストリビューションで使用できるコマンドです:CentOS を使用して、System V互換サービスを有効または無効にします。また、インストールされているサービスとそれぞれのランレベルを一覧表示するためにも使用できます。そのためのコマンドは次のとおりです(CentOSで動作します):

Debianディストリビューションでは、このようなユーティリティはネイティブには存在しません。Debianシステムのupdate-rc.dは、ランレベルからのサービスのインストールと削除のみを行います。Debianシステムにchkconfig機能をもたらすために使用できるカスタムツールが用意されています。インストールするには、次のコマンドを入力してください:

インストールが完了したら、次のコマンドを実行して、さまざまなサービスのランレベルの動作を表示できます。

このコマンドの出力は、左側にサービス名、そのサービスが実行されるランレベルを示す表の形式で表示されます。

service crash 2

Xは、サービスが実行されるランレベルを示します。このツールでは、矢印キーとスペースキーを使用して、ランレベルに対するサービスの有効化または無効化を行うことができます。ツールを終了するには、Qキーを押します。

ステップ 5: システム起動時におけるMySQLの起動動作のテスト

上のスクリーンショットから、mysqlサービスがランレベル2、3、4、5で有効になっていることがわかります。次のコマンドを使用してMySQLを無効にすることができます。

出力は以下のようになります。すべてのランレベルでサービスが停止していることに注意してください。

service crash 3

ディレクトリの内容を確認するには、以下のコマンドを実行します。

以下の出力のmysqlの行を確認してください。

出力は、シンボリックリンクがK(Kill、つまり停止)に変更されたことを示しています。したがって、MySQLはランレベル2でデフォルトで自動起動しません。System Vでサービスを有効または無効にするたびに、これが実行されます。サービスのデフォルトのランレベルディレクトリの下にS(start)スクリプトがある限り、initデーモンはシステム起動時にそのサービスを開始します。

サービスを再度有効にするには、次のコマンドを入力します。

ステップ 6: システムクラッシュ後のMySQLの起動動作をテストする

このセクションでは、System Vがサービスのクラッシュをどのように処理するかについて説明します。この知識を使用して、クラッシュ後のカスタムサービスの動作を設定できます。

このチュートリアルの最初の部分では、クラッシュ後にMySQLが自動的に起動するように、/etc/inittabファイルを変更しました。この動作を有効にするために、次の行を追加しました。

いくつかのテストを行うことで、この動作を確認できます。まず、次のコマンドを入力してVPSを再起動します。

再起動後、mysql_safe と mysqld がどのプロセスIDで実行されているかを確認します。次のコマンドを入力してプロセスIDを取得してください:

出力は以下のようになります:

プロセスIDを書き留めておきます。今回の例では、1836と186338でした。次に、以下のコマンドを入力して-9スイッチでプロセスを強制終了し、クラッシュをシミュレートします。ご自身のプロセスIDに置き換えることを忘れないでください:

数分後、次のコマンドを実行してMySQLのステータスを確認します:

出力はMySQLが実行中であることを示しており、シミュレートされたクラッシュの後に再起動されたことを意味します。もう一度 ps -ef | grep mysql コマンドを実行すると、両方のmysqld_safemysqld プロセスが、新しいIDではありますが実行されています。

プロセスを何度も強制終了しようとしても、数分後に再生成されます。この動作は、/etc/inittab ファイルに追加した行によって可能になります。これが、System Vでクラッシュした後にサービスを自動的に再起動するように設定する方法です。構文をもう一度確認するには、このチュートリアルのパート1を参照してください。

一部のカスタムサービスにはバグがあり、複数回再試行した後に再起動に失敗することがあります。init デーモンはサービスの再起動を試みますが、2分以内に10回以上失敗した場合、Linuxシステムはそのサービスを最大5分間無効にします。これにより、システムの安定性が維持され、クラッシュするサービスにシステムリソースが浪費されるのを防ぐことができます。システムログを確認して、修正が必要なカスタムアプリケーションの問題を特定することをお勧めします。

Upstartの紹介

System Vのinitシステムは、長い間Linuxディストリビューションにとって極めて重要でした。しかし、テクノロジーの常として、それは進化し続けています。オープンソースコミュニティからのサポートのおかげで、Linuxのエコシステムは驚異的に成長しました。System Vはジョブやサービスをシリアルにロードするため、複雑さが増し、時間がかかります。さらに、System Vが想定していなかった現代的なプラグイン可能なストレージメディアの導入により、別のinitシステムの必要性が高まりました。

Ubuntuの開発者たちは、別の初期化システムの開発に取り組み始めました。このinitシステムは、OSの高速な読み込みを処理し、クラッシュしたサービスの正常なクリーンアップを保証し、システムサービス間の依存関係を予測可能に保ち、プラグイン可能なストレージメディアに対応するように設計されました。こうしてUpstartデーモンが誕生しました。

Upstart initには、System V initに対して以下のような利点があります。

  • UpstartはSystem Vのようにサービスを順次ロードしないため、システムの起動時間を短縮できます。
  • クラッシュしたサービスをより適切に処理できるように設計されており、正常なクリーンアップとサービスの再起動(respawn)を行います。
  • Upstartは、さまざまな状態のサービスの処理をカスタマイズするために、柔軟なイベントシステムを使用しています。
  • initは、System Vのようなサービスのロードや管理のための複雑なシェルスクリプトを回避します。Upstartは、理解しやすく変更が容易なシンプルな設定ファイルを使用します。
  • Upstartは後方互換性を念頭に置いて構築されました。ネイティブなSystem Vサービスを管理するために、/etc/init.d/rcスクリプトが引き続き実行されます。
  • すべて同じスクリプトを指すような、冗長なシンボリックリンクを保持することを回避します。

Upstartイベント

Upstartはイベントベースであり、複数のイベントを同じサービスに関連付けることができます。このイベントベースのアーキテクチャにより、柔軟なサービス管理が保証されます。各イベントは、そのイベントに固有のシェルスクリプトを呼び出すことができます。

Upstartのイベントには以下が含まれます:

  • 起動中 (Starting)
  • 起動完了 (Started)
  • 停止中 (Stopping)
  • 停止完了 (Stopped)

イベントの間、サービスは以下を含む(ただしこれらに限定されない)さまざまな状態になることがあります:

  • 待機中 (Waiting)
  • 起動前 (Pre-start)
  • 起動中 (Starting)
  • 起動後 (Post-start)
  • 実行中 (Running)
  • 停止前 (Pre-stop)
  • 停止中 (Stopping)
  • 停止後 (Post-stop)

Upstart initは、これらの状態ごとにアクションを実行するように設定できるため、柔軟な設計となっています。

Upstart Initの起動シーケンス

Upstart initは以下を実行します:/etc/init.d/rc 起動時のスクリプト(System Vと同様)。このスクリプトは、後方互換性を確保するために、System Vの初期化スクリプトを通常通り実行します。

Upstartの設定ファイルは、/etc/init ディレクトリにあるため、デフォルトでそこを参照し、このディレクトリ内の設定ファイルに記述されているシェルコマンドを実行します。

Upstart設定ファイル

Upstartのinitは、System Vで使用されるbashスクリプトとは異なり、サービスを制御するためにサービス設定ファイルを使用します。これらの service 設定ファイルの命名規格は、 service_name.conf.

ファイルには、スタンザと呼ばれるさまざまなセクションに分割されたプレーンテキストのコンテンツが含まれています。各スタンザは、サービスの異なる状態とその動作を記述します。異なるスタンザは、サービスの異なるイベントを制御します。たとえば、waiting、pre-start、start、pre-stop、stoppingなどです。

スタンザにはシェルコマンドが含まれており、各サービスの各イベントに対して複数のアクションを開始できます。さらに、各サービスの構成ファイルは次の2つの事項を指定します。

  • サービスをどのランレベルで起動および停止するか。
  • サービスがクラッシュした場合に再起動(respawn)するかどうか。

Upstartのディレクトリ構造

Upstartサービスの設定ファイルは、次のディレクトリにあります:/etc/init。これと、以下を混同しないでください: /etc/init.d.

Upstartの例

この例では、システム起動時およびクラッシュ時にUpstartがサービスをどのように処理するかを確認します。このチュートリアルの最初の部分で示した具体的な例について、さらに詳しく説明していきます。

ステップ1:Ubuntu 14.0.4サーバーにログインする

まず、Upstartのテストには、Ubuntu 14.0.4が動作している2番目のVPSを使用します。これは、このLinuxディストリビューションがUpstartをネイティブに実装しているためです。Windowsを使用している場合は、sshまたはputtyを使用してください。rootまたはsudo権限を持つユーザーでログインする必要があります。私にはhackinsというユーザーがいるので、このようにログインします:

お使いのroot/sudoユーザーとサーバーのパブリックIPアドレスに置き換えてください。その後、Enterキーを押し、パスワードまたはパスフレーズを入力します。

ステップ 2: initおよびrcディレクトリの確認

Upstartの設定ファイルは/etc/initディレクトリに保存されています。これは、新しいサービス設定ファイルを作成する際に使用するディレクトリです。

/etc/initディレクトリ内の設定ファイル名の一覧を表示するには、次のコマンドを実行します。

上記のコマンドの出力からわかるように、多くのサービスがUpstartの下で動作しています。Qを押してlessを終了します。

rcディレクトリ内のSystem Vのサービス設定ファイルの一覧を表示するために以下を実行した場合、数個しか表示されません。

ステップ 3: Upstart ファイルの確認

このチュートリアルの第1部では、mysql.conf ファイルを使用してサーバー設定について学びました。知識をさらに深めるために、別の設定を使用してみましょう。 cron 設定ファイルが良い候補です。次のコマンドを入力してファイルを開きます。

下のスクリーンショットのような出力が表示されるはずです。

screenshot 4

スクリプトは非常にシンプルです。次の重要なフィールドに注意してください: start on、stop on、fork、および respawn。これらのディレクティブが何を行っているかを定義しましょう。

  • start on は、Ubuntuに cron デーモンを、システムがランレベル2、3、4、または5に入ったときに起動するように指示します。ここには指定されていない他のランレベル(つまり0、1、または6)では実行されません。
  • stop on は、実行中のデーモンを停止するようにUbuntuに指示します。ただし、この場合は感嘆符(!)があり、これは否定の記号です。スクリプトは、感嘆符の後のランレベル(2、3、4、5)では停止されるべきではありません。
  • fork ディレクティブは、プロセスをコンソールから切り離し、バックグラウンドで実行し続けるようUpstartに指示します。
  • respawn ディレクティブは、システムに cron が何らかの理由でクラッシュした場合に自動的に起動するように指示します。

何も入力せずにエディタを終了するには、Ctrl Xを押してください。

他のupstart設定ファイルも同じ構造に従い、start、stop、respawnのスタンザがあります。一部の設定ファイルには、pre-start、pre-stop、post-startなどの追加のスクリプトブロックがある場合があります。これらのコードブロックは、プロセスが定義されたいずれかの状態にあるときに何を実行するかをシステムに指示します。

ステップ 4: システム起動後のMySQLサービスの起動動作をテストする

MySQLはデフォルトでシステム起動後に自動起動するように設定されています。これを無効にして動作を確認してみましょう。Upstartでは、service_name.override という名前のファイルを、/etc/init/ ディレクトリの下に作成することで、サービスを無効にできます。ファイルの内容は、次の1語だけです:manual.

このコマンドを使用してMySQLサービスを無効にする方法を見てみましょう。次のコマンドを入力して、nanoエディタでファイルを開きます。

開いたファイルに次の行を追加します:

Ctrl + Oを押してからEnterキーを押して変更を保存します。Ctrl + Xを押してエディタを終了します。次のコマンドを実行してサーバーを再起動します。

数分待ってから再度ログインします。ログインしたら、次のコマンドを入力してMySQLサービスのステータスをテストします。

出力はサービスが実行されていないことを示します:

これは、システム起動後にMySQLが自動的に起動しなかったことを示しています。次に、MySQLの設定ファイルを開き、start ディレクティブが変更されたか確認します:

出力は、何も変更されていないことを示します:

これは、サービスが自動起動しておらず、そのサービスの構成ファイル(service_name.conf)のみを確認している場合、エラーが見つからない可能性があることを意味します。また、ディレクトリ内に service_name.override ファイルが存在するかも確認する必要があります。

次のコマンドを入力して override ファイルを削除し、MySQL サービスを再有効化します。その後、サーバーを再起動します:

サーバーが起動したら、MySQLサービスの状態を再度テストします。

MySQLサービスが自動的に起動したことが示されるはずです。

ステップ 5: システムクラッシュ後のMySQLサービスの起動動作をテストする

デフォルトでは、MySQLサービスがクラッシュすると自動的に再起動します。この動作を停止するには、mysql.conf ファイルを編集します。次のコマンドを入力して、nanoエディタでファイルを開きます:

次の記述を探します:respawn ディレクティブ行を、以下のようにコメントアウトします。 #:

次のコマンドを実行して、サービスを再起動します:

上記のコマンドを使用してサービスを停止および開始したのは、initctl restart または initctl reload ではここでは機能しないためです。MySQLサービスを開始するコマンドを実行すると、出力に以下のようにMySQLのPIDが表示されます:

私たちのPIDは1439でした。次に、コマンドを実行したときに表示された値を書き留めておいてください。次のステップで使用します。クラッシュをシミュレートするには、次のコマンドを使用してMySQLプロセスを強制終了します。上記で説明したように、PIDをご自身のものに置き換えることを忘れないでください。

クラッシュ後にMySQLが再起動したかどうかを確認するには、数分待ってから次のコマンドを入力します。

出力はMySQLが停止していることを示します:

ステータスをもう数回確認して、変化があるかどうか見てみてください。MySQLが停止したままになっていることに気づくでしょう。これは、サービス設定ファイルにrespawnディレクティブ(コメントアウトしたもの)がないためです。respawnディレクティブの詳細な説明については、このチュートリアルのパート1を参照してください。

システム起動後やクラッシュ後にサービスの自動再起動を無効にする方法を説明したのはなぜでしょうか?これは主にトラブルシューティングを目的としています。たとえば、サービスが起動してもクラッシュを繰り返す場合、トラブルシューティングを行い、システムの安定性を維持するために、自動再起動を無効にしたい場合があります。また、ネイティブで搭載されている新しいLinuxディストリビューションにアップグレードした際、古いサービス設定が自動再起動するのを防ぐこともできます。その対象となるのが、systemdであり、これについては次のセクションで説明します。

Systemdの紹介

Systemd は、最新のLinuxディストリビューションで採用されている最新のinitシステムです。これには、現代のLinuxシステムを構成する多くのコンポーネントが含まれています。

Systemd はサービスだけでなく、Linuxシステム全体も管理します。このセクションでは、システムの起動やクラッシュの後に、systemdがサービスの動作をどのように制御するかに焦点を当てます。

SystemdはSystem Vのinitスクリプトおよびコマンドと後方互換性があります。したがって、System Vで設定されたサービスがある場合、それらはSystemdの下でも動作します。ほとんどのUpstartおよびSystem Vの管理コマンドは、Systemdで動作するように変更されています。Systemdは起動時に自らをinitにリネームします。 /sbin/init ファイルは、以下へのシンボリックリンクとして存在します: /bin/systemd.

Systemd設定ファイル: ユニットファイル

Systemdの設定はユニットファイルで構成されています。各ユニットファイルはシステムリソースを表します。他の2つのinitシステム(すなわちSystem VとUpstart)はLinuxシステムのサービス管理を担当していましたが、Systemdはサービスデーモンだけでなく、デバイスのオペレーティングシステムパス、ソケット、マウントポイントなどの他のタイプのシステムリソースも管理します。ユニットファイルにはリソースに関する情報が格納されています。

各ユニットファイルは、特定のシステムリソースを次の命名スタイルで表します:service_name.unit_type. これは、home.mount、dbus.service、sshd.socketなどのファイルがあることを意味します。ユニットファイルは、理解しやすく変更しやすい宣言的な構文を持つシンプルなテキストファイルです。

ディレクトリ構造

ネイティブユニットファイルの主な場所は、/lib/systemd/system/ディレクトリです。ユーザーが作成したユニットファイル、システム管理者がカスタム作成したユニットファイル、およびその他の変更されたネイティブユニットファイルは、/etc/systemd/systemディレクトリに保存されます。

同じ名前のユニットファイルが、/lib/systemd/system//etc/systemd/systemの両方のディレクトリに存在する場合、systemdは/etcディレクトリの下にあるものを使用します。

ブート時またはその他のターゲット/ランレベルで起動するようにサービスを有効にすると、そのサービスユニットファイルのシンボリックリンクが、次の場所にある適切なディレクトリの下に作成されます:/etc/systemd/system/etc/systemd/system ディレクトリ内のユニットファイルは、次の場所にある同名のファイルへの単なるシンボリックリンクです:/lib/systemd/system ディレクトリ。

Systemdの起動シーケンス:ターゲットユニット

ターゲットユニットは、通常、次のサフィックス(接尾辞)が付けられる特殊な種類のユニットファイルです:.target. ターゲットユニットは、特定の1つのリソースを表すものではないため、他のタイプのユニットファイルとは異なります。代わりに、ある時点におけるシステム全体の状態を表します。

これを実現するために、ターゲットユニットは、特定の状態の一部である複数のユニットファイルをグループ化して起動します。SystemdのターゲットとSystem Vのランレベルは緩やかに比較することはできますが、同じものではありません。ターゲットユニットファイルには、数字ではなく名前があります。たとえば、runlevel 3の代わりにmulti-user.target、runlevel 6の代わりにreboot.targetのようなものがあります。Linuxシステムはmulti-user.targetで起動する場合があります。この場合、基本的にはサーバーをrunlevel 2、3、または4に移行させることになり、これによりネットワークが有効なマルチユーザーテキストモードでシステムが起動します。

その違いは、サーバーをそのレベルに移行させる方法にあります。System Vはサービスを順次起動します。一方、システムが起動する際、systemdは他のサービスやリソースが存在するかどうかを確認し、それらのロード順序を決定します。

systemdのターゲットユニットとSystem Vのランレベルのもう一つの違いは、System Vを使用するLinuxディストリビューションは1つのランレベルのみで存在するということです。ランレベルを変更すると、単にその新しいランレベルに切り替わり、その状態で存在することになります。一方、ターゲットユニットファイルは包括的(他のユニットを含むこと)が可能です。さらに、ターゲットユニットをアクティブにすると、他のターゲットユニットがその一部として確実にロードされます。例えば、グラフィカルユーザーインターフェースを備えたLinuxシステムを起動すると、graphical.targetがアクティブになります。これにより、自動的にmulti-user.targetも同様にロードされ、アクティブになります。

ランレベルとターゲットを比較した表を以下に示します。

ランレベル (System V) ターゲットユニット (systemd)
ランレベル 0 poweroff.target
ランレベル 1 rescue.target
ランレベル 2,3,4 multi-user.target
ランレベル 5 graphical.target
ランレベル 6 reboot.target

systemd の default.target

systemd では、default.target は System V におけるデフォルトのランレベルに相当します。System V のデフォルトのランレベルは inittab ファイルで定義されていることを見てきました。systemd では、default.target ファイルがあります。デフォルトのターゲットファイルは、/etc/systemd/system ディレクトリに格納されています。これは、次のディレクトリ配下にあるターゲットユニットファイルのいずれかへのシンボリックリンクです:/lib/systemd/system. デフォルトのターゲットを変更することは、単にシンボリックリンクを再作成し、システムのランレベルを変更することを意味します。

System Vでは、inittabはLinuxがinitスクリプトを見つけるディレクトリを指定していました。これは、前述のいずれかの rc ディレクトリになります。一方、systemdのデフォルトターゲットは、起動時にロードするリソースユニットを決定します。定義されたすべてのユニットがロードされます。ただし、すべてが並行してロードされるわけではなく、すべてが順次ロードされるわけでもありません。リソースユニットのロードは、それが wants または requires.

Systemdの依存関係: WantsとRequires

このセクションでは、Systemdが依存関係をどのように処理するかについて説明します。Upstartでは、設定ファイルを使用することでサービスの並行読み込みが可能であることを確認しました。また、System Vがランレベルを使用して、どのサービスを自動起動するか、あるいは別のサービスやリソースが起動するまで待機するかを決定する方法についても説明しました。同様に、Systemdサービスは、1つ以上のターゲットで読み込むように設定したり、別のサービスやリソースが起動するまで待機するように設定したりできます。

Systemdにおいて、次のものを必要とする 必要なユニットがロードされてアクティブになるまで、別のユニットは起動しません。最初のユニットがアクティブな間に必要なユニットのロードに失敗した場合、最初のユニットは停止します。

この挙動によりシステムの安定性が確保されます。サービスが 必要とする 特定のリソース(例えばポート)が利用可能でアクティブになるのを、そのリソースが利用可能になる(つまりポートが開く)まで待機させることができます。

対照的に、ユニットが 望む 別のユニットは、そのような制限を課しません。呼び出し元のユニットがまだアクティブな間に、要求されたユニットが停止しても、そのユニットは停止しません。例えば、graphical-targetモードにおける一部の非必須サービスなどです。

Systemdの例

systemdの下でサービスの動作をどのように設定できるかを見てみましょう。

ステップ1: VPSインスタンスにログインする

実際のサービスとしてMySQLを、サーバーとしてCentOS 7を使用します。実際に手順を進めて概念を理解するために、CentOS 7のVPSにログインするか、 CloudSigmaで作成してください.  CentOS 7、Debian 7または8、あるいはUbuntu 15以降のディストリビューションを実行しているVPSは、すべてsystemdが付属しているため、このセクションに適しています。sshコマンドを使用してログインするか、Windowsの場合はPuTTYを使用してください:

ステップ 2: default.target ファイルと依存関係の確認

Systemdの起動シーケンスは長い依存関係の連鎖に従っており、これについてはこのセクションで詳しく説明します。

  • default.target

default.target ファイルは、通常の起動時に開始されるサービスを制御します。次のコマンドを使用して、デフォルトのターゲットユニットファイルを表示できます。

出力は以下のスクリーンショットのようになります。

screenshot

スクリーンショットは、デフォルトのターゲットが、次のディレクトリ内のmulti-user.targetファイルにシンボリックリンクしていることを示しています:/lib/systemd/system/ ディレクトリ。これは、デフォルトでシステムが次のターゲットで起動することを意味します:multi-user.target(以下に相当):ランレベル3.

  • multi-user.target.wants

multi-user.targetファイルが必要とするすべてのサービスを表示するには、次のコマンドを入力します:

出力には多くの行が含まれています。以下はその一部です:

出力が示すように、これらは次の場所にある実際のユニットファイルを指すシンボリックリンクです:/lib/systemd/system/ ディレクトリ。ここでは、mysqld.service が、次のものの一部でもあることを示すために強調表示しています:multi-user.target. 特定のサービスが起動するように構成されているか確認したい場合は、そのファイル用のコマンドを変更できます。例えば、次のコマンドを使用して出力をフィルタリングし、mysqlまたはcronデーモンを検索できます。

出力には以下が表示されます:

cronデーモンの結果をフィルタリングするには、次のコマンドを入力します:

出力には以下が表示されます:

Apart from the multi-user.target 以外にも、他の異なるタイプのターゲットが存在します。例えば、system-update.target または basic.target.

multi-user ターゲットがどのターゲットに依存しているかを確認するには、次のコマンドを入力します:

出力には以下が表示されます:

これは、basic-target が、システムを multi-user.target モードで起動するために最初にロードされる必要があることを意味します。

  • basic-target

basic.target が他に必要としているターゲットを確認するには、次のコマンドを入力します:

出力は次のようになります:

  • sysinit.target

次のコマンドを実行すると、sysinit.target に必要なターゲットがあるかどうかを確認できます。コマンドの構文は同じです。作業を進めながら、どのターゲットユニットが別のターゲットユニットから必要とされているかを確認するために、コマンドを変更していくことができます。コマンドは次のとおりです:

出力には、sysinit.targetに必要なユニットがないことが示されます。他のサービスやターゲットが要求(wanted)されているかを、sysinit.targetについて、次のコマンドを使用して確認できます:

出力には、sysinit.targetによって要求(wanted)されているサービスやターゲットの長いリストが表示されます。出力の一部を以下に示します:

system4を使用したシステム初期化中、システムは1つのターゲットだけに留まりません。代わりに、あるターゲットから別のターゲットへと移行しながら、依存関係に従ってサービスをロードします。

ステップ 3: ユニットファイルの確認

ユニットファイルがどのようなものか見てみましょう。このチュートリアルの最初の部分でMySQLサービスのユニットファイルを使用しましたが、ここでもそれを使用します。ただし、別のサービスユニットファイルであるsshdユニットファイルを見ることもできます。次のコマンドを入力して、sshd設定ファイルを開きます。

以下は、ファイル内の行を示すスクリーンショットです:

unit screesnhot

ご覧のように、ファイル内で囲まれたコードブロックにより、必要に応じていつでも簡単に理解し、変更することができます。以下に、理解しておくべき重要なディレクティブをいくつか示します:

  • AfterAfter 句は、指定されたターゲットとサービスがロードされた後にのみサービスをロードするようシステムに指示します。この場合、SSHDサービスはネットワークターゲットとkeygenサービスがロードされた後にロードされます。
  • WantsWants 句は、どのターゲットがこのサービスを必要としているかを示します。この例では、 ssh-keygen.service が必要としているのは sshd.service. しかし、sshdが失敗またはクラッシュしても、次のサービスはシャットダウンされません:ssh-keygen.service.

Ctrl + Xを押してエディタを閉じます。

ステップ 4: システム起動時におけるMySQLサービスの起動動作のテスト

このセクションでは、システム起動時におけるMySQLサービスの動作を変更およびテストする方法を説明します。前のセクションでは、mysqld.service が以下によって要求されている(wanted by)ことを見ました:multi-user.target。そのため、起動時に自動開始されます。

次のコマンドを実行することで、サービスを無効化できます:

コマンドを実行すると、mysqlのシンボリックリンクが /etc/systemd/system/multi-user.target.wants/ ディレクトリから削除されていることがわかります。これをテストするには、次のコマンドを実行して、MySQLがまだ以下によって要求されているか確認します: multi-user.target:

コマンドは何も返しません。サーバーを再起動してMySQLのステータスを確認すると、実行されていません。これは、起動時に自動起動しなかったことを意味します。

次のコマンドを使用して、サービスを再度有効にします:

出力にシンボリックリンクが表示されます。サーバーを再起動すると、MySQLが自動的に起動するはずです。Systemdサービスを有効にすると、デフォルトターゲットのwantsディレクトリにシンボリックリンクが作成されます。Systemdサービスを無効にすると、wantsディレクトリからシンボリックリンクが削除されます。

ステップ 5: サービスクラッシュ後のMySQLサービス起動動作のテスト

デフォルトでは、MySQLサービスはクラッシュした場合に自動起動します。MySQLのSystemd設定ファイルでこの動作を無効にすることができます。まず、ファイルを確認してみましょう。次のコマンドを入力してファイルを開きます。

以下のスクリーンショットは出力を示しています。

screen shot 5

Restartディレクティブの値はon-failureに設定されています。これは、異常な終了コード、タイムアウト、または異常なシグナルの後にMySQLサービスが再起動することを意味します。以下は、次のドキュメントから抜粋した再起動パラメータの一部を示す表です:manページ.

再起動の設定/終了原因 no always on-success on-failure on-abnormal on-abort on-watchdog
正常な終了コードまたはシグナル X X
異常な終了コード X X
異常なシグナル X X X X
タイムアウト X X X
ウォッチドッグ X X X X

Systemdユニットファイルにおける2つの重要なディレクティブは、RestartRestartSec です。これらはサービスのクラッシュ時の動作を制御します。Restart はサービスを再起動するタイミングを指定し、RestartSec は、クラッシュ後に再起動するまでの待ち時間を指定します。再起動の動作を無効にするには、次のように行の先頭に # を追加して Restart ディレクティブをコメントアウトします。

次に、システムデーモンをリロードし、続いて mysqld サービスを次のコマンドを使用してリロードします:

次に、次のコマンドを実行して MySQL サービスのメイン PID を確認します:

screenshot 7

テストのメインPIDは23809でした。次のコマンドで使用するために、ご自身のPIDをメモしておいてください。kill -9コマンドを使用して、プロセスを強制終了することでクラッシュをシミュレートします。また、テストで取得したプロセス番号に置き換えることを忘れないでください:

MySQLのステータスを確認するコマンドを実行すると、アクティブではなく、再起動に失敗していることがわかります:

screesnshot 8

Restartディレクティブが次のファイル内でコメントアウトされている限り、失敗状態のままになります:mysqld.service 設定ファイル。これは、サービスが停止して復旧しないクラッシュをエミュレートします。

サービスを再有効化するには、mysqld.service 設定ファイルを編集し、Restart ディレクティブのコメントアウトを解除して、保存して閉じます。先ほどと同様に、デーモンをリロードしてサービスを再起動します。これにより、サービスは初期設定に戻り、クラッシュ後に自動起動できるようになります。以上で、クラッシュ後にサービスを自動起動するための設定はすべて完了です。クラッシュ後にサービスが自動起動するように設定したい場合は、単に次のディレクティブを追加するだけです: Restart ディレクティブ(および、必要に応じて RestartSec ディレクティブを追加することもできます)を、[Service] セクション(サービスユニットファイル内)の下に指定します。

まとめ

このチュートリアルでは、起動時やクラッシュ後に Linux がサービスをどのように処理するかについて説明しました。Linux システムの初期化プロセスを理解するために、Linux が使用する 3 つの init システム(System V、Upstart、Systemd)について説明しました。それらの進化と、それぞれの init プロセスが、システムの再起動やクラッシュ後にサービスを自動起動することに関してどのように機能するかについて説明しました。

initデーモンとLinuxディストリビューションはどちらも時間の経過とともに進化しているため、実行しているLinuxディストリビューションのバージョンを確認し、システムがネイティブにサポートしているinitデーモンを把握しておくようにしてください。

Linuxのネイティブアプリケーションやほとんどのサードパーティ製アプリケーションは、システムの起動やクラッシュ後にすでに自動起動するため、何もする必要はありません。このチュートリアルの知識は、独自のカスタムサービスの起動やリスポーン動作を構成する場合や、クラッシュを繰り返すサービスのトラブルシューティングを行う場合に不可欠です。

快適なコンピューティングを!

author

Manpreet Singh

著者 · CloudSigma

Preslav DobrevはCloudSigmaのクリエイティブデザイナーであり、従来型および革新的なマーケティングチャネルを活用した一貫性のあるビジネスアイデンティティに注力しています。彼は芸術的なビジョンと戦略的マーケティングを融合させ、インパクトのあるブランドナラティブを生み出すことに長けています。

コメント

コメントはまだありません。最初のコメントを投稿しましょう。