Upstartイベントシステム:それは何であり、それをどのように使用するか

提供:Dev Guides
移動先:案内検索

序章

初期化は、すべてのスクリプトとサービスの動作を制御するためのUnixベースのオペレーティングシステムの中心にある重要な手順です。 これは、起動とシャットダウンの重要なポイントで問題が発生する可能性があり、最適なパフォーマンスを確保することが優先されるサーバー環境では不可欠です。

本質的に、初期化はこの種のプロセスに従います。

  1. サーバーが起動します
  2. init プロセスが実行されます(通常はPID 1として)
  3. 事前定義された一連の起動タスクが順番にアクティブ化されます

初期化は、クラウドサーバーが正常に起動およびシャットダウンできるようにする責任があります。

Unix基盤を備えた一部のディストリビューションは、初期化に標準のinitプロセスを利用します。 この記事では、 Upstart を見ていきます。これは、サーバーの操作を強化できる実用的で強力な代替品です。

古典的なinitの何が問題になっていますか?

従来の初期化は線形プロセスに従います。システムの起動時に、個々のタスクが事前定義された順序でロードされます。 これは、特に急速に変化する状況では、それほど役に立ちません。 その理由を理解するために、たとえば、ストレージデバイスを追加してサーバーの環境を変更したとします。

初期化プロセスでは、環境の突然の変化を考慮に入れることができません。つまり、追加のストレージを認識する前に、クラウドサーバーを再初期化する必要があります。 オンザフライ検出が必要ですが、従来の初期化手順の機能ではありません。

線形シーケンスでの起動にも時間がかかります。これは、迅速な展開が不可欠なクラウドベースの環境では特に不利です。

システムがロードされた後のタスクのステータスについても心配する場合があります。 残念ながら、 init は、起動時または電源切断時のみシーケンスに関係します。

同期ブートシーケンスはもはや望ましくありません。 リジッドシステムは昨日のシステムをサポートできますが、今日は動的です。

そこで登場するのがUpstartであり、高度な機能を備えたこれらの問題の解決策です。

事前設定されたタスクの順番のリストではなく、リアルタイムイベントに基づいて、この置換initデーモンはタスクの開始と停止を処理し、はシステムの実行中にこれらのプロセスを監視します–“フルカバレッジ」はそれを説明するための最良の方法です。

この新しく非同期処理により、厳密なブートシーケンスが不要になります。 リアルタイム処理は概念化するのが面倒かもしれませんが、Upstartはジョブの構造を使用することで、最も複雑なシステムをサポートし、すべてをチェックすることができます。

スタートアップの概要

最初から柔軟性を持って設計されたUpstartイベントシステムは、従来の初期化システムとは異なるさまざまな概念を利用しています。 このソリューションは、Red Hat Enterprise Linux(RHEL)6、GoogleのChrome OS、Ubuntuにデフォルトでインストールされますが、最近の議論により、これが継続するかどうかについて混乱が生じています。

ジョブズ

Upstartの世界では、ジョブは作業プロセスであり、タスクジョブ(目的を持って)とサービスジョブ(バックグラウンドで実行できます)に分割されます。 抽象ジョブもあります。これは、管理者権限を持つユーザーによって停止されるまで、永久に実行されるプロセスです。

イベント

ただし、イベントは、ジョブまたは別のイベントで特定のアクションをトリガーするために使用されるシグナルまたは「呼び出し」です。 イベントの一般的な形式は、プロセスの監視を指します:startingstartedstopping、およびstopped

イベントの発行

イベントをブロードキャストするプロセスは「送信」と呼ばれます。 これは通常、プロセスまたはジョブの状態が原因で発生しますが、管理者はinitctl emit <event>コマンドを発行して手動でイベントを発行することもできます。 init controlコマンドは、Upstartに関連する多数の操作をナビゲートするときに非常に便利になることに気付くでしょう。

最初のジョブ構成を作成する

UpstartはUbuntuでうまく機能することが知られているので、始める前に Ubuntu 14.04Dropletを起動してください。

準備ができたので、ジョブ構成ファイルが有効であるためには3つの基本原則に従う必要があることを理解することが重要です。

  • 空であってはなりません(内容のないファイル)
  • 構文エラーが含まれていてはなりません
  • スタンザと呼ばれる少なくとも1つのコマンドブロックが含まれている必要があります

