แยกกระบวนการลูกวางไข่หลังจากเริ่มต้น


9

ฉันเริ่มต้นกระบวนการเลี้ยงลูกด้วยวิธีนี้:

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

process.unref()

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

เมื่อฉันเริ่มกระบวนการฉันต้องเก็บไว้เพราะฉันต้องการอ่านผลลัพธ์ แต่ก่อนที่จะปิดโปรเซส Node ของฉัน (แม่) ฉันต้องการแยกโพรเซสลูกที่ไม่เสร็จทั้งหมดเพื่อให้มันทำงานในแบ็คกราวน์ แต่ตามที่เอกสารอธิบาย :

เมื่อใช้ตัวเลือกที่แยกออกเพื่อเริ่มกระบวนการที่ใช้เวลานานกระบวนการจะไม่ทำงานในพื้นหลังหลังจากที่ผู้ปกครองออกจากเว้นแต่ว่าจะมีการกำหนดค่า stdio ที่ไม่ได้เชื่อมต่อกับผู้ปกครอง

แต่ด้วยตัวเลือกที่stdio: 'ignore'ฉันไม่สามารถอ่านstdoutซึ่งเป็นปัญหา

ฉันพยายามปิดท่อด้วยตนเองก่อนที่จะปิดกระบวนการหลัก แต่ไม่สำเร็จ:

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

1
ฉันสับสนเล็กน้อยว่าทำไมคุณคาดหวังว่าจะสามารถอ่าน stdout / stderr ของกระบวนการที่เป็นอิสระจากโหนด ไม่ว่าคุณจะต้องจับเอาท์พุทเพราะกระบวนการกำลังทำงานที่เป็นส่วนหนึ่งของโปรแกรมของคุณ (แค่ทำงานแบบขนาน) ซึ่งในกรณีนี้โหนดควรจะเป็นผู้ปกครอง; หรือคุณกำลังเริ่มโปรแกรมอิสระอย่างแท้จริงในกรณีที่เอาต์พุตมาตรฐานไม่ใช่ข้อกังวลของโปรแกรมโหนดของคุณและคุณควรทำให้พวกเขาแบ่งปันข้อมูลในแบบที่เหมาะสมสำหรับสองโปรแกรมอิสระ (เช่นฐานข้อมูลการตรวจสอบไฟล์เซิร์ฟเวอร์ API อะไรก็ตาม)
Kamermans 'Pomax' ของ Mike

บางทีฉันอาจจะไม่ชัดเจนพอเมื่อฉันเริ่มต้นกระบวนการที่ฉันต้องเก็บไว้เพราะฉันต้องการที่จะอ่านเอาท์พุทของมัน แต่ก่อนที่จะปิดโปรเซส Node ของฉัน (แม่) ฉันต้องการแยกโพรเซสลูกที่ยังไม่เสร็จทั้งหมดเพื่อให้มันทำงานในพื้นหลัง
Opsse

ทำไมไม่มีกระบวนการ / โปรแกรมที่แตกต่างกันและแบ่งปันข้อมูลระหว่างพวกเขาโดยใช้ไฟล์หรือวิธีอื่น ๆ
Ma'moun othman

ไม่ใช่สิ่งที่ท่อทำ ดังนั้นคุณแนะนำให้จัดการการสื่อสารระหว่างกระบวนการด้วยตัวเองเหรอ?
Opsse

แต่ทำไมคุณต้องถอดกระบวนการออก? มันกำลังทำบางสิ่งบางอย่างในการให้บริการโปรแกรมของคุณซึ่งในกรณีนี้โปรแกรมของคุณควรรอจนกว่าจะเสร็จสิ้นหรือควรส่งสัญญาณกระบวนการที่หมดเวลาและต้องทำให้เสร็จในสิ่งที่ทำเพราะกำลังจะได้รับ SIGKILL - โดยทั่วไป : กรณีการใช้งานจริงคืออะไร เพราะฟังดูเหมือนเป็นตัวเลือกอันดับหนึ่งสำหรับปัญหา XYที่คุณพยายามทำบางสิ่งและคุณคิดถึงวิธีการทำเช่นนั้นและคุณกำลังถามเกี่ยวกับวิธีการทำสิ่งนั้นแทนที่จะถามถึงปัญหาดั้งเดิม
Mike 'Pomax' Kamermans

คำตอบ:


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)

เอาท์พุต

เริ่มต้นรับ
ข้อมูลหลัก: เริ่มเด็ก

มีข้อมูล: สวัสดีจากเด็ก
มีข้อมูล: สวัสดีจากเด็ก
มีข้อมูล: สวัสดีจากเด็ก
มีข้อมูล: สวัสดีจากเด็ก
ปลดเด็ก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.