Nod direka bentuk untuk mengendalikan operasi I/O dengan cekap, tetapi anda harus sedar bahawa beberapa jenis atur cara tidak sesuai untuk model ini. Sebagai contoh, jika anda bercadang untuk menggunakan Node untuk mengendalikan tugas intensif CPU, anda boleh menyumbat gelung acara dan oleh itu mengurangkan responsif program. Alternatifnya adalah untuk memuatkan tugas intensif CPU ke proses yang berasingan, dengan itu membebaskan gelung acara. Node membolehkan anda melahirkan proses dan menjadikan proses baharu sebagai anak kepada induknya. Dalam Node, proses anak boleh berkomunikasi dengan proses induk secara dua hala, dan pada tahap tertentu, proses induk juga boleh memantau dan mengurus proses anak.
Situasi lain di mana anda perlu menggunakan subproses ialah apabila anda hanya mahu melaksanakan arahan luaran dan biarkan Node mendapat nilai pulangan arahan itu. Sebagai contoh, anda boleh melaksanakan perintah UNIX, skrip atau arahan lain yang tidak boleh dilaksanakan secara langsung dalam Node.
Bab ini akan menunjukkan kepada anda cara melaksanakan perintah luaran, mencipta dan berkomunikasi dengan proses anak dan menamatkan proses anak. Intinya adalah untuk membolehkan anda memahami cara menyelesaikan satu siri tugasan di luar proses Node.
Laksanakan arahan luaran
Apabila anda perlu melaksanakan perintah shell luaran atau fail boleh laku, anda boleh menggunakan modul child_process dan mengimportnya seperti ini:
exec(arahan,panggil balik);
// Nota penterjemah: Jika anda menggunakan windows, anda boleh menukar kepada perintah windows, seperti dir, yang tidak akan diterangkan lagi
});
Jika ralat berlaku, parameter pertama akan menjadi contoh kelas Ralat Jika parameter pertama tidak mengandungi ralat, maka parameter kedua stdout akan mengandungi output standard arahan. Parameter terakhir mengandungi output ralat yang berkaitan dengan arahan.
Penyenaraian 8-1 menunjukkan contoh yang lebih kompleks untuk melaksanakan perintah luaran
PENYENARAIAN 8-1: Laksanakan arahan luaran (kod sumber: chapter8/01_external_command.js)
Pada baris keempat, kami lulus "cat *.js | wc -l" sebagai parameter pertama untuk melaksanakan Anda juga boleh mencuba mana-mana arahan lain, selagi anda telah menggunakan arahan dalam shell.
Kemudian lulus fungsi panggil balik sebagai parameter kedua, yang akan dipanggil apabila ralat berlaku atau proses anak ditamatkan.
Anda juga boleh menghantar parameter pilihan ketiga sebelum fungsi panggil balik, yang mengandungi beberapa pilihan konfigurasi, seperti:
Tamat masa: 1000,
killSignal: ‘SIGKILL’
};
//…
});
1.cwd - Direktori semasa, anda boleh menentukan direktori kerja semasa.
2.pengekodan - format pengekodan kandungan output proses anak Nilai lalai ialah "utf8", iaitu pengekodan UTF-8. Jika output proses anak bukan utf8, anda boleh menggunakan parameter ini untuk menetapkannya Format pengekodan yang disokong ialah:
Gunakan Penampan untuk memproses, mengekod dan menyahkod data binari".
1.masa tamat - tamat masa pelaksanaan perintah dalam milisaat, lalai ialah 0, yang bermaksud tiada had, sehingga proses anak tamat.
2.maxBuffer - Tentukan bilangan maksimum bait yang dibenarkan untuk dikeluarkan oleh aliran stdout dan aliran stderr Jika nilai maksimum dicapai, proses anak akan dimatikan. Nilai lalai ialah 200*1024.
3.killSignal - Isyarat penamatan dihantar kepada proses anak apabila tamat masa atau penimbal output mencapai saiz maksimumnya. Nilai lalai ialah "SIGTERM", yang akan menghantar isyarat penamatan kepada proses anak. Pendekatan teratur ini biasanya digunakan untuk menamatkan proses. Apabila menggunakan isyarat SIGTERM, proses boleh memprosesnya atau mengatasi kelakuan lalai pemproses isyarat selepas menerimanya. Jika proses sasaran memerlukannya, anda boleh menghantar isyarat lain (seperti SIGUSR1) kepadanya pada masa yang sama. Anda juga boleh memilih untuk menghantar isyarat SIGKILL, yang akan diproses oleh sistem pengendalian dan memaksa proses kanak-kanak ditamatkan serta-merta Dalam kes ini, sebarang operasi pembersihan proses kanak-kanak tidak akan dilakukan.
1.evn - Menentukan pembolehubah persekitaran yang dihantar kepada proses anak Lalai adalah batal, yang bermaksud bahawa proses anak akan mewarisi pembolehubah persekitaran semua proses induk sebelum ia dibuat.
Nota: Menggunakan pilihan killSignal, anda boleh menghantar isyarat kepada proses sasaran dalam bentuk rentetan. Isyarat wujud dalam bentuk rentetan dalam Node Berikut ialah senarai isyarat UNIX dan operasi lalai yang sepadan:
Anda mungkin mahu menyediakan proses anak dengan set pembolehubah persekitaran induk yang boleh dikembangkan. Jika anda mengubah suai objek process.env secara langsung, anda akan menukar pembolehubah persekitaran semua modul dalam proses Node, yang akan menyebabkan banyak masalah. Alternatifnya ialah mencipta objek baharu dan menyalin semua parameter dalam process.env, lihat Contoh 8-2:
PENYENARAIAN 8-2: Gunakan pembolehubah persekitaran berparameter untuk melaksanakan arahan (kod sumber: chapter8/02_env_vars_augment.js)
envCopy['CUSTOM ENV VAR1'] = 'sesetengah nilai';
envCopy['CUSTOM ENV VAR2'] = 'beberapa nilai lain';
exec(‘ls –la’,{env: envCopy}, function(err,stdout,stderr){
If(err){ throw err;
console.log(‘stdout:’, stdout);
console.log(‘stderr:’,stderr);
}
Contoh di atas mencipta pembolehubah envCopy untuk menyimpan pembolehubah persekitaran Ia mula-mula menyalin pembolehubah persekitaran proses Node daripada process.env, kemudian menambah atau menggantikan beberapa pembolehubah persekitaran yang perlu diubah suai, dan akhirnya menggunakan envCopy sebagai persekitaran. . Argumen pembolehubah dihantar ke fungsi exec dan arahan luaran dilaksanakan.
Ingat bahawa pembolehubah persekitaran dihantar antara proses melalui sistem pengendalian, dan semua jenis nilai pembolehubah persekitaranmencapai proses anak dalam bentuk rentetan. Sebagai contoh, jika proses induk mengandungi nombor 123 sebagai pembolehubah persekitaran, proses anak akan menerima "123" sebagai rentetan.
Contoh berikut akan membuat dua skrip Node dalam direktori yang sama: parent.js dan child.js. Skrip pertama akan memanggil yang kedua Mari buat dua fail ini:
PENYENARAIAN 8-3: Proses induk menetapkan pembolehubah persekitaran (bab8/03_environment_number_parent.js)
exec('node child.js', {env: {nombor: 123}}, function(err, stdout, stderr) {
jika (err) { membuang err;
console.log('stdout:n', stdout);console.log('stderr:n', stderr);
});
Contoh 8-4: Pembolehubah persekitaran penghuraian proses anak (bab8/04_environment_number_child.js)
nombor = parseInt(nombor, 10);
console.log(typeof(nombor)); // → "nombor"
nombor
stderr:
Jana proses anak
Seperti yang anda lihat, anda boleh menggunakan fungsi child_process.exec() untuk memulakan proses luaran dan memanggil fungsi panggil balik anda apabila proses tamat Ini sangat mudah untuk digunakan, tetapi ia juga mempunyai beberapa kelemahan:1 Selain menggunakan parameter baris arahan dan pembolehubah persekitaran, exec() tidak boleh berkomunikasi dengan proses anak
2. Output proses anak dicache, jadi anda tidak boleh menstrimnya, ia mungkin kehabisan memori
Buat proses anak
Anda boleh menggunakan fungsi child_process.spawn untuk mencipta proses anak baharu, lihat Contoh 8-5:Contoh 8-5: Melahirkan proses anak. (bab 8/05_spawning_child.js)
// Hasilkan proses anak untuk melaksanakan perintah "tail -f /var/log/system.log"
var child = spawn('tail', ['-f', '/var/log/system.log']);
Kod di atas menjana subproses untuk melaksanakan perintah ekor dan mengambil "-f" dan "/bar/log/system.log" sebagai parameter. Perintah tail akan memantau fail /var/log/system.og (jika wujud) dan mengeluarkan sebarang data baharu yang ditambahkan ke strim output standard stdout. Fungsi spawn mengembalikan objek ChildProcess, yang merupakan objek penunjuk yang merangkum antara muka akses proses sebenar. Dalam contoh ini kami menetapkan deskriptor baharu ini kepada pembolehubah yang dipanggil anak.
Dengar data daripada proses kanak-kanak
Mana-mana pemegang proses anak yang mengandungi atribut stdout akan menggunakan stdout keluaran standard proses anak sebagai objek strim Anda boleh mengikat peristiwa data pada objek strim ini, supaya apabila blok data tersedia, panggilan balik yang sepadan fungsi, lihat contoh di bawah:
child.stdout.on(‘data’,function(data){
console.log(‘output ekor: ‘ data);
});
Setiap kali proses anak mengeluarkan data ke stdout, proses induk akan dimaklumkan dan mencetak data ke konsol.
Selain output standard, proses ini mempunyai satu lagi strim output lalai: strim ralat standard Strim ini biasanya digunakan untuk mengeluarkan maklumat ralat.
Dalam contoh ini, jika fail /var/log/system.log tidak wujud, proses ekor akan mengeluarkan mesej yang serupa dengan yang berikut: "/var/log/system.log: Tiada fail atau direktori sedemikian" , dengan memantau aliran stderr, proses induk akan dimaklumkan apabila ralat sedemikian berlaku.
Proses induk boleh mendengar aliran ralat standard seperti ini:
console.log('output ralat ekor:', data);
});
Atribut stderr, seperti stdout, juga merupakan strim baca sahaja Setiap kali anak memproses data kepada strim ralat standard, proses induk akan dimaklumkan dan mengeluarkan data.
Hantar data ke proses anak
Selain menerima data daripada aliran output proses anak, proses induk juga boleh menulis data ke input standard proses anak melalui sifat childPoces.stdin, dengan itu menghantar data ke dan dari proses anak.
Proses anak boleh memantau data input standard melalui strim baca sahaja process.stdin, tetapi ambil perhatian bahawa anda mesti menyambung semula strim input standard terlebih dahulu kerana ia berada dalam keadaan dijeda secara lalai.
Contoh 8-6 akan mencipta program yang mengandungi fungsi berikut:
1. 1 Aplikasi: Aplikasi mudah yang boleh menerima integer daripada input standard, menambahnya, dan kemudian mengeluarkan hasil tambah kepada aliran output standard. Sebagai perkhidmatan pengkomputeran yang mudah, aplikasi ini mensimulasikan proses Node sebagai perkhidmatan luaran yang boleh melaksanakan kerja tertentu.
2. Uji klien 1 aplikasi, hantar integer rawak, dan kemudian keluarkan hasilnya. Digunakan untuk menunjukkan cara proses Node melahirkan proses anak dan kemudian membenarkannya melaksanakan tugas tertentu.
Buat fail bernama plus_one.js menggunakan kod dalam Contoh 8-6 di bawah:
Contoh 8-6: 1 permohonan (bab8/06_plus_one.js)
Dalam kod di atas, kami menunggu data daripada aliran input standard stdin Apabila data tersedia, kami menganggap ia adalah integer dan menghuraikannya ke dalam pembolehubah integer, kemudian tambah 1 dan keluarkan hasilnya kepada aliran output standard. .
Anda boleh menjalankan program ini dengan arahan berikut:
Selepas berjalan, program mula menunggu input Jika anda memasukkan integer dan tekan Enter, anda akan melihat nombor ditambah dengan 1 dipaparkan pada skrin.
Anda boleh keluar dari program dengan menekan Ctrl-C.
Pelanggan ujian
Kini anda perlu mencipta proses Node untuk menggunakan perkhidmatan pengkomputeran yang disediakan oleh "1 aplikasi" sebelumnya.
Mula-mula buat fail bernama plus_one_test.js Kandungan ditunjukkan dalam Contoh 8-7:
Contoh 8-7: Aplikasi Ujian 1 (bab8/07_plus_one_test.js)
Subproses yang digunakan untuk menjalankan "1 aplikasi" dimulakan dari baris pertama hingga keempat, dan kemudian fungsi setInterval digunakan untuk melaksanakan operasi berikut sekali setiap saat:
1.. Buat nombor rawak baharu kurang daripada 10000
2. Hantar nombor ini sebagai rentetan kepada proses anak
3. Tunggu proses anak membalas dengan rentetan
4. Kerana anda hanya ingin menerima hasil pengiraan 1 nombor pada satu masa, anda perlu menggunakan child.stdout.sekali dan bukannya child.stdout.on. Jika yang terakhir digunakan, fungsi panggil balik untuk peristiwa data akan didaftarkan setiap 1 saat Setiap fungsi panggil balik yang didaftarkan akan dilaksanakan apabila stdout proses anak menerima data, jadi anda akan mendapati bahawa hasil pengiraan yang sama akan dikeluarkan. Banyak kali, tingkah laku ini jelas salah.
Terima pemberitahuan apabila proses anak keluar
Apabila proses anak keluar, acara keluar akan dicetuskan. Contoh 8-8 menunjukkan cara mendengarnya:
Contoh 8-8: Mendengar peristiwa keluar dari proses anak (bab8/09_listen_child_exit.js)
// Apabila proses anak keluar:
child.on('keluar', fungsi(kod) {
console.log('proses kanak-kanak ditamatkan dengan kod ');
});
Dalam beberapa baris terakhir kod yang dicetak tebal, proses induk menggunakan acara keluar proses anak untuk mendengar acara keluarnya Apabila peristiwa itu berlaku, konsol memaparkan output yang sepadan. Kod keluar proses anak akan dihantar ke fungsi panggil balik sebagai parameter pertama. Sesetengah program menggunakan kod keluar bukan sifar untuk mewakili keadaan kegagalan tertentu. Contohnya, jika anda cuba melaksanakan arahan "ls –al click filename.txt" tetapi fail itu tidak wujud dalam direktori semasa, anda akan mendapat kod keluar 1, lihat Contoh 8-9:
Contoh 8-9: Dapatkan kod keluar proses anak (bab8/10_child_exit_code.js)
Dalam contoh ini, peristiwa keluar mencetuskan fungsi panggil balik dan menghantar kod keluar proses anak kepadanya sebagai parameter pertama. Jika proses anak keluar secara tidak normal kerana dibunuh oleh isyarat, kod isyarat yang sepadan akan dihantar ke fungsi panggil balik sebagai parameter kedua, seperti Contoh 8-10:
PENYENARAIAN 8-10: Dapatkan isyarat keluar proses anak (bab8/11_child_exit_signal.js)
Dalam contoh ini, proses kanak-kanak dimulakan untuk melakukan operasi tidur selama 10 saat, tetapi isyarat SIGKILL dihantar kepada proses kanak-kanak sebelum 10 saat, yang akan menghasilkan output berikut:
Hantar isyarat dan proses bunuh
Dalam bahagian ini, anda akan belajar cara menggunakan isyarat untuk mengurus proses kanak-kanak. Isyarat ialah cara mudah untuk proses ibu bapa berkomunikasi dengan, atau bahkan membunuh, proses anak.
Kod isyarat yang berbeza mewakili makna yang berbeza Terdapat banyak isyarat, beberapa yang paling biasa digunakan untuk mematikan proses. Jika proses menerima isyarat bahawa ia tidak tahu bagaimana untuk mengendalikan, program akan terganggu secara tidak normal. Sesetengah isyarat akan dikendalikan oleh proses kanak-kanak, manakala yang lain hanya boleh dikendalikan oleh sistem pengendalian.
Secara amnya, anda boleh menggunakan kaedah child.kill untuk menghantar isyarat kepada proses anak Isyarat SIGTERM dihantar secara lalai:
Anda juga boleh menghantar isyarat tertentu dengan menghantar rentetan yang mengenal pasti isyarat sebagai satu-satunya parameter kaedah bunuh:
Perlu diingat bahawa walaupun nama kaedah ini adalah membunuh, isyarat yang dihantar tidak semestinya membunuh proses kanak-kanak. Jika proses kanak-kanak mengendalikan isyarat, tingkah laku isyarat lalai akan ditolak. Subproses yang ditulis dalam Node boleh menulis semula definisi pengendali isyarat seperti berikut:
Sekarang anda telah menentukan pengendali isyarat SIGUSR2, apabila proses anda menerima isyarat SIGUSR2 sekali lagi, ia tidak akan dimatikan, tetapi akan mengeluarkan ayat "Mendapat isyarat SIGUSR2". Menggunakan mekanisme ini, anda boleh mereka bentuk cara mudah untuk berkomunikasi dengan proses kanak-kanak dan juga mengarahkannya. Walaupun tidak sekaya menggunakan input standard, kaedah ini lebih mudah.
Ringkasan
Dalam bab ini, kami belajar menggunakan kaedah child_process.exec untuk melaksanakan perintah luaran Kaedah ini tidak menggunakan parameter baris arahan, tetapi menghantar parameter kepada proses anak dengan mentakrifkan pembolehubah persekitaran.
Anda juga mempelajari cara memanggil perintah luaran dengan memanggil kaedah child_process.spawn untuk melahirkan proses anak Dengan cara ini, anda boleh menggunakan aliran input dan aliran output untuk berkomunikasi dengan proses anak, atau menggunakan isyarat untuk berkomunikasi dengan dan. membunuh proses kanak-kanak.