NodeJSプロセスがどのように終了するかについて詳しく説明します

NodeJSプロセスがどのように終了するかについて詳しく説明します

序文

NodeJS プロセスが終了する原因はいくつかあります。これらの要因には、コードが例外をスローするなど予防可能なものもあれば、メモリ不足など予防不可能なものもあります。グローバル変数 process は、イベント エミッター インスタンスです。プロセスが正常に終了すると、プロセスは終了イベントをディスパッチします。アプリケーション コードはこのイベントをリッスンして最終的なクリーンアップを実行できます。

次の表に、プロセスが終了する原因となる要因を示します。

操作する
手動終了プロセス終了(1)
キャッチされない例外新しいエラーをスローします()
未処理の約束の拒否Promise.reject()
未処理のエラーイベントイベントエミッター#emit('error')
未処理信号<プロセスID> を強制終了する

積極的な撤退

process.exit(code) はプロセスを終了する最も直接的な方法です。コード パラメータはオプションで、0 ~ 255 の任意の数値を指定できます。デフォルト値は 0 です。0 はプロセスが正常に実行されたことを示し、0 以外の数値はプロセスが失敗したことを示します。

process.exit() を使用すると、コンソールに出力されません。プロセスが終了したときにコンソールにエラー情報を出力したい場合は、呼び出す前にエラー情報を表示する必要があります。

ノード -e "プロセス終了(42)"
$をエコーし​​ますか?

上記のコードは NodeJS プロセスを直接終了し、コマンド ラインに出力情報はありません。プロセスが終了すると、ユーザーは有効なエラー情報を取得できません。

関数 checkConfig(config) {
  if (!config.host) {
    console.error("構成に 'host' パラメータがありません!");
    プロセス終了(1);
  }
}

上記のコードでは、プロセスが終了する前に明確なエラー メッセージを出力します。

process.exit() は非常に強力ですが、ユーティリティ ライブラリでは使用しないでください。ツール ライブラリでエラーが発生した場合は、それを例外としてスローし、アプリケーション コードでエラーの処理方法を決定できるようにする必要があります。

例外、拒否、および発行されたエラー

process.exit() は、アプリケーションの起動構成チェックなどのシナリオでは非常に便利ですが、実行時例外の処理には適していないため、他のツールが必要です。

たとえば、アプリケーションが HTTP リクエストを処理しているときに、エラーによってプロセスが終了するのではなく、エラー メッセージを含む応答を返す必要があります。

Error クラスには、呼び出しスタックやエラー テキストなど、発生したエラーの詳細を説明するデータを含めることができます。通常、特定のシナリオに対して XXXError を定義し、これらの XXXError はすべて Error クラスを継承します。

throw キーワードを使用するとき、またはコード ロジックにエラーがある場合、エラーがスローされます。この時点で、システム コール スタックが解除され、現在の呼び出しをラップする try/catch ステートメントが検出されるまで、各関数は終了します。 try/catch ステートメントがない場合、エラーはキャッチされない例外と見なされます。

通常、NodeJS アプリケーションでは、特定のエラーを説明するエラー コードとして、Error クラスの code プロパティを定義します。これを行う利点は、エラー コードを一意かつ読みやすい状態に保つことができることです。同時に、メッセージ属性を使用して特定のエラー情報を記述することもできます。

キャッチされない例外がスローされると、コール スタックがコンソールに出力され、プロセスは終了ステータス 1 で終了します。

/tmp/foo.js:1
新しい TypeError をスローします ('無効な foo')。
^
エラー: 無効な foo
    Object.<anonymous> (/tmp/foo.js:2:11) で
    ... 省略されました ...
    internal/main/run_main_module.js:17:47 で

このコンソール出力は、foo.js の 2 行目、11 列目でエラーが発生したことを示しています。

グローバル変数 process は、uncaughtException イベントをリッスンしてこれらのキャッチされていない例外を処理できるイベント エミッター インスタンスです。次のコードはその使用方法を示しています。

logger は、次のコードで定義されます。
process.on("uncaughtException", (エラー) => {
  logger.send("キャッチされない例外が発生しました", error, () => {
    コンソールエラー(エラー);
    プロセス終了(1);
  });
});

