起動後にspawn子プロセスを切り離します


9

このようにして、スポーン子プロセスを開始します。

let process = spawn(apiPath, {
  detached: true
})

process.unref()

process.stdout.on('data', data => { /* do something */ })

プロセスを開始するとき、その出力を読みたいので、プロセスをアタッチしたままにする必要があります。しかし、Nodeプロセス(親)を閉じる直前に、完了していないすべての子プロセスを切り離して、バックグラウンドで実行したままにしておきたいのですが、ドキュメントでは次のように述べています。

detachedオプションを使用して長時間実行プロセスを開始する場合、親に接続されていないstdio構成が提供されていない限り、親の終了後、プロセスはバックグラウンドで実行されたままにはなりません。

しかし、オプションstdio: 'ignore'を使用stdoutすると、問題を読み取ることができません。

親プロセスを閉じる前に手動でパイプを閉じようとしましたが、失敗しました:

// Trigger just before the main process end
process.stdin.end()
process.stderr.unpipe()
process.stdout.unpipe()

1
Nodeに依存しないプロセスのstdout / stderrを読み取ることができる理由を少し混乱しています。プロセスがプログラムの一部であるタスクを実行しているため(並列で実行するだけ)、出力をキャプチャする必要があります。この場合、Node 親になります。または真に独立したプログラムを開始している場合、その標準出力はノードプログラムの問題ではないため、2つの独立したプログラム(データベース、ファイルモニター、APIサーバーなど)にとって意味のある方法でデータを共有する必要があります。 、 なんでも)。
Mike 'Pomax' Kamermans

プロセスを開始するとき、出力を読みたいので、接続を維持する必要があるので、十分に明確ではなかったのかもしれません。しかし、Nodeプロセス(親)を閉じる直前に、終了していないすべての子プロセスを切り離して、バックグラウンドで実行し続けるようにします。
Opsse

なぜ異なるプロセス/プログラムを持たず、ファイルまたは他の手段を使用してそれらの間でデータを共有するのですか?
Ma'moun othman

それはパイプがすることではありませんか?では、プロセス間の通信を自分で処理することを提案しますか?
Opsse

しかし、なぜプロセスを切り離すのでしょうか?それはあなたのプログラムのサービスで何かをしている、その場合あなたのプログラムはそれが完了するまで待つべきである、あるいはそれはそれが時間外でありそしてそれがSIGKILLされようとしているのでそれがやっていることを完了する必要があるというプロセスに合図するべきである-基本的に:実際のユースケースは何ですか?これは、何かをしようとしているXY問題の最有力候補のように聞こえ、その方法を考えていて、元の問題についてではなく、その方法について尋ねているからです
マイク「ポマックス」カマーマンズ

回答:


1

多くのテストの後、私はこの問題を解決する少なくとも1つの方法を見つけました。メインプロセスを終了する前にすべてのパイプを破棄することです。

トリッキーなポイントの1つは、子プロセスが破棄するパイプを正しく処理する必要があることです。そうでない場合は、エラーが発生し、とにかく閉じることができます。この例では、ノードの子プロセスには問題がないようですが、他のシナリオとは異なる場合があります。

main.js

const { spawn } = require('child_process')

console.log('Start Main')

let child = spawn('node', ['child.js'], { detached: true })
child.unref() // With this the main process end after fully disconnect the child

child.stdout.on('data', data => {
  console.log(`Got data : ${data}`)
})

// In real case should be triggered just before the end of the main process
setTimeout(() => {
  console.log('Disconnect the child')

  child.stderr.unpipe()
  child.stderr.destroy()
  child.stdout.unpipe()
  child.stdout.destroy()
  child.stdin.end()
  child.stdin.destroy()
}, 5000)

child.js

console.log('Start Child')

setInterval(function() {
   process.stdout.write('hello from child')
}, 1000)

出力

メイン
取得データの開始:子の開始

Got data:hello from child
Got data:hello from child
Got data:hello from child
Got data:hello from child子を
切断する

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.