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でのパーティションのフォーマットとマウントの実装

推薦する

Vueはチャットインターフェースを実装する

この記事の例では、チャットインターフェースの表示を実現するためのVueの具体的なコードを参考までに共...

原因不明のMySqlサービス消失の解決策

原因不明のMySqlサービス消失の解決策先ほど、MySQL-Front が突然 MySql を開けな...

MySQLはmysqldump+binlogを使用して、削除されたデータベースの原理分析を完全に復元します。

1. 概要MySQL データベースの日常的な操作とメンテナンスにおいて、ユーザーが誤ってデータを削...

tomcat8の最新のLinuxインストールプロセス

ダウンロード参考:ダウンロードするコアパッケージを選択してくださいダウンロード後、ファイルをサーバー...

Vue-cliフレームワークはタイマーアプリケーションを実装します

技術的背景このアプリケーションは vue-cli フレームワークを使用し、カスタム コンポーネント ...

Linux には make コマンドがありません (make: *** ターゲットが指定されておらず、makefile または make コマンドのインストール方法が見つかりません)

知らせ! ! !この状況は、実際には仮想マシンのインストール中に回避できます。次回仮想マシンをテスト...

Unix/Linux システムにおける nobody ユーザーと nologin の詳細な紹介

Unix/Linux システムの nobody ユーザーとは何ですか? 1. Windows システ...

MySQL データ型 DECIMAL の使用方法の詳細な説明

MySQL DECIMALデータ型は、データベースに正確な数値を保存するために使用されます。会計シス...

Zabbix と bat スクリプトを組み合わせて複数のアプリケーションの状態を監視する方法

シナリオシミュレーション:国内企業の中には、重要な業務をサポートするために特定のウィンドウ プログラ...

mysql-joinsの具体的な使用方法

目次結合構文: 1. InnerJOIN: (内部結合) 2. LeftJOIN: (左結合) 3....

Dockerをクリーンアンインストールする方法の詳細な説明

まず、サーバー環境情報: アンインストールの理由:しばらくするとホストマシンのディスクが100%にな...

Linux yum コマンドを使用して mysql8.0 をインストールする方法の詳細なチュートリアル

1. 設置前によく掃除する rpm -pa | grep mysql または rpm -qa | g...

Vue で video.js を使用して m3u8 形式のビデオを再生する方法

目次1. インストール2. videojsの紹介3. コンポーネントでのテストと使用1. 基本的な自...

Linux ソースコードからのソケット (TCP) バインドの詳細な説明

目次1. 最も単純なサーバー側の例2. バインドシステムコール2.1、inet_bind 2.2、i...

床スクロール効果を実現する js

この記事ではjQueryを使用して、階段のスライド効果を実装し、フロアをスクロールし、フロアボタンを...