So erstellen Sie einen untergeordneten Prozess in nodejs

So erstellen Sie einen untergeordneten Prozess in nodejs

Einführung

Die Hauptereignisschleife von nodejs ist einfädig. Nodejs selbst unterhält auch einen Worker-Pool, um einige zeitaufwändige Vorgänge abzuwickeln. Wir können auch manuell neue Threads erstellen, um unsere eigenen Aufgaben auszuführen, indem wir die von nodejs bereitgestellten worker_threads verwenden.

Dieser Artikel stellt eine neue Möglichkeit zur Ausführung von Node.JS-Aufgaben und untergeordneten Prozessen vor.

Untergeordneter Prozess

lib/child_process.js stellt das Modul child_process bereit, mit dem wir untergeordnete Prozesse erstellen können.

Beachten Sie, dass worker_threads untergeordnete Threads erstellt, während child_process untergeordnete Prozesse erstellt.

Im Modul child_process können Prozesse synchron oder asynchron erstellt werden. Die synchrone Erstellungsmethode besteht lediglich darin, Sync nach der asynchronen Erstellungsmethode hinzuzufügen.

Der erstellte Prozess wird durch die Klasse ChildProcess dargestellt.

Schauen wir uns die Definition von ChildProcess an:

Schnittstelle ChildProcess erweitert events.EventEmitter {
 stdin: Beschreibbar | null;
 stdout: Lesbar | null;
 stderr: Lesbar | null;
 schreibgeschützter Kanal?: Pipe | null;
 schreibgeschütztes stdio: [
  Schreibbar | null, // stdin
  Lesbar | null, // stdout
  Lesbar | null, // stderr
  Lesbar | Schreibbar | null | undefiniert, // extra
  Lesbar | Schreibbar | null | undefiniert // extra
 ];
 schreibgeschützt beendet: Boolesch;
 schreibgeschützte PID: Nummer;
 schreibgeschützt verbunden: Boolesch;
 schreibgeschützter ExitCode: Zahl | null;
 schreibgeschützter Signalcode: NodeJS.Signals | null;
 schreibgeschützte Spawnargs: Zeichenfolge[];
 schreibgeschützte Spawndatei: Zeichenfolge;
 kill(Signal?: NodeJS.Signals | Zahl): Boolesch;
 senden (Nachricht: Serialisierbar, Rückruf?: (Fehler: Fehler | null) => void): Boolesch;
 senden (Nachricht: Serialisierbar, Sendehandle?: Sendehandle, Rückruf?: (Fehler: Fehler | null) => ungültig): Boolesch;
 senden (Nachricht: Serialisierbar, Sende-Handle?: Sende-Handle, Optionen?: Nachrichtenoptionen, Rückruf?: (Fehler: Fehler | null) => ungültig): Boolesch;
 trennen(): void;
 unref(): ungültig;
 ref(): ungültig;

 /**
  * Ereignisse.EventEmitter
  * 1. schließen
  * 2. trennen
  * 3. Fehler
  * 4. Ausgang
  * 5. Nachricht
  */
 ...
 }

Sie können sehen, dass ChildProcess auch ein EventEmitter ist und daher Ereignisse senden und empfangen kann.

ChildProcess kann fünf Ereignistypen empfangen: Schließen, Trennen, Fehler, Beenden und Nachricht.

Das Trennungsereignis wird ausgelöst, wenn im übergeordneten Prozess subprocess.disconnect() oder im untergeordneten Prozess process.disconnect() aufgerufen wird.

Das Fehlerereignis wird ausgelöst, wenn ein Prozess nicht erstellt oder beendet werden kann oder an einen untergeordneten Prozess keine Nachricht gesendet werden kann.

Wenn der Kindprozess endet, wird das Exit-Ereignis ausgelöst.

Das Schließereignis wird ausgelöst, wenn die Standarddio-Streams des untergeordneten Prozesses geschlossen werden. Beachten Sie, dass sich das Schließereignis vom Beendigungsereignis unterscheidet, da mehrere Prozesse möglicherweise dasselbe Standarddio gemeinsam nutzen, sodass das Senden eines Beendigungsereignisses nicht unbedingt ein Schließereignis auslöst.

Schauen wir uns ein Beispiel für Schließen und Beenden an:

const { spawn } = erfordern('Kindprozess');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('Daten', (Daten) => {
 Konsole.log(`stdout: ${data}`);
});