Promise Rejection は例外をスローすることに似ています。拒否() 関数を呼び出すか、非同期関数で例外をスローすることで、Promise を拒否状態に到達させることができます。次の 2 つのコード スニペットは同様の機能を持ちます。

Promise.reject(new Error("ああ、だめだ"));

(非同期() => {
  新しいエラーをスローします("ああ、だめだ");
})();

現在、NodeJS 14 では、Promise Rejection によってプロセスが終了しません。以降のバージョンでは、Promise Rejection によってプロセスが終了する可能性があります。

以下は、キャッチされていない Promise 拒否のコンソール出力のサンプルです。

(ノード:52298) UnhandledPromiseRejectionWarning: エラー: ああ、だめだ
Object.<anonymous> (/tmp/reject.js:1:16) で
... 省略されました ...
internal/main/run_main_module.js:17:47 で
(ノード:52298) UnhandledPromiseRejectionWarning: 処理されていないプロミス
このエラーは、
catchブロックなしの非同期関数、またはpromiseを拒否する
これは .catch() では処理されませんでした。

unhandledRejection イベントをリッスンすることで、キャッチされていない拒否を処理できます。サンプル コードは次のとおりです。

process.on("unhandledRejection", (reason, promise) => {});

Event Emitter は NodeJS の基本モジュールであり、広く使用されています。イベント エミッターのエラー イベントが処理されない場合、イベント エミッターはエラーをスローし、プロセスを終了します。以下は、イベント エミッター エラーのコンソール出力です。

イベント.js:306
throw err; // 処理されない「エラー」イベント
^
エラー [ERR_UNHANDLED_ERROR]: 処理されないエラーです。(未定義)
EventEmitter.emit (events.js:304:17) で
Object.<anonymous> (/tmp/foo.js:1:40) で
... 省略されました ...
internal/main/run_main_module.js:17:47 {で
コード: 'ERR_UNHANDLED_ERROR'、
コンテキスト: 未定義
}

したがって、Event Emitter を使用する場合は、エラーが発生したときにアプリケーションがこれらのエラーを処理してクラッシュを回避できるように、エラー イベントをリッスンする必要があります。

信号

シグナルは、プロセス間通信のメカニズムを提供する操作メッセージです。信号は通常は数値ですが、文字列で識別することもできます。たとえば、SIGKILL は数字 9 を識別します。オペレーティング システムによって信号の定義が異なります。次の表に、基本的な共通信号の定義を示します。

名前番号処理可能ですか? NodeJS のデフォルトの動作信号が意味するもの
SIGHUP 1はいやめる親コマンドラインは閉じられています
シギント2はいやめるコマンドラインから中断してみてください(Ctrl+C)
終了3はいやめるCtrl + Zを押してコマンドラインを終了してください
シグナルキル9いいえやめるプロセスを強制終了する
SIGUSR1 10はいデバッガーを起動するユーザー定義信号
SIGUSR2 12はいやめるユーザー定義信号
シグナルターム15はいやめるプロセスは正常に終了する
シグナルストップ19いいえやめるプロセスは強制的に停止されました

この表では、信号が処理可能かどうかは、プロセスによって信号を受信して​​処理できるかどうかを示します。 NodeJS のデフォルトの動作は、このシグナルを受信した後にプロセスが実行するデフォルトのアクションを示します。

これらの信号は次の方法で監視できます。

#!/usr/bin/env ノード
console.log(`プロセスID: ${process.pid}`);
process.on("SIGHUP", () => console.log("受信: SIGHUP"));
process.on("SIGINT", () => console.log("受信: SIGINT"));
setTimeout(() => {}, 5 * 60 * 1000); // プロセスを継続する

このコードをコマンド ライン ウィンドウで実行し、Ctrl + C を押します。プロセスは終了しません。代わりに、SIGINT シグナルが受信されたことを示すログ情報の行がコンソールに出力されます。新しいコマンド ライン ウィンドウを開き、次のコマンドを実行します。PROCESS_ID は、上記のプログラムによって出力されたプロセス ID です。

kill -s SIGHUP <プロセスID>

新しいコマンドラインを通じて、元のプログラム プロセスに SIGHUP シグナルが送信され、SIGHUP シグナルが受信されたことを示すログ情報の行が元のコマンドライン ウィンドウに出力されます。