とりあえず基本的にしましょう。 すぐに、/etc/initディレクトリにtestjob.confというファイルを作成します。 この場合、「init」は「初期化」の短縮版として使用されます。

.confファイルの関連付けに注意してください。これは、ジョブ構成ファイルを作成することを示しています。

このチュートリアルでは、コマンドラインテキストエディタnanoをお勧めします。 これらのコマンドの中には、sudoの管理者権限が必要な場合があるため、この記事をチェックして適切なユーザーを作成してください。

テストジョブの新しい構成ファイルを作成するには、次のコマンドを実行します。

sudo nano /etc/init/testjob.conf

それでは、目的の概要を説明しましょう。 このジョブでメッセージと現在のタイムスタンプをログファイルに書き込みます。

ジョブスクリプトの目的と作成者を定義するのに役立つ2つの基本的なスタンザがあります。descriptionauthorです。 これらをファイルの最初の行として書き込みます。

description "A test job file for experimenting with Upstart"
author "Your Name"

ここで、システムサービスとプロセスが既にロードされた後に(競合を防ぐために)このジョブを実行する必要があるため、次の行には次のイベントが組み込まれます。

start on runlevel [2345]

ランレベルとは何か疑問に思われるかもしれません。 基本的に、これは現在のシステム構成を表す単一の値です。 [2345]は、一般的なLinuxアクセスとネットワークを備えたすべての構成状態を指します。これは基本的なテスト例に最適です。

次に、実行コードを追加します。 この行はexecで始まり、次のコマンドをBashシェルで実行する必要があることを示しています。

exec echo Test Job ran at  `date` >> /var/log/testjob.log

このechoコマンドは、バッククォートを使用してdateをコマンドとして実行し、メッセージ全体をログファイルに書き込むことに注意してください。 dateという単語をバッククォートなしで記述した場合、コマンドの出力の代わりに単語自体が出力されます。

このファイルを保存して閉じます。

これが機能することを手動でジョブを開始することで確認できますが、最初に構成ファイルの構文を確認しましょう。

init-checkconf /etc/init/testjob.conf

問題が検出された場合、このコマンドは特定の行番号と問題を示します。 ただし、テストジョブでは、次のような出力が表示されます。

File /etc/init/testjob.conf: syntax ok

このコマンドは、UpstartジョブおよびWebサーバーなどの他のバックグラウンドサービスを制御するために使用できます。

基本的なコマンド構文は次のとおりです。

sudo service <servicename> <control>

この構文は、次の基本的なコントロールで機能します。

  • 再起動:これは停止し、サービスを開始します
  • start:サービスが実行されていない場合、これによりサービスが開始されます
  • 停止:サービスが実行されている場合、これによりサービスが停止します
  • status:これはサービスのステータスを表示します

テストジョブを手動で開始したいので、コマンドは次のようになります。

sudo service testjob start

次に、次のコマンドを実行して、testjob.logファイルを確認します。

cat /var/log/testjob.log

このコマンドは、ファイルをシェルに読み込みます。 以下のような1行が表示されます。

Test Job ran at Fri Aug 1 08:43:05 BST 2014

これは、テストジョブが設定され、実行する準備ができていることを示しています。

ドロップレットを再起動し、ログインしてログファイルを再度読み取ります。

cat /var/log/testjob.log

ログに2行目が表示され、Upstartジョブとして実行されたことを確認するためのタイムスタンプが表示されます。

Test Job ran at Fri Aug 1 08:44:23 BST 2014

これは、Upstartでできることのほんの一部にすぎません。 詳細な例については後で説明しますが、ここでは、ジョブの状態とイベントの説明に移りましょう。

仕事の状態とイベント

システムジョブは/etc/init/ディレクトリにあり、ユーザージョブはユーザー自身のinitディレクトリ~/.init/にあります。

ユーザージョブはユーザー自身のセッションで実行されるため、セッションジョブとも呼ばれます。 これらはシステム全体で実行されず、PID 1の指定には含まれません。 テストジョブの目的で、/etc/initを使用して、システムの起動時にロードできるようにしました。

タイプに関係なく、ジョブは常に構成ファイル(.conf)で定義され、ファイル名は関連するサービスまたはタスクを表す必要があります。