ls.on('schließen', (Code) => {
 console.log(`Der untergeordnete Prozess verwendet den Code $[code], um alle Standarddio zu schließen`);
});

ls.on('exit', (Code) => {
 console.log(`Der untergeordnete Prozess wurde mit dem Code $[code] beendet`);
});

Schließlich gibt es das Nachrichtenereignis, das ausgelöst wird, wenn der untergeordnete Prozess mit process.send() eine Nachricht sendet.

Es gibt mehrere Standard-Stream-Attribute in ChildProcess, nämlich stderr, stdout, stdin und stdio.

stderr, stdout und stdin sind leicht zu verstehen, sie stehen jeweils für Standardfehler, Standardausgabe und Standardeingabe.

Schauen wir uns die Verwendung von stdout an:

const { spawn } = erfordern('Kindprozess');

const subprocess = spawn('ls');

subprocess.stdout.on('Daten', (Daten) => {
 console.log(`Empfangener Datenblock ${data}`);
});

stdio ist eigentlich eine Sammlung von stderr, stdout und stdin:

schreibgeschütztes stdio: [
  Schreibbar | null, // stdin
  Lesbar | null, // stdout
  Lesbar | null, // stderr
  Lesbar | Schreibbar | null | undefiniert, // extra
  Lesbar | Schreibbar | null | undefiniert // extra
 ];

Davon steht stdio[0] für stdin, stdio[1] für stdout und stdio[2] für stderr.

Wenn die drei Standard-Streams beim Erstellen des untergeordneten Prozesses mit stdio auf etwas anderes als Pipe eingestellt sind, sind stdin, stdout und stderr null.

Sehen wir uns ein Beispiel mit stdio an:

const assert = erfordern('assert');
const fs = erfordern('fs');
const untergeordneter Prozess = erforderlich('untergeordneter Prozess');

const Unterprozess = Kindprozess.spawn('ls', {
 stdio:
 0, // Standardeingabe des übergeordneten Prozesses für untergeordneten Prozess verwenden.
 „Pipe“, // Übergeben Sie die Standardausgabe des untergeordneten Prozesses über die Pipe an den übergeordneten Prozess.
 fs.openSync('err.out', 'w') // Leitet den stderr des untergeordneten Prozesses in eine Datei um.
 ]
});

assert.strictEqual(subprocess.stdio[0], null);
assert.strictEqual(Unterprozess.stdio[0], Unterprozess.stdin);

assert(Unterprozess.stdout);
assert.strictEqual(Unterprozess.stdio[1], Unterprozess.stdout);

assert.strictEqual(subprocess.stdio[2], null);
assert.strictEqual(Unterprozess.stdio[2], Unterprozess.stderr);

Normalerweise verwaltet der übergeordnete Prozess einen Referenzzähler für den untergeordneten Prozess und der übergeordnete Prozess wird erst beendet, wenn der untergeordnete Prozess beendet wird.

Diese Referenz ist „ref“, und wenn die Methode „unref“ aufgerufen wird, ermöglicht sie, den übergeordneten Prozess unabhängig vom untergeordneten Prozess zu beenden.

const { spawn } = erfordern('Kindprozess');

const Unterprozess = spawn(Prozess.argv[0], ['child_program.js'], {
 losgelöst: wahr,
 stdio: "ignorieren"
});

Unterprozess.unref();

Schauen wir uns abschließend an, wie Nachrichten über ChildProcess gesendet werden:

subprocess.send(Nachricht[, sendHandle[, Optionen]][, Rückruf])

Dabei ist „Nachricht“ die zu sendende Nachricht und „Rückruf“ der Rückruf nach dem Senden der Nachricht.

sendHandle ist etwas Besonderes. Es kann ein TCP-Server- oder Socket-Objekt sein und diese Handles an den untergeordneten Prozess übergeben. Der untergeordnete Prozess übergibt den Handle im Nachrichtenereignis an die Rückruffunktion, sodass dieser im untergeordneten Prozess verarbeitet werden kann.

Schauen wir uns ein Beispiel für die Übergabe an einen TCP-Server an. Sehen wir uns zunächst den Hauptprozess an:

const Unterprozess = erfordern ('Unterprozess').fork ('Unterprozess.js');

