Node.js で子プロセスを作成する方法の詳細な分析
この記事では、Node.js のサブプロセスを理解し、Node.js でサブプロセスを作成する 4 つの方法を紹介します。皆様のお役に立てれば幸いです。
ご存知のとおり、Node.js はシングルスレッド、非同期、ノンブロッキングのプログラミング言語です。 CPU?これには、子プロセスを作成するための child_process モジュールが必要です。Node.js では、子プロセスを作成するには 4 つの方法があります:
exec
execFile
##spawn
-
fork
nodejs チュートリアル "]
上記 4 つのメソッドはChildProcess を返します インスタンス (
EventEmitter から継承)。これには 3 つの標準 stdio ストリームがあります:
-
child.stdin
child.stdout
- ##child.stderr
: 子プロセスの終了時にトリガーされ、パラメータはコード エラー コードとシグナル割り込みシグナルです。
: 子プロセスが終了し、stdio ストリームが閉じられるとトリガーされます。パラメータは exit
イベントと同じです。
: 親プロセスが child.disconnect()
を呼び出すか、子プロセスが process.disconnect()
を呼び出すとトリガーされます。
: 子プロセスを作成できない場合、強制終了できない場合、または子プロセスへのメッセージの送信に失敗した場合にトリガーされます。
: 子プロセスが process.send()
を通じてメッセージを送信するとトリガーされます。
: 子プロセスが正常に作成されたときにトリガーされます (このイベントは Node.js v15.1 でのみ追加されました)。
メソッドと execFile
メソッドは、子プロセスの終了時にトリガーされる追加のコールバック関数も提供します。次に、詳細な分析を行います。 exec
exec メソッドは bash コマンドの実行に使用され、そのパラメータはコマンド文字列です。たとえば、現在のディレクトリ内のファイルの数をカウントするには、exec 関数は次のように記述されます。
const { exec } = require("child_process") exec("find . -type f | wc -l", (err, stdout, stderr) => { if (err) return console.error(`exec error: ${err}`) console.log(`Number of files ${stdout}`) })
exec は、新しいサブプロセスを作成し、その実行結果をキャッシュし、実行後にコールバック関数を呼び出します。完成されました。
exec コマンドは比較的危険だと思われたかもしれませんが、ユーザーが指定した文字列を exec 関数のパラメーターとして使用すると、次のようなコマンド ライン インジェクションのリスクに直面することになります。 #
find . -type f | wc -l; rm -rf /;
const { execFile } = require("child_process")
const child = execFile("node", ["--version"], (error, stdout, stderr) => {
if (error) throw error
console.log(stdout)
})
ログイン後にコピー
作成シェルがないため、プログラムのパラメータが配列として渡されるため、安全性が高いです。 spawnspawn 関数は execFile に似ています。デフォルトではシェルは開かれませんが、異なる点は、execFile がコマンド ラインの出力をキャッシュし、その結果をコールバックに渡すことです。関数では、spawn はストリーム出力を使用しますが、ストリームを使用すると、入力と出力を接続するのに非常に便利です。たとえば、典型的な const { execFile } = require("child_process") const child = execFile("node", ["--version"], (error, stdout, stderr) => { if (error) throw error console.log(stdout) })
wc
コマンド:const child = spawn("wc") process.stdin.pipe(child.stdin) child.stdout.on("data", data => { console.log(`child stdout:\n${data}`) })
このとき、入力はユーザーが復帰
ctrl D をトリガーすると、コマンドの実行が開始され、結果が標準出力から出力されます。 wc は Word Count の略語で、単語数をカウントするために使用されます。構文は次のとおりです:
wc [OPTION]... [FILE]...
ターミナルで wc コマンドを入力して Enter キーを押すと、 、カウントはキーボードからのものです。ターミナルに文字を入力し、もう一度 Enter キーを押し、Node.js での記述方法 コマンド ラインとまったく同じです:Ctrl D
を押して統計結果を出力します。
現在のディレクトリ内のファイル数を数えるなど、パイプラインを介して複雑なコマンドを組み合わせることができます。Linux コマンド ラインでは、次のように記述されます:
find . -type f | wc -lログイン後にコピー
const find = spawn("find", [".", "-type", "f"]) const wc = spawn("wc", ["-l"]) find.stdout.pipe(wc.stdin) wc.stdout.on("data", (data) => { console.log(`Number of files ${data}`) })
const child = spawn("find . -type f | wc -l", { stdio: "inherit", // 继承父进程的输入输出流 shell: true, // 开启命令行模式 cwd: "/Users/keliq/code", // 指定执行目录 env: { ANSWER: 42 }, // 指定环境变量(默认是 process.env) detached: true, // 作为独立进程存在 })
const { fork } = require("child_process")
const forked = fork("./child.js")
forked.on("message", msg => {
console.log("Message from child", msg);
})
forked.send({ hello: "world" })
ログイン後にコピー
子プロセスのchild.jsコード: const { fork } = require("child_process") const forked = fork("./child.js") forked.on("message", msg => { console.log("Message from child", msg); }) forked.send({ hello: "world" })
process.on("message", msg => { console.log("Message from parent:", msg) }) let counter = 0 setInterval(() => { process.send({ counter: counter++ }) }, 1000)
fork("child.js")
を呼び出すとき、実際には、node を使用してファイル内のコードを実行するだけです。これは、spawn('node', ['./child.js']) と同等です。
fork の一般的なアプリケーション シナリオは次のとおりです。 Node.js を使用して http サービスを作成する場合、ルートが
compute
const http = require("http") const server = http.createServer() server.on("request", (req, res) => { if (req.url === "/compute") { const sum = longComputation() return res.end(Sum is ${sum}) } else { res.end("OK") } }) server.listen(3000);
次のコードを使用して、この時間のかかる操作をシミュレートできます:
const longComputation = () => { let sum = 0; for (let i = 0; i < 1e9; i++) { sum += i } return sum }
那么在上线后,只要服务端收到了 compute
请求,由于 Node.js 是单线程的,耗时运算占用了 CPU,用户的其他请求都会阻塞在这里,表现出来的现象就是服务器无响应。
解决这个问题最简单的方法就是把耗时运算放到子进程中去处理,例如创建一个 compute.js
的文件,代码如下:
const longComputation = () => { let sum = 0; for (let i = 0; i < 1e9; i++) { sum += i; } return sum } process.on("message", msg => { const sum = longComputation() process.send(sum) })
再把服务端的代码稍作改造:
const http = require("http") const { fork } = require("child_process") const server = http.createServer() server.on("request", (req, res) => { if (req.url === "/compute") { const compute = fork("compute.js") compute.send("start") compute.on("message", sum => { res.end(Sum is ${sum}) }) } else { res.end("OK") } }) server.listen(3000)
这样的话,主线程就不会阻塞,而是继续处理其他的请求,当耗时运算的结果返回后,再做出响应。其实更简单的处理方式是利用 cluster 模块,限于篇幅原因,后面再展开讲。
总结
掌握了上面四种创建子进程的方法之后,总结了以下三条规律:
- 创建 node 子进程用 fork,因为自带通道方便通信。
- 创建非 node 子进程用 execFile 或 spawn。如果输出内容较少用 execFile,会缓存结果并传给回调方便处理;如果输出内容多用 spawn,使用流的方式不会占用大量内存。
- 执行复杂的、固定的终端命令用 exec,写起来更方便。但一定要记住 exec 会创建 shell,效率不如 execFile 和 spawn,且存在命令行注入的风险。
更多编程相关知识,请访问:编程视频!!
以上がNode.js で子プロセスを作成する方法の詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









ノンブロッキングおよびイベント駆動に基づいて構築されたノード サービスには、メモリ消費量が少ないという利点があり、大量のネットワーク リクエストの処理に非常に適しています。大量のリクエストを前提として、「メモリ制御」に関する問題を考慮する必要があります。 1. V8 のガベージ コレクション メカニズムとメモリ制限 Js はガベージ コレクション マシンによって制御されます

この記事では、NodeJS V8 エンジンのメモリとガベージ コレクター (GC) について詳しく説明します。

ファイル モジュールは、ファイルの読み取り/書き込み/開く/閉じる/削除の追加など、基礎となるファイル操作をカプセル化したものです。ファイル モジュールの最大の特徴は、すべてのメソッドが **同期** と ** の 2 つのバージョンを提供することです。 asynchronous**、sync サフィックスが付いているメソッドはすべて同期メソッドであり、持たないメソッドはすべて異種メソッドです。

ノード用の Docker イメージの選択は些細なことのように思えるかもしれませんが、イメージのサイズと潜在的な脆弱性は、CI/CD プロセスとセキュリティに大きな影響を与える可能性があります。では、最適な Node.js Docker イメージを選択するにはどうすればよいでしょうか?

Node 19 が正式リリースされましたので、この記事では Node.js 19 の 6 つの主要な機能について詳しく説明します。

Node.js はどのように GC (ガベージ コレクション) を行うのでしょうか?次の記事で詳しく説明します。

イベント ループは Node.js の基本的な部分であり、メイン スレッドがブロックされていないことを確認することで非同期プログラミングが可能になります。イベント ループを理解することは、効率的なアプリケーションを構築するために重要です。次の記事では、Node のイベント ループについて詳しく説明します。お役に立てれば幸いです。

ノードが npm コマンドを使用できない理由は、環境変数が正しく設定されていないためです。解決策は次のとおりです: 1. 「システムのプロパティ」を開きます; 2. 「環境変数」->「システム変数」を見つけて、環境を編集します。変数; 3.nodejs フォルダーの場所を見つけます; 4.「OK」をクリックします。
