โหนดได้รับการออกแบบมาเพื่อจัดการการดำเนินงาน I/O อย่างมีประสิทธิภาพ แต่คุณควรรู้ว่าโปรแกรมบางประเภทไม่เหมาะสำหรับโหมดนี้ ตัวอย่างเช่นหากคุณวางแผนที่จะใช้โหนดเพื่อจัดการกับงานที่ต้องใช้ CPU มากคุณสามารถบล็อกลูปเหตุการณ์และลดการตอบสนองของโปรแกรม อีกทางเลือกหนึ่งคือการกำหนดงานที่ต้องใช้ CPU ให้กับกระบวนการแยกต่างหากเพื่อจัดการดังนั้นจึงทำให้เกิดการวนซ้ำเหตุการณ์ โหนดช่วยให้คุณสามารถวางไข่กระบวนการและใช้กระบวนการใหม่นี้เป็นลูกของกระบวนการแม่ ในโหนดกระบวนการเด็กสามารถสื่อสารในสองทางด้วยกระบวนการหลักและในระดับหนึ่งกระบวนการหลักยังสามารถตรวจสอบและจัดการกระบวนการเด็กได้
อีกกรณีหนึ่งที่คุณต้องใช้กระบวนการเด็กคือเมื่อคุณต้องการเพียงแค่เรียกใช้คำสั่งภายนอกและปล่อยให้โหนดรับค่าส่งคืนของคำสั่ง ตัวอย่างเช่นคุณสามารถเรียกใช้คำสั่ง UNIX สคริปต์หรือคำสั่งอื่น ๆ ที่ไม่สามารถดำเนินการโดยตรงในโหนด
บทนี้จะแสดงวิธีดำเนินการคำสั่งภายนอกสร้างและสื่อสารกับเด็ก ๆ และยุติเด็ก ๆ ประเด็นก็คือให้คุณทราบถึงวิธีการทำชุดงานนอกกระบวนการโหนด ดำเนินการคำสั่งภายนอก เมื่อคุณต้องการเรียกใช้คำสั่งเชลล์ภายนอกหรือเรียกใช้งานได้คุณสามารถใช้โมดูล child_process เพื่อนำเข้าเช่นนี้: การคัดลอกรหัสมีดังนี้: var child_process = ต้องการ ('child_process') จากนั้นคุณสามารถใช้ฟังก์ชั่น exec ในโมดูลเพื่อเรียกใช้คำสั่งภายนอก: การคัดลอกรหัสมีดังนี้: var exec = child_process.exec; EXEC (คำสั่ง, การโทรกลับ); พารามิเตอร์แรกของ EXEC คือสตริงคำสั่งเชลล์ที่คุณกำลังเตรียมที่จะดำเนินการและพารามิเตอร์ที่สองเป็นฟังก์ชันการเรียกกลับ ฟังก์ชั่นการโทรกลับนี้จะถูกเรียกเมื่อ EXEC ดำเนินการเสร็จสิ้นการเรียกใช้คำสั่งภายนอกหรือเกิดข้อผิดพลาด ฟังก์ชั่นการเรียกกลับมีพารามิเตอร์สามตัว: ข้อผิดพลาด, stdout, stderr, ดูตัวอย่างต่อไปนี้: การคัดลอกรหัสมีดังนี้: exec ('ls', ฟังก์ชั่น (err, stdout, stderr) { // หมายเหตุของนักแปล: หากคุณใช้ Windows คุณสามารถเปลี่ยนเป็นคำสั่ง Windows เช่น DIR และฉันจะไม่ทำซ้ำในภายหลัง - หากเกิดข้อผิดพลาดพารามิเตอร์แรกจะเป็นอินสแตนซ์ของคลาสข้อผิดพลาด หากพารามิเตอร์แรกไม่มีข้อผิดพลาดพารามิเตอร์ที่สอง stdout จะมีเอาต์พุตมาตรฐานของคำสั่ง พารามิเตอร์สุดท้ายมีเอาต์พุตข้อผิดพลาดที่เกี่ยวข้องกับคำสั่ง รายการ 8-1 แสดงตัวอย่างที่ซับซ้อนมากขึ้นในการดำเนินการคำสั่งภายนอก รายการ 8-1: ดำเนินการคำสั่งภายนอก (ซอร์สโค้ด: บทที่ 8/01_External_Command.js) การคัดลอกรหัสมีดังนี้: // นำเข้าฟังก์ชั่น exec ของโมดูล child_process var exec = ต้องการ ('child_process'). exec; // เรียกคำสั่ง "cat *.js | wc -l" exec ('cat *.js | wc l', ฟังก์ชั่น (err, stdout, stderr) {// line 4 // คำสั่งออกหรือการโทรล้มเหลว ถ้า (err) { // ล้มเหลวในการเริ่มกระบวนการภายนอก console.log ('child_process ออก, รหัสข้อผิดพลาดคือ:', err.code); กลับ; - - ในบรรทัดที่สี่เราผ่าน "cat *.js | wc -l" เป็นพารามิเตอร์แรกของ Exec นอกจากนี้คุณยังสามารถลองใช้คำสั่งอื่น ๆ ตราบใดที่คำสั่งที่คุณใช้ในเชลล์ก็โอเค จากนั้นใช้ฟังก์ชั่นการเรียกกลับเป็นพารามิเตอร์ที่สองซึ่งจะถูกเรียกเมื่อเกิดข้อผิดพลาดหรือกระบวนการเด็กสิ้นสุดลง นอกจากนี้คุณยังสามารถผ่านพารามิเตอร์ตัวเลือกที่สามก่อนฟังก์ชั่นการโทรกลับซึ่งมีตัวเลือกการกำหนดค่าบางอย่างเช่น: การคัดลอกรหัสมีดังนี้: var exec = ต้องการ ('child_process'). exec; ตัวเลือก var = { หมดเวลา: 1,000 Killsignal: 'Sigkill' - exec ('cat *.js | wc l', ตัวเลือก, ฟังก์ชั่น (err, stdout, stderr) { - - พารามิเตอร์ที่สามารถใช้ได้คือ: 1.CWD - ไดเรกทอรีปัจจุบันคุณสามารถระบุไดเรกทอรีการทำงานปัจจุบัน 2. การเข้ารหัส-รูปแบบการเข้ารหัสของเนื้อหาเอาต์พุตกระบวนการเด็กค่าเริ่มต้นคือ "UTF8" นั่นคือการเข้ารหัส UTF-8 หากผลลัพธ์ของกระบวนการเด็กไม่ใช่ UTF8 คุณสามารถใช้พารามิเตอร์นี้เพื่อตั้งค่า รูปแบบการเข้ารหัสที่รองรับคือ: การคัดลอกรหัสมีดังนี้: ASCII UTF8 UCS2 ฐาน 64 หากคุณต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับรูปแบบการเข้ารหัสเหล่านี้ที่รองรับโดยโหนดโปรดดูบทที่ 4 "การใช้บัฟเฟอร์เพื่อประมวลผลการเข้ารหัสและการถอดรหัสข้อมูลไบนารี" 1.TimeOut - การหมดเวลาดำเนินการคำสั่งในมิลลิวินาทีค่าเริ่มต้นคือ 0 นั่นคือไม่มีการ จำกัด และรอจนกว่ากระบวนการเด็กจะสิ้นสุดลง 2.MAXBUFFER - ระบุจำนวนไบต์สูงสุดที่อนุญาตโดยสตรีม StDOUT และสตรีม StderR หากถึงค่าสูงสุดกระบวนการเด็กจะถูกฆ่า ค่าเริ่มต้นคือ 200*1024 3. Killsignal - สัญญาณสิ้นสุดที่ส่งไปยังกระบวนการเด็กเมื่อหมดเวลาหรือแคชเอาท์พุทถึงค่าสูงสุด ค่าเริ่มต้นคือ "sigterm" ซึ่งจะส่งสัญญาณการเลิกจ้างไปยังกระบวนการเด็ก สิ่งนี้มักจะใช้เพื่อยุติกระบวนการอย่างเป็นระเบียบ เมื่อใช้สัญญาณ sigterm กระบวนการยังสามารถประมวลผลหรือเขียนพฤติกรรมเริ่มต้นของตัวประมวลผลสัญญาณหลังจากได้รับ หากกระบวนการเป้าหมายต้องการคุณสามารถส่งสัญญาณอื่น ๆ ในเวลาเดียวกัน (เช่น SIGUSR1) นอกจากนี้คุณยังสามารถเลือกที่จะส่งสัญญาณ Sigkill ซึ่งจะดำเนินการโดยระบบปฏิบัติการและบังคับให้กระบวนการเด็กถูกยกเลิกทันทีเพื่อให้การดำเนินการทำความสะอาดของกระบวนการเด็กจะไม่ถูกดำเนินการ หากคุณต้องการควบคุมการสิ้นสุดของกระบวนการต่อไปคุณสามารถใช้คำสั่ง child_process.spawn ซึ่งจะมีการแนะนำในภายหลัง 1.evn - ระบุตัวแปรสภาพแวดล้อมที่ส่งผ่านไปยังกระบวนการเด็ก ค่าเริ่มต้นคือ NULL ซึ่งหมายความว่ากระบวนการเด็กจะสืบทอดตัวแปรสภาพแวดล้อมของกระบวนการหลักทั้งหมดก่อนที่จะถูกสร้างขึ้น หมายเหตุ: การใช้ตัวเลือก Killsignal คุณสามารถส่งสัญญาณไปยังกระบวนการเป้าหมายเป็นสตริง ในโหนดสัญญาณมีอยู่เป็นสตริง นี่คือรายการสัญญาณ UNIX และการดำเนินการเริ่มต้นที่สอดคล้องกัน: คุณอาจต้องการจัดเตรียมชุดของตัวแปรสภาพแวดล้อมหลักที่ขยายได้สำหรับกระบวนการเด็ก หากคุณปรับเปลี่ยนวัตถุ Process.env โดยตรงคุณจะเปลี่ยนตัวแปรสภาพแวดล้อมของโมดูลทั้งหมดในกระบวนการโหนดซึ่งจะทำให้เกิดปัญหามากมาย ทางเลือกคือการสร้างวัตถุใหม่และคัดลอกพารามิเตอร์ทั้งหมดใน process.env ดูตัวอย่าง 8-2: รายการ 8-2: ใช้ตัวแปรสภาพแวดล้อมพารามิเตอร์เพื่อดำเนินการคำสั่ง (ซอร์สโค้ด: บทที่ 8/02_ENV_VARS_AUGMENT.JS) การคัดลอกรหัสมีดังนี้: var env = process.env ชื่อวุ้น Envcopy = {} EXEC = ต้องการ ('child_process'). Exec; // คัดลอก process.env ไปยัง Envcopy สำหรับ (vaname in ev) { envcopy [varname] = env [varname]; - // ตั้งค่าตัวแปรที่กำหนดเองบางส่วน envcopy ['custom env var1'] = 'บางค่า'; envcopy ['custom env var2'] = 'ค่าอื่น ๆ '; // ดำเนินการคำสั่งโดยใช้ process.env และตัวแปรที่กำหนดเอง exec ('ls la', {env: envcopy}, ฟังก์ชั่น (err, stdout, stderr) { ถ้า (err) {โยน err; - console.log ('stdout:', stdout); console.log ('stderr:', stderr); - ในตัวอย่างข้างต้นตัวแปร Envcopy ถูกสร้างขึ้นเพื่อบันทึกตัวแปรสภาพแวดล้อม ก่อนอื่นจะคัดลอกตัวแปรสภาพแวดล้อมของกระบวนการโหนดจาก process.env จากนั้นเพิ่มหรือแทนที่ตัวแปรสภาพแวดล้อมบางอย่างที่จำเป็นต้องแก้ไขและในที่สุดก็ผ่าน Envcopy เป็นพารามิเตอร์ตัวแปรสภาพแวดล้อมไปยังฟังก์ชัน Exec และดำเนินการคำสั่งภายนอก โปรดจำไว้ว่าตัวแปรสภาพแวดล้อมจะถูกส่งผ่านระหว่างกระบวนการผ่านระบบปฏิบัติการและค่าตัวแปรสภาพแวดล้อมทุกประเภทมาถึงกระบวนการเด็กเป็นสตริง ตัวอย่างเช่นหากกระบวนการหลักใช้หมายเลข 123 เป็นตัวแปรสภาพแวดล้อมกระบวนการเด็กจะได้รับ "123" เป็นสตริง ในตัวอย่างต่อไปนี้สคริปต์โหนดสองจะถูกสร้างขึ้นในไดเรกทอรีเดียวกัน: parent.js และ child.js สคริปต์แรกจะเรียกสคริปต์ที่สอง มาสร้างไฟล์สองไฟล์นี้กันเถอะ: รายชื่อ 8-3: กระบวนการหลักตั้งค่าตัวแปรสภาพแวดล้อม (บทที่ 8/03_ENVironment_number_parent.js) การคัดลอกรหัสมีดังนี้: var exec = ต้องการ ('child_process'). exec; exec ('node child.js', {env: {number: 123}}, ฟังก์ชั่น (err, stdout, stderr) { ถ้า (err) {โยน err; - console.log ('stdout:/n', stdout); console.log ('stderr:/n', stderr); - บันทึกรหัสนี้ไปยัง Parent.js ต่อไปนี้เป็นซอร์สโค้ดของกระบวนการเด็กและบันทึกไว้ใน child.js (ดูตัวอย่าง 8-4) ตัวอย่างที่ 8-4: ตัวแปรสภาพแวดล้อมย่อย (บทที่ 8/04_environment_number_child.js) การคัดลอกรหัสมีดังนี้: var number = process.env.number; console.log (typeof (number)); // → "สตริง" number = parseInt (หมายเลข, 10); console.log (typeof (number)); // → "หมายเลข" หลังจากที่คุณบันทึกไฟล์นี้เป็น child.js คุณสามารถเรียกใช้คำสั่งต่อไปนี้ในไดเรกทอรีนี้: การคัดลอกรหัสมีดังนี้: $ node parent.js คุณจะเห็นผลลัพธ์ต่อไปนี้: การคัดลอกรหัสมีดังนี้: sdtou: สาย ตัวเลข Stderr: อย่างที่คุณเห็นแม้ว่ากระบวนการหลักจะผ่านตัวแปรสภาพแวดล้อมตัวเลข แต่กระบวนการเด็กจะได้รับเป็นสตริง (ดูบรรทัดที่สองของเอาต์พุต) และในบรรทัดที่สามที่คุณแยกวิเคราะห์สตริงเป็นตัวเลข สร้างกระบวนการเด็ก อย่างที่คุณเห็นคุณสามารถใช้ฟังก์ชัน child_process.exec () เพื่อเริ่มกระบวนการภายนอกและเรียกใช้ฟังก์ชั่นการโทรกลับของคุณในตอนท้ายของกระบวนการ ใช้งานง่ายมาก แต่มีข้อเสียบางประการ: 1. นอกเหนือจากการใช้พารามิเตอร์บรรทัดคำสั่งและตัวแปรสภาพแวดล้อมแล้ว Exec () ไม่สามารถสื่อสารกับกระบวนการเด็กได้ 2. เอาต์พุตของกระบวนการเด็กถูกแคชดังนั้นคุณจึงไม่สามารถสตรีมได้มันอาจไม่มีหน่วยความจำ โชคดีที่โมดูล child_process ของ Node ช่วยให้ความละเอียดได้ดียิ่งขึ้นในการควบคุมการเริ่มต้นหยุดและการดำเนินงานทั่วไปอื่น ๆ ของกระบวนการเด็ก คุณสามารถเริ่มกระบวนการเด็กใหม่ในแอปพลิเคชัน Node จัดเตรียมช่องทางการสื่อสารแบบสองทางช่วยให้กระบวนการพาเรนต์และเด็กสามารถส่งและรับข้อมูลสตริงจากกันและกัน กระบวนการหลักสามารถมีการดำเนินการด้านการจัดการสำหรับกระบวนการเด็กส่งสัญญาณไปยังกระบวนการเด็กและปิดกระบวนการเด็กอย่างแข็งขัน สร้างกระบวนการเด็ก คุณสามารถใช้ฟังก์ชัน child_process.spawn เพื่อสร้างกระบวนการเด็กใหม่ดูตัวอย่าง 8-5: ตัวอย่าง 8-5: สร้างกระบวนการเด็ก (บทที่ 8/05_Spawning_child.js) การคัดลอกรหัสมีดังนี้: // นำเข้าฟังก์ชั่นการวางไข่ของโมดูล child_process var spawn = ต้องการ ('child_process'). วางไข่; // สร้างกระบวนการเด็กที่ใช้ในการเรียกใช้คำสั่ง "tail -f /var/log/system.log" var child = วางไข่ ('tail', ['-f', '/var/log/system.log']); รหัสข้างต้นสร้างกระบวนการเด็กที่ใช้ในการเรียกใช้คำสั่งหางและใช้ "-f" และ "/bar/log/system.log" เป็นพารามิเตอร์ คำสั่ง tail จะตรวจสอบไฟล์ /var/log/system.og (ถ้ามี) จากนั้นส่งออกข้อมูลใหม่ทั้งหมดที่ผนวกเข้ากับสตรีมเอาท์พุทมาตรฐาน stdout ฟังก์ชั่นการวางไข่ส่งคืนวัตถุเด็ก ๆ ซึ่งเป็นวัตถุตัวชี้ห่อหุ้มอินเทอร์เฟซการเข้าถึงของกระบวนการจริง ในตัวอย่างนี้เรากำหนดคำอธิบายใหม่นี้ให้กับตัวแปรที่เรียกว่าเด็ก ฟังข้อมูลจากกระบวนการเด็ก การจัดการกระบวนการเด็กใด ๆ ที่มีแอตทริบิวต์ stdout จะใช้ผลลัพธ์มาตรฐานของกระบวนการเด็กเป็นวัตถุสตรีม คุณสามารถผูกเหตุการณ์ข้อมูลบนวัตถุสตรีมนี้เพื่อให้เมื่อใดก็ตามที่มีบล็อกข้อมูลฟังก์ชันการโทรกลับที่สอดคล้องกันจะถูกเรียกดูตัวอย่างต่อไปนี้: การคัดลอกรหัสมีดังนี้: // พิมพ์ผลลัพธ์ของกระบวนการเด็กไปยังคอนโซล child.stdout.on ('data', function (data) { console.log ('เอาต์พุตหาง:' + data); - เมื่อใดก็ตามที่การประมวลผลของเด็กส่งออกข้อมูลไปยัง output มาตรฐาน stdout กระบวนการหลักจะได้รับแจ้งและพิมพ์ข้อมูลไปยังคอนโซล นอกเหนือจากเอาต์พุตมาตรฐานแล้วกระบวนการยังมีสตรีมเอาต์พุตเริ่มต้นอื่น: สตรีมข้อผิดพลาดมาตรฐานซึ่งมักจะใช้ในการส่งออกข้อมูลข้อผิดพลาด ในตัวอย่างนี้หากไม่มีไฟล์/var/log/system.log กระบวนการหางจะส่งออกข้อความคล้ายกับต่อไปนี้: "/var/log/system.log: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว" โดยการฟังสตรีม Stderr กระบวนการพาเรนต์จะได้รับแจ้งเมื่อเกิดข้อผิดพลาดนี้ กระบวนการหลักสามารถฟังสตรีมข้อผิดพลาดมาตรฐานเช่นนี้: การคัดลอกรหัสมีดังนี้: child.stderr.on ('data', function (data) { console.log ('เอาต์พุตข้อผิดพลาดหาง:', ข้อมูล); - คุณสมบัติ stderr เช่น stdout ยังเป็นสตรีมแบบอ่านอย่างเดียว เมื่อใดก็ตามที่การประมวลผลของเด็กส่งออกข้อมูลไปยังสตรีมข้อผิดพลาดมาตรฐานกระบวนการพาเรนต์จะได้รับการแจ้งเตือนและส่งออก ส่งข้อมูลไปยังกระบวนการเด็ก นอกเหนือจากการรับข้อมูลจากกระแสเอาต์พุตของกระบวนการเด็กกระบวนการแม่ยังสามารถเขียนข้อมูลลงในอินพุตมาตรฐานของกระบวนการเด็กผ่านคุณสมบัติ ChildPoces.stdin เพื่อส่งข้อมูลไปยังกระบวนการเด็ก กระบวนการเด็กสามารถฟังข้อมูลอินพุตมาตรฐานผ่านกระบวนการสตรีมแบบอ่านอย่างเดียว แต่ควรระวังว่าคุณจะต้องดำเนินการต่อกระแสอินพุตมาตรฐานก่อนหน้านี้เนื่องจากอยู่ในสถานะหยุดชั่วคราวโดยค่าเริ่มต้น ตัวอย่าง 8-6 จะสร้างโปรแกรมที่มีฟังก์ชั่นต่อไปนี้: 1.+1 แอปพลิเคชัน: แอปพลิเคชันง่าย ๆ ที่สามารถรับจำนวนเต็มจากอินพุตมาตรฐานจากนั้นเพิ่มพวกเขาจากนั้นส่งออกผลลัพธ์หลังจากเพิ่มเติมไปยังสตรีมเอาต์พุตมาตรฐาน ในฐานะที่เป็นบริการคอมพิวเตอร์อย่างง่ายแอปพลิเคชันนี้จำลองกระบวนการโหนดเป็นบริการภายนอกที่สามารถทำงานเฉพาะได้ 2. ทดสอบไคลเอนต์ของแอปพลิเคชัน +1 ส่งจำนวนเต็มแบบสุ่มแล้วส่งออกผลลัพธ์ ใช้เพื่อแสดงให้เห็นว่ากระบวนการโหนดสร้างกระบวนการเด็กอย่างไรจากนั้นให้ทำงานเฉพาะ ใช้รหัสต่อไปนี้ในตัวอย่าง 8-6 เพื่อสร้างไฟล์ชื่อ Plus_one.js: ตัวอย่าง 8-6: +1 แอปพลิเคชัน (บทที่ 8/06_plus_one.js) การคัดลอกรหัสมีดังนี้: // กู้คืนสตรีมอินพุตมาตรฐานที่หยุดชั่วคราวโดยค่าเริ่มต้น process.stdin.resume (); process.stdin.on ('data', function (data) { หมายเลข var; พยายาม { // แยกวิเคราะห์ข้อมูลอินพุตเป็นจำนวนเต็ม number = parseInt (data.toString (), 10); // +1 หมายเลข += 1; // ผลลัพธ์ผลลัพธ์ process.stdout.write (หมายเลข + "/n"); } catch (err) { process.stderr.write (err.message + "/n"); - - ในรหัสข้างต้นเรารอข้อมูลจากสตรีมอินพุตมาตรฐาน Stdin เมื่อใดก็ตามที่ข้อมูลพร้อมใช้งานเราถือว่าเป็นจำนวนเต็มและแยกวิเคราะห์เป็นตัวแปรจำนวนเต็มจากนั้นเพิ่ม 1 และส่งออกผลลัพธ์ไปยังสตรีมเอาต์พุตมาตรฐาน คุณสามารถเรียกใช้โปรแกรมนี้ผ่านคำสั่งต่อไปนี้: การคัดลอกรหัสมีดังนี้: $ node plus_one.js หลังจากทำงานโปรแกรมจะเริ่มรออินพุต หากคุณป้อนจำนวนเต็มและกด Enter คุณจะเห็นหมายเลขหลังจากเพิ่ม 1 เพื่อแสดงบนหน้าจอ คุณสามารถออกจากโปรแกรมได้โดยกด Ctrl-C ไคลเอนต์ทดสอบ ตอนนี้คุณต้องการสร้างกระบวนการโหนดเพื่อใช้บริการคอมพิวเตอร์ที่จัดทำโดย "+1 แอปพลิเคชัน" ก่อนหน้านี้ ก่อนอื่นสร้างไฟล์ชื่อ plus_one_test.js ดูตัวอย่าง 8-7: ตัวอย่าง 8-7: แอปพลิเคชันทดสอบ +1 (บทที่ 8/07_plus_one_test.js) การคัดลอกรหัสมีดังนี้: var spawn = ต้องการ ('child_process'). วางไข่; // สร้างกระบวนการเด็กเพื่อดำเนินการแอปพลิเคชัน +1 var child = วางไข่ ('โหนด', ['plus_one.js']); // เรียกฟังก์ชั่นทุกวินาที setInterval (function () { // สร้างหมายเลขสุ่มที่เล็กกว่า 10.000 var number = math.floor (math.random () * 10,000); // ส่งหมายเลขนั้นไปยังกระบวนการเด็ก: child.stdin.write (หมายเลข + "/n"); // รับการตอบกลับจากกระบวนการเด็กและพิมพ์: child.stdout.once ('data', function (data) { console.log ('เด็กตอบกลับ' + number + 'ด้วย:' + data); - }, 1,000); child.stderr.on ('data', function (data) { process.stdout.write (ข้อมูล); - จากบรรทัดแรกไปยังบรรทัดที่สี่กระบวนการเด็กเริ่มเรียกใช้ "+1 แอปพลิเคชัน" จากนั้นการดำเนินการต่อไปนี้จะดำเนินการทุกวินาทีโดยใช้ฟังก์ชัน setInterval: 1. สร้างหมายเลขสุ่มใหม่น้อยกว่า 10,000 2. ส่งหมายเลขนี้เป็นสตริงไปยังกระบวนการเด็ก 3. รอให้กระบวนการเด็กตอบกลับสตริง 4. เนื่องจากคุณต้องการรับเพียง 1 หมายเลขในแต่ละครั้งคุณต้องใช้ child.stdout.once แทนที่จะเป็น child.stdout.on หากใช้งานหลังฟังก์ชั่นการโทรกลับของเหตุการณ์ข้อมูลจะลงทะเบียนทุก ๆ 1 วินาที แต่ละฟังก์ชั่นการโทรกลับที่ลงทะเบียนจะถูกดำเนินการเมื่อ STDout ของกระบวนการเด็กได้รับข้อมูล ด้วยวิธีนี้คุณจะพบว่าผลการคำนวณเดียวกันจะถูกส่งออกหลายครั้ง เห็นได้ชัดว่าพฤติกรรมนี้ผิด รับการแจ้งเตือนเมื่อออกจากกระบวนการเด็ก เมื่อกระบวนการเด็กออกไปเหตุการณ์ทางออกจะถูกไล่ออก ตัวอย่าง 8-8 แสดงวิธีการฟัง: ตัวอย่าง 8-8: ฟังเหตุการณ์ทางออกของกระบวนการเด็ก (บทที่ 8/09_listen_child_exit.js) การคัดลอกรหัสมีดังนี้: var spawn = ต้องการ ('child_process'). วางไข่; // สร้างกระบวนการเด็กเพื่อดำเนินการคำสั่ง "ls -la" var child = วางไข่ ('ls', ['-la']); child.stdout.on ('data', function (data) { console.log ('ข้อมูลจากเด็ก:' + data); - // เมื่อกระบวนการเด็กออกจาก: <strong> child.on ('ออก', ฟังก์ชั่น (รหัส) { console.log ('กระบวนการเด็กยกเลิกด้วยรหัส' + รหัส); }); </strong> ในสองสามบรรทัดสุดท้ายของรหัสสีดำกระบวนการหลักใช้เหตุการณ์ทางออกของกระบวนการเด็กเพื่อฟังเหตุการณ์ทางออก เมื่อเหตุการณ์เกิดขึ้นคอนโซลจะแสดงผลลัพธ์ที่สอดคล้องกัน รหัสออกของกระบวนการเด็กจะถูกส่งผ่านไปยังฟังก์ชันการโทรกลับเป็นพารามิเตอร์แรก บางโปรแกรมใช้รหัสออกที่ไม่ใช่ 0 เพื่อแสดงสถานะความล้มเหลวที่แน่นอน ตัวอย่างเช่นหากคุณพยายามเรียกใช้คำสั่ง "ls al click filename.txt" แต่ไดเรกทอรีปัจจุบันไม่มีไฟล์นี้คุณจะได้รับรหัสออกที่มีค่า 1 ดูตัวอย่าง 8-9: ตัวอย่าง 8-9: รับรหัสออกของกระบวนการเด็ก (บทที่ 8/10_Child_exit_Code.js) การคัดลอกรหัสมีดังนี้: var spawn = ต้องการ ('child_process'). วางไข่; // สร้างกระบวนการเด็กและดำเนินการคำสั่ง "LS DON_NOT_EXIST.TXT" var child = วางไข่ ('ls', ['does_not_exist.txt']); // เมื่อกระบวนการเด็กออก child.on ('ออก', ฟังก์ชั่น (รหัส) { console.log ('กระบวนการเด็กยกเลิกด้วยรหัส' + รหัส); - ในตัวอย่างนี้เหตุการณ์ทางออกจะกระตุ้นฟังก์ชั่นการโทรกลับและส่งผ่านรหัสออกของกระบวนการเด็กเป็นพารามิเตอร์แรก หากกระบวนการเด็กออกไปอย่างผิดปกติเนื่องจากถูกฆ่าตายโดยสัญญาณรหัสสัญญาณที่เกี่ยวข้องจะถูกส่งผ่านไปยังฟังก์ชันการโทรกลับเป็นพารามิเตอร์ที่สองดังตัวอย่างในตัวอย่าง 8-10: รายการ 8-10: รับสัญญาณออกของกระบวนการเด็ก (บทที่ 8/11_Child_exit_signal.js) การคัดลอกรหัสมีดังนี้: var spawn = ต้องการ ('child_process'). วางไข่; // สร้างกระบวนการเด็กและเรียกใช้คำสั่ง "sleep 10" var child = วางไข่ ('sleep', ['10']); settimeout (function () { เด็ก kill (); }, 1,000); child.on ('ออก', ฟังก์ชั่น (รหัส, สัญญาณ) { ถ้า (รหัส) { console.log ('กระบวนการเด็กยกเลิกด้วยรหัส' + รหัส); } อื่นถ้า (สัญญาณ) { console.log ('กระบวนการเด็กยกเลิกเนื่องจากสัญญาณ' + สัญญาณ); - - ในตัวอย่างนี้กระบวนการเด็กเริ่มทำการนอนหลับ 10 วินาที แต่สัญญาณ Sigkill จะถูกส่งไปยังกระบวนการเด็กก่อน 10 วินาทีซึ่งจะส่งผลให้ผลลัพธ์ต่อไปนี้: การคัดลอกรหัสมีดังนี้: กระบวนการเด็กสิ้นสุดลงเนื่องจากสัญญาณ sigterm ส่งสัญญาณและฆ่ากระบวนการ ในส่วนนี้คุณจะได้เรียนรู้วิธีการใช้สัญญาณเพื่อจัดการกระบวนการย่อย สัญญาณเป็นวิธีที่ง่ายสำหรับกระบวนการหลักในการสื่อสารกับเด็กและแม้แต่ฆ่าเด็ก รหัสสัญญาณที่แตกต่างกันแสดงถึงความหมายที่แตกต่างกันและมีสัญญาณมากมายซึ่งบางอย่างเป็นรหัสที่พบบ่อยที่สุดที่ใช้ในการฆ่ากระบวนการ หากกระบวนการได้รับสัญญาณว่าไม่ทราบวิธีจัดการโปรแกรมจะถูกขัดจังหวะโดยข้อยกเว้น สัญญาณบางอย่างถูกประมวลผลโดยกระบวนการย่อยในขณะที่ระบบอื่นสามารถประมวลผลได้โดยระบบปฏิบัติการเท่านั้น โดยทั่วไปคุณสามารถใช้วิธีการเด็ก Kill เพื่อส่งสัญญาณไปยังกระบวนการเด็กและส่งสัญญาณ sigterm โดยค่าเริ่มต้น: การคัดลอกรหัสมีดังนี้: var spawn = ต้องการ ('child_process'). วางไข่; var child = วางไข่ ('sleep', ['10']); settimeout (function () { เด็ก kill (); }, 1,000); นอกจากนี้คุณยังสามารถส่งสัญญาณเฉพาะโดยผ่านสตริงที่ระบุสัญญาณเป็นพารามิเตอร์เดียวของวิธีการฆ่า: การคัดลอกรหัสมีดังนี้: child.kill ('sigusr2'); ควรสังเกตว่าถึงแม้ว่าชื่อของวิธีนี้จะถูกฆ่า แต่สัญญาณที่ส่งไม่จำเป็นต้องฆ่ากระบวนการเด็ก หากเด็กประมวลผลสัญญาณพฤติกรรมสัญญาณเริ่มต้นถูกเขียนทับ subprocesses ที่เขียนในโหนดสามารถเขียนคำจำกัดความของตัวประมวลผลสัญญาณดังต่อไปนี้: การคัดลอกรหัสมีดังนี้: process.on ('sigusr2', function () { console.log ('มีสัญญาณ sigusr2'); - ตอนนี้คุณได้กำหนดตัวประมวลผลสัญญาณ SIGUSR2 เมื่อกระบวนการของคุณได้รับสัญญาณ SIGUSR2 อีกครั้งมันจะไม่ถูกฆ่า แต่แทนที่จะส่งออกประโยค "ได้รับสัญญาณ SIGUSR2" การใช้กลไกนี้คุณสามารถออกแบบวิธีง่ายๆในการสื่อสารกับกระบวนการเด็กหรือแม้แต่สั่ง แม้ว่ามันจะไม่อุดมไปด้วยการใช้อินพุตมาตรฐาน แต่วิธีนี้ง่ายกว่ามาก สรุป ในบทนี้เราเรียนรู้ที่จะใช้วิธี child_process.exec เพื่อดำเนินการคำสั่งภายนอก ด้วยวิธีนี้เราสามารถส่งผ่านพารามิเตอร์ไปยังกระบวนการเด็กแทนการใช้พารามิเตอร์บรรทัดคำสั่ง แต่แทนที่จะกำหนดตัวแปรสภาพแวดล้อม ฉันยังได้เรียนรู้วิธีการสร้างกระบวนการเด็กโดยเรียกใช้วิธี child_process.spawn เพื่อเรียกคำสั่งภายนอก ด้วยวิธีนี้คุณสามารถใช้สตรีมอินพุตและสตรีมเอาต์พุตเพื่อสื่อสารกับกระบวนการเด็กหรือใช้สัญญาณเพื่อสื่อสารกับกระบวนการเด็กและฆ่ากระบวนการ