//Öffne das Serverobjekt und sende den Handle.
const server = require('net').createServer();
server.on('Verbindung', (Socket) => {
 socket.end('Wird vom übergeordneten Prozess verarbeitet');
});
server.listen(1337, () => {
 Unterprozess.senden('Server', Server);
});

Schauen Sie sich den Unterprozess noch einmal an:

process.on('Nachricht', (m, Server) => {
 wenn (m === 'Server') {
 server.on('Verbindung', (Socket) => {
 socket.end('Vom untergeordneten Prozess verarbeitet');
 });
 }
});

Sie können sehen, dass der untergeordnete Prozess den Server-Handle empfängt und auf das Verbindungsereignis im untergeordneten Prozess wartet.

Sehen wir uns ein Beispiel für die Übergabe eines Socket-Objekts an:

onst { fork } = erfordern('untergeordneter_Prozess');
const normal = fork('subprocess.js', ['normal']);
const special = fork('Unterprozess.js', ['special']);

// Starten Sie den Server und senden Sie den Socket an den untergeordneten Prozess.
// Verwenden Sie „pauseOnConnect“, um zu verhindern, dass der Socket gelesen wird, bevor er an den untergeordneten Prozess gesendet wird.
const server = require('net').createServer({ pauseOnConnect: true });
server.on('Verbindung', (Socket) => {

 // Besondere Priorität.
 wenn (socket.remoteAddress === '74.125.127.100') {
 speziell.send('Socket', Socket);
 zurückkehren;
 }
 // Normale Priorität.
 normal.send('socket', socket);
});
server.listen(1337);

Inhalt von subprocess.js:

Prozess.Ein('Nachricht', (m, Socket) => {
 wenn (m === 'Socket') {
 wenn (Buchse) {
 // Überprüfen, ob der Client-Socket vorhanden ist.
 // Der Socket kann zwischen dem Senden und dem Empfangen durch den Kindprozess geschlossen werden.
 socket.end(`Anfrage wird mit der Priorität ${process.argv[2]} verarbeitet`);
 }
 }
});

Der Hauptprozess erstellt zwei Unterprozesse, einen für besondere Priorität und einen für normale Priorität.

Einen Prozess asynchron erstellen

Das Modul child_process bietet vier Möglichkeiten, Prozesse asynchron zu erstellen, nämlich child_process.spawn(), child_process.fork(), child_process.exec() und child_process.execFile().

Schauen wir uns zunächst die Definition der einzelnen Methoden an:

child_process.spawn(Befehl[, Argumente][, Optionen])

child_process.fork(Modulpfad[, Argumente][, Optionen])

child_process.exec(Befehl[, Optionen][, Rückruf])

child_process.execFile(Datei[, Argumente][, Optionen][, Rückruf])

Unter ihnen ist child_process.spawn die Basis, die asynchron einen neuen Prozess generiert. Andere Forks, Execs und ExecFiles werden alle basierend auf Spawn generiert.

Fork generiert einen neuen Node.js-Prozess.

exec und execFile führen neue Befehle in einem neuen Prozess mit Rückruf aus. Der Unterschied zwischen ihnen besteht darin, dass Sie in der Windows-Umgebung eine .bat- oder .cmd-Datei nicht ohne ein Shell-Terminal ausführen können. Derzeit kann es nur mit exec gestartet werden. execFile ist nicht ausführbar.

Alternativ können Sie Spawn verwenden.

Sehen wir uns ein Beispiel für die Verwendung von „spawn“ und „exec“ in Windows an:

// Nur unter Windows.
const { spawn } = erfordern('Kindprozess');
const bat = spawn('cmd.exe', ['/c', 'my.bat']);

bat.stdout.on('Daten', (Daten) => {
 Konsole.log(Daten.toString());
});

bat.stderr.on('Daten', (Daten) => {
 Konsole.Fehler(Daten.toString());
});

bat.on('Beenden', (Code) => {
 console.log(`Unterprozess beendet, Exitcode $[code]`);
});
const { exec, spawn } = erfordern('Kindprozess');
exec('my.bat', (err, stdout, stderr) => {
 wenn (Fehler) {
 Konsole.Fehler(Fehler);
 zurückkehren;
 }
 konsole.log(stdout);
});

// Skript mit Leerzeichen im Dateinamen:
const bat = spawn('"mein Skript.cmd"', ['a', 'b'], { shell: true });
// oder:
exec('"mein Skript.cmd" a b', (err, stdout, stderr) => {
 // ...
});