これらの各ジョブには、startまたはstopという目標があります。 これらの2つの目標の間には、目標に関するジョブの現在のアクションを定義する一連のタスク状態があります。 重要な状態は次のとおりです。

  • 待機中:処理の初期状態
  • 開始:ジョブが開始されようとしている場所
  • pre-start:pre-startセクションがロードされる場所
  • スポーン:スクリプトセクションが実行されようとしている場所
  • ポストスタート:ポストスタート操作が行われる場所
  • 実行中:ジョブが完全に機能している場所
  • プレストップ:プレストップ操作が行われる場所
  • 停止:ジョブが停止されている場所
  • 殺された:ジョブが停止された場所
  • ポストストップ:ポストストップ操作が行われる場所-クリーンアップする

開始後の状態の後、ジョブは実行中として定義されます。 事前停止がトリガーされるまで実行を継続し、ジョブを停止する準備が整うと、ジョブが強制終了され、定義されている場合は停止後のクリーンアップ手順が実行されます。

次のコマンドを使用して、Upstartシステムログ(/var/log/upstart/ディレクトリにあります)の優先度をdebugに設定することにより、ジョブが状態間でどのように遷移するかを確認できます。

sudo initctl log-priority debug

状態はイベントではなく、イベントは状態ではないことに注意してください。 4つのイベント(開始、開始、停止、停止)はUpstartによって発行されますが、タスクの状態は、ジョブの存続期間のステージ間の遷移を定義します。

これで、サービスジョブを作成することにより、最初の構成の要素を組み込んだ、より焦点を絞った例に進む準備が整いました。 これは、基本的なテスト構成の実行から本番環境に対応したスクリプトに移行する方法を示しています。

詳細な例:サービスジョブ

はじめに簡単に説明したように、サービスジョブには、プロセスをバックグラウンドで実行できるようにする構成ファイルのスクリプトが含まれます。 基本的なNode.jsサーバーを最初からセットアップします。

Nodeに慣れていない場合、本質的には「サーバーサイドおよびネットワーキングアプリケーション用のクロスプラットフォーム環境」(Wikipedia)です。

Node.jsは非常に軽量なパッケージですが、Ubuntu14.04にはデフォルトでインストールされていません。 開始するには、先に進んでクラウドサーバーにインストールします。

sudo apt-get install nodejs

それでは、サービスジョブを始めましょう。 /etc/initnodetest.confという名前の新しいジョブ構成ファイルを作成します。 目的に応じてファイルに名前を付けることが不可欠であるため、このサービスジョブがNode.jsテスト用であることを認識できます。

sudo nano /etc/init/nodetest.conf

事前にUpstart構成を理解することが重要であるため、この例の後半でNodeアプリケーション自体について説明します。

まず最初に。 まず、ジョブの説明と作成者の行を入力して、構成を定義します。

description "Service for a test node.js server"
author      "Your Name"

このノードを利用したサーバーアプリケーションは、サーバーが稼働しているときに起動し、正常にシャットダウンしたときに停止する必要があります。 このため、必ず両方の条件を指定してください。

start on filesystem or runlevel [2345]
stop on shutdown

以前のランレベル基準を覚えていますか? filesystemイベントと組み合わせると、サーバーが正常に稼働しているときにジョブが確実に読み込まれます。

これらは基本ですが、今ではより複雑になっています。 前述のスタンザを使用します。

これはサーバーアプリケーションであるため、ジョブ構成にロギング要素を組み込みます。 Nodeアプリケーションの開始時と停止時にログに記録するため、サービスアクションを分離するためにscriptpre-start scriptpre-stop scriptの3つの異なるスタンザを使用します。

これらがおなじみのように聞こえると思うなら、あなたは絶対に正しいです。 事前開始と事前停止はジョブ状態ですが、スタンザでも機能します。 これは、ジョブの状態に基づいてさまざまなコマンドを実行できることを意味します。

ただし、最初に作成するスタンザはジョブスクリプト自体です。 これにより、ノードバックグラウンドサーバーのプロセスIDが取得され、アプリケーションスクリプトが実行されます。 スタンザ内のコマンドのインデントに注意してください。これは、構文的に正しいフォーマットに不可欠です。

