Differenza tra ChildProcess vicino, eventi di uscita

Quando la deposizione delle uova i processi secondari di via spawn()/exec()/... in Node.js c’è un 'close' e un 'exit' evento processi figli.

Qual è la differenza tra questi due e quando è necessario usare cosa?

InformationsquelleAutor Narigo | 2016-05-30

 

3 Replies
  1. 26

    Prima Node.js 0.7.7, c’era solo un “exit”, evento di processi figli (e non “chiudere” l’evento). Questo evento potrebbe essere generato quando il processo figlio è stato chiuso, e tutti i flussi (stdin, stdout stdout) sono stati chiusi.

    Nel Nodo 0.7.7 , “il vicino” evento è stato introdotto (vedere il commit).
    Il documentazione (permalink) attualmente dice:

    ‘Chiudi’ evento viene emesso quando il stdio flussi di di un processo figlio sono stati chiusi. Questo è distinto dal ‘uscita’ evento, dal più processi possono condividere lo stesso stdio flussi.

    Se è solo la generazione di un programma e non fare nulla di speciale con stdio, “il vicino” evento viene generato dopo “l’uscita”.
    Il “vicino”, un evento può essere ritardata se, per esempio, il flusso stdout viene reindirizzato a un altro flusso. In modo che significa che il “vicino”, un evento può essere ritardata (a tempo indeterminato) dopo l ‘ “uscita” evento.

    Questo significa che il “vicino” evento è sempre licenziato dopo “uscita”? Come dimostrano gli esempi seguenti mostrano, la risposta è no.

    Quindi, se siete interessati solo alla terminazione del processo (ad esempio, perché il processo contiene un esclusivo delle risorse), l’ascolto di “uscita” non è sufficiente.
    Se non ti interessa il programma, e solo circa il suo ingresso e/o uscita, utilizzare il “vicino” evento.

    Esperimento: distruggere stdio prima di uccidere il bambino

    Sperimentalmente (in Node.js v7.2.0), ho scoperto che se la stdio flussi non sono utilizzati dal processo figlio, che poi “chiudi” evento viene generato solo dopo che il programma è terminato:

    //The "sleep" command takes no input and gives no output.
    cp = require('child_process').spawn('sleep', ['100']);
    cp.on('exit', console.log.bind(console, 'exited'));
    cp.on('close', console.log.bind(console, 'closed'));
    cp.stdin.end();
    cp.stdout.destroy();
    cp.stderr.destroy();
    console.log('Closed all stdio');
    setTimeout(function() { 
        console.log('Going to kill');
        cp.kill();
    }, 500);

    Il suddetto programma la deposizione delle uova “sonno” uscite:

    Closed all stdio
    Going to kill
    exited null SIGTERM
    closed null SIGTERM

    Quando cambio le prime linee di un programma che ha solo un’uscita,

    //The "yes" command continuously outputs lines with "y"
    cp = require('child_process').spawn('yes');

    … quindi il risultato è:

    Closed all stdio
    exited 1 null
    closed 1 null
    Going to kill

    Allo stesso modo quando cambio la generazione di un programma che legge da stdin,

    //Keeps reading from stdin.
    cp = require('child_process').spawn('node', ['-e', 'process.stdin.resume()']);

    O quando ho letto dallo standard input e output su stdout,

    //"cat" without arguments reads from stdin, and outputs to stdout
    cp = require('child_process').spawn('cat');

    Esperimento: Tubo di programma e l’altro, uccidere primo programma

    Precedente esperimento è piuttosto artificiale. Il prossimo esperimento è un po ‘ più realistico: Si tubo di un programma e l’altro e uccidere il primo.

    //Reads from stdin, output the input to stdout, repeat.
    cp = require('child_process').spawn('bash', ['-c', 'while read x ; do echo "$x" ; done']);
    cp.on('exit', console.log.bind(console, 'exited'));
    cp.on('close', console.log.bind(console, 'closed'));
    
    cpNext = require('child_process').spawn('cat');
    cp.stdout.pipe(cpNext.stdin);
    
    setTimeout(function() {
        //Let's assume that it has started. Now kill it.
        cp.kill();
        console.log('Called kill()');
    }, 500);

    Di uscita:

    Called kill()
    exited null SIGTERM
    closed null SIGTERM

    Allo stesso modo, quando il primo programma che legge da input e mai uscite:

    //Keeps reading from stdin, never outputs.
    cp = require('child_process').spawn('bash', ['-c', 'while read ; do : ; done']);

    Quando il primo programma mantiene l’output senza aspettare stdin, il comportamento è diverso anche se, come il prossimo esperimento mostra.

    Esperimento: Tubo di programma con un sacco di uscita di un altro, uccidere primo programma

    //Equivalent to "yes | cat".
    cp = require('child_process').spawn('yes');
    cp.on('exit', console.log.bind(console, 'exited'));
    cp.on('close', console.log.bind(console, 'closed'));
    
    cpNext = require('child_process').spawn('cat');
    cp.stdout.pipe(cpNext.stdin);
    
    setTimeout(function() {
        //Let's assume that it has started. Now kill it.
        cp.kill();
        console.log('Called kill()');
        setTimeout(function() {
            console.log('Expecting "exit" to have fired, and not "close"');
            //cpNext.kill();
            //^ Triggers 'error' event, errno ECONNRESET.
            //^ and does not fire the 'close' event!
    
            //cp.stdout.unpipe(cpNext.stdin);
            //^ Does not appear to have any effect.
            //^ calling cpNext.kill() throws ECONNRESET.
            //^ and does not fire the 'close' event!
    
            cp.stdout.destroy(); //<-- triggers 'close'
            cpNext.stdin.destroy();
            //^ Without this, cpNext.kill() throws ECONNRESET.
    
            cpNext.kill();
        }, 500);
    }, 500);

    Il programma di cui sopra uscite e poi esce:

    Called kill()
    exited null SIGTERM
    Expecting "exit" to have fired, and not "close"
    closed null SIGTERM
  2. 0

    la versione breve è, ‘exit’ emette quando il bambino esce, ma il stdio sono non ancora chiuso.
    ‘chiudi’ emette quando il bambino è uscito e sua stdios sono chiusi.

    Oltre che condividono la stessa firma.

    • questa info non sembra gel con @Gilad risposta
  3. 0

    Ti guardi la documentazione?

    Secondo questo:

    ‘Chiudi’ evento viene emesso quando il stdio flussi di di un processo figlio sono stati chiusi. Questo è distinto dal ‘uscita’ evento, dal più processi possono condividere lo stesso stdio flussi.

    La ‘exit’ evento è emessa dopo il processo figlio termina. Se il processo terminato, il codice è il finale di un codice di uscita del processo, altrimenti null. Se il processo è terminato a causa della ricezione di un segnale, il segnale è il nome della stringa di segnale, altrimenti null. Uno dei due sarà sempre non nullo.

    • Ti sei perso la parte più importante Note that when the 'exit' event is triggered, child process stdio streams might still be open.
    • Il problema è che non ho ben capito che cosa questo significa. Si ‘exit’ E ‘chiudere’ essere chiamato? Come può un processo che si è concluso, in qualche modo, ancora di ricevere / inviare IO? Se ‘uscita’ è chiamato prima di “chiudere”, come entrambi hanno l’uscita codice?

Lascia un commento