Synchroner Erstellungsprozess

Um einen Prozess synchron zu erstellen, können Sie child_process.spawnSync(), child_process.execSync() und child_process.execFileSync() verwenden. Die synchrone Methode blockiert die Node.js-Ereignisschleife und unterbricht die Ausführung jeglichen anderen Codes, bis der untergeordnete Prozess beendet wird.

Für manche Skriptaufgaben ist es üblicher, einen synchronen Erstellungsprozess zu verwenden.

Dies ist das Ende dieses Artikels zum Erstellen eines untergeordneten Prozesses in nodejs. Weitere Informationen zum Erstellen eines untergeordneten Prozesses in nodejs finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Nodejs-Fehlerbehandlungsprozessaufzeichnung
  • Detaillierte Erklärung zum schnellen Betrieb einer MySQL-Datenbank in einer Node.js-Umgebung
  • Ein vollständiges Beispiel für die Implementierung eines zeitgesteuerten Crawlers mit Nodejs
  • Unterschiede zwischen diesem Schlüsselwort in NodeJS und Browsern
  • Der Kernprozess der NodeJS-Verarbeitung einer TCP-Verbindung
  • Detaillierte Erklärung der Nodejs-Array-Warteschlange und der forEach-Anwendung
  • Lernen Sie die asynchrone Programmierung in Node.js in einem Artikel
  • So verwenden Sie worker_threads zum Erstellen neuer Threads in nodejs
  • Implementierung des WeChat-Applet-Nachrichten-Pushs in Nodejs
  • Beispielcode zur Implementierung der WeChat-Kontoaufteilung mit Nodejs
  • Detaillierte Erläuterung der Wissenspunkte zur asynchronen Programmierung in nodejs
  • Der einfachste Weg, mit nodejs+express eine Verbindung zur Datenbank herzustellen
  • So führen Sie in Windows ein Downgrade der installierten höheren Node.js-Version auf eine niedrigere Version durch (grafisches Tutorial)
  • Detaillierte Erläuterung des Implementierungsprozesses der NodeJS CORS-Konfiguration
  • So verwenden Sie node.js, um automatisch in regelmäßigen Abständen E-Mail-Erinnerungen zu senden (super praktisch)
  • Einfache Bereitstellung eines Node.Js-Projekts in der Alibaba Cloud
  • So verwenden Sie Node.js zum Implementieren von Befehlszeilenspielen
  • Es ist ganz einfach zu verstehen, was Node.js ist

<<:  Lösung für das Problem mit verstümmelten chinesischen Schriftzeichen in MySQL unter Ubuntu

>>:  Lösung für das Problem, dass Docker Nginx nach dem Ausführen nicht mehr aufgerufen werden kann

Artikel empfehlen

Detaillierte Erläuterung der Angular-Routing-Unterrouten

Inhaltsverzeichnis 1. Subroutensyntax 2. Beispiel...

mysql charset=utf8 verstehen Sie wirklich, was es bedeutet

1. Schauen wir uns zunächst eine Anweisung zur Ta...

Einführung in die neuen Funktionen von ECMAscript

Inhaltsverzeichnis 1. Standardwerte für Funktions...

Detaillierte Erklärung zum Anzeigen der MySQL-Speichernutzung

Vorwort Dieser Artikel stellt hauptsächlich die r...

Ein Artikel zum Verständnis von MySQL Index Pushdown (ICP)

Inhaltsverzeichnis 1. Einleitung 2. Grundsatz Pra...

Diagramm des Prozesses zur Implementierung eines Richtungsproxys durch Nginx

Dieser Artikel stellt hauptsächlich den Prozess d...

So optimieren Sie MySQL-Indizes

1. Wie MySQL Indizes verwendet Indizes werden ver...

Lösung für den Überlauf der HTML-Tabelle

Wenn die Tabelle breit ist, kann es zu einem Über...

Implementierungsbeispiel für den Linux-Befehl „tac“

1. Befehlseinführung Der Befehl tac (umgekehrte R...

So zeigen Sie den Startparameterbefehl „Docker Run“ an (empfohlen)

Verwenden Sie runlike, um die Docker Run-Startpar...

So fügen Sie Wettervorhersagen in Ihre Website ein

Wir hoffen, dass wir durch die Einbindung der Wet...