script

    export HOME="/srv"
    echo $$ > /var/run/nodetest.pid
    exec /usr/bin/nodejs /srv/nodetest.js

end script

ノードではホームディレクトリ変数を設定する必要があるため、/srvがスタンザの最初の行にエクスポートされるのはなぜですか。 次に、$$を使用して、使用可能なプロセスIDを取得し、ジョブのPIDファイルを作成します。 準備ができたら、Node.jsアプリケーションが読み込まれます。これについては、後で説明します。

次に、pre-startpre-stopに焦点を当てます。これらは、単純なアプリケーションロギングに使用されます。 日付は、開始メッセージまたは停止メッセージとともに、ジョブのログファイルに追加されます。

pre-start script
    echo "[`date`] Node Test Starting" >> /var/log/nodetest.log
end script

事前停止スタンザに別の行が含まれていることに注意してください。サーバーをシャットダウンする手順の一部としてPIDファイルを削除します(事前停止の機能)。

pre-stop script
    rm /var/run/nodetest.pid
    echo "[`date`] Node Test Stopping" >> /var/log/nodetest.log
end script

これが、ソートされたUpstartジョブ構成全体です。 参考までに、これがすべてです。

description "Test node.js server"
author      "Your Name"

start on filesystem or runlevel [2345]
stop on shutdown

script

    export HOME="/srv"
    echo $$ > /var/run/nodetest.pid
    exec /usr/bin/nodejs /srv/nodetest.js

end script

pre-start script
    echo "[`date`] Node Test Starting" >> /var/log/nodetest.log
end script

pre-stop script
    rm /var/run/nodetest.pid
    echo "[`date`] Node Test Stopping" >> /var/log/nodetest.log
end script

ファイルを保存して閉じます。

exec行に記載されているように、Node.jsスクリプトはサーバーから実行されるため、目的の場所にnodetest.jsファイルを作成します(この例では/srv/を使用します) :

sudo nano /srv/nodetest.js

これはUpstartチュートリアルであるため、Node.jsコードの確認にそれほど時間をかけることはありませんが、このスクリプトが実行する内容の概要は次のとおりです。

  • ノードのHTTPモジュールを要求してロードする
  • HTTPWebサーバーを作成します
  • ヘッダーにステータス200(OK)応答を提供します
  • 「HelloWorld」を出力として書き込みます
  • ポート8888でリッスン

Nodeアプリケーションを実行するために必要なコードは次のとおりです。これを直接コピーして時間を節約できます。

var http = require("http");

http.createServer(function(request, response) {
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.write("Hello World");
    response.end();
}).listen(8888);

Node.jsファイルを保存した後、最後に確認するのは、Upstartジョブの構文が有効かどうかです。 いつものように、構成チェックコマンドを実行すると、出力として確認を受け取るはずです。

init-checkconf /etc/init/nodetest.conf 

File nodetest.conf: syntax ok

ジョブ構成を取得し、構文を確認し、Node.jsコードを保存しました。すべての準備が整ったので、Dropletを再起動して、 http:// IP :8888[にアクセスします。 X181X]、または関連するドメイン。

ウィンドウの左上隅にある「HelloWorld」に出会った場合は、Upstartサービスジョブが機能しています。

状態ベースのログを確認するには、事前定義されたログファイルを読み取ると、タイムスタンプ付きのStarting行が表示されます。 サーバーをシャットダウンするか、サービスジョブを手動で停止すると、ログにStopping行が書き込まれます。これは、必要に応じて確認することもできます。

cat /var/log/nodetest.log

[Sun Aug 17 08:08:34 EDT 2014] Node Test Starting
[Sun Aug 17 08:13:03 EDT 2014] Node Test Stopping

スターンダードの開始、停止、再起動などを実行できます。 このサービスのコマンド、および次のような構文を持つ他の同様のUpstartジョブ。

sudo service nodetest restart

結論

このチュートリアルは、UpstartEventSystemの表面をかじっただけです。 従来の初期化の背景を読み、オープンソースのUpstartソリューションがより強力な選択肢である理由を理解し、独自のジョブを書き始めました。 基本を理解したので、可能性は無限大です。

Upstart公式ウェブサイトのロゴ、著作権オリジナルデザイナー/CanonicalLtd。