NodeJS コードでは、プロセスは他のプロセスにシグナルを送信することもできます。例えば:

node -e "process.kill(<PROCESS_ID>, 'SIGHUP')"

このコードは、SIGHUP シグナルが受信されたことを示すログ行を最初のコマンド ライン ウィンドウに出力します。

最初のコマンド ライン ウィンドウのプロセスを終了したい場合は、次のコマンドを使用します。

kill -9 <プロセスID>

NodeJS では、プロセスの正常な終了を制御するためにシグナルがよく使用されます。たとえば、Kubernetes では、ポッドが終了しようとすると、k8s はポッド内のプロセスに SIGTERM シグナルを送信し、30 秒のタイマーを開始します。アプリケーションには、接続を閉じたり、データを保存するなどの操作を行うのに 30 秒かかります。 30 秒経過してもプロセスがまだ実行中の場合、k8s は別の SIGKILL を送信してプロセスを強制的に閉じます。

まとめ

この記事では、プロセスが終了する原因となるいくつかの要因について説明します。

  • 積極的な撤退
  • キャッチされない例外、処理されないプロミス拒否、処理されないイベントエミッターエラーイベント
  • システム信号

NodeJS プロセスを終了する方法についての記事はこれで終わりです。NodeJS プロセス終了の詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Node.js プロセス終了の詳細な理解

<<:  MySQLで負荷分散を実装する方法

>>:  Centos7でのパーティションのフォーマットとマウントの実装

推薦する

HTML で色を表すには、6 桁の 16 進コード、RGB、またはキーワードを使用します。

HTML で色を表す方法は 3 つありますが、最もよく使われるのは 6 桁の 16 進コード表現です...

MySQL データ操作 - DML ステートメントの使用

例示するDML(データ操作言語)とは、データベースの追加、削除、変更を行うための操作命令のことです。...

Iframe の内外のページで JS がどのように動作するかの概要

目次iframeの外側のiframeのコンテンツを取得する方法1方法2 iframe 内の ifra...

Reactプロジェクトで要素を使用する方法

React プロジェクトで要素フレームワークを使用するのは今回が初めてです。非常に単純な問題に遭遇し...

Nginx の動的および静的分離実装ケースのコード分析

静的と動的の分離動的リクエストと静的リクエストはミドルウェアを通じて分離され、不要なリクエストの消費...

IE6/7 における a.getAttribute(href,2) 問題の分析と解決

簡単な説明<br />IE6および7では、一般的なaタグ(HTMLで記述され、DOM操作...

ユーザーエクスペリエンスの76の経験ポイントの要約

ウェブサイト体験の分類1. 感覚体験:快適性を重視した視聴覚体験をユーザーに提供します。 2. イン...

Apache POIの基本的な使い方の詳しい説明

目次基本的な紹介入門テスト (Excel ファイルからのデータの読み取り)ステップ1: Maven座...

Pycharm2017はpython3.6とmysqlの接続を実現します

この記事では、pycharm2017でpython3.6とmysqlを接続する方法を参考までに紹介し...

MySQL 5.7.17 zip パッケージ バージョンを Windows 10 にインストールするチュートリアル

mysql5.7.17のインストールチュートリアルを参考までに共有します。具体的な内容は次のとおりで...

MySQL タイムスタンプ比較クエリで遭遇する落とし穴と解決策

目次タイムスタンプ比較クエリで遭遇する落とし穴タイムスタンプクエリ範囲の問題タイムスタンプ比較クエリ...

グローバルトーストコンポーネントをカプセル化するVueの完全な例

目次序文1. vue-cliを使う1. Toastコンポーネントを定義する2. main.jsで設定...

Vueでeslintを使用する方法の詳細な説明

目次1. 説明2. 関連する依存パッケージをダウンロードする3. 設定ファイル .eslintrc....

mysql のインデックスと FROM_UNIXTIME に関する問題

ゼロ、背景今週の木曜日にたくさんのアラートを受け取りました。DBA に確認を依頼したところ、遅いクエ...

MySQL 8.0.15 winx64 解凍版のインストールと設定方法のグラフィックチュートリアル

この記事では、MySQL 8.0.15 winx64解凍版のインストールと設定方法を紹介します。具体...