2012-02-08 10 views
9

Tengo un script node.js que hace un poco de registro en un archivo usando WriteStream. En ciertos eventos, quiero detener la ejecución del script, es decir, advertir que inicie sesión y salga inmediatamente después de eso. Siendo Node.js asyncronious no permite que hagamos de ella hacia adelante como:¿Cuál es la forma correcta de salir del script node.js con un mensaje de registro?

#!/usr/local/bin/node 

var fs = require('fs'); 
var stream = fs.createWriteStream('delme.log', { flags: 'a' }); 

stream.write('Something bad happened\n'); 
process.exit(1); 

En lugar de añadir un mensaje a delme.log este script no hace nada con el archivo. El manejo del evento de 'salida' y el enjuague no funciona. La única manera de escribir el último mensaje de registro antes de exitting encontrado hasta ahora es envolver en el process.exit(1)setTimeout():

#!/usr/local/bin/node 

var fs = require('fs'); 
var stream = fs.createWriteStream('delme.log', { flags: 'a' }); 

stream.write('Something bad happened\n'); 
setTimeout(function(){ 
    process.exit(1); 
}, 30); 

Sin embargo, en esta forma no se detiene la ejecución del script de inmediato y el script se ejecuta por alguna tiempo después de que sucedió el evento crítico. Entonces, me pregunto si hay otras formas de salir de un script con un mensaje de registro.

Respuesta

11

Dado que desea bloquear y ya está utilizando una secuencia, es probable que desee manejar la escritura usted mismo.

var data = new Buffer('Something bad happened\n'); 
fs.writeSync(stream.fd, data, 0, data.length, stream.pos); 
process.exit(); 
+0

Gracias! Esa es una variación de la llamada a setTimeout(), que no bloquea la ejecución del script. Si hay un código que no debería ejecutarse después de la excepción, este patrón podría convertirse en una preocupación. – nab

+0

Actualizado mi respuesta. – fent

+1

En mi caso particular, uso WriteStream para el registro, por lo que la llamada real sería log.error ('Algo malo pasó') que formatea el mensaje con el nivel de registro apropiado y agrega otras cosas. Por lo tanto, sería difícil implementar este fragmento sin cambiar la interfaz del registrador. Estoy publicando mi solución alternativa como una solución alternativa. La pregunta inicial está perfectamente respondida. ¡Gracias! – nab

0

Yo estaría a favor de sólo escribir en stderr en este caso - por ejemplo ejemplo trivial

console.error(util.inspect(exception)); 

y luego dejar que el proceso de supervisión * manejar la persistencia de registro. Desde mi entendimiento hoy en día, no tiene que preocuparse de que stdout y stderr no se vayan a enjuagar antes de que el nodo salga (aunque vi el comportamiento opuesto problemático en algunas de las versiones 0.2.x).

(*) Para supervisar el proceso para elegir supervisord, dios, monit, para siempre, pswatch etc ...

Esto también proporciona un camino limpio para usar los proveedores de PaaS tales como Heroku y dotCloud etc ... dejar que la infraestructura de gestión de la tala

+1

Preferiría resolverlo (de alguna manera) programmicamente. Tengo un número de secuencias cortas de diferentes tipos.Algunos de ellos solo advierten a STDERR, algunos datos de registro al sistema de archivos. Lo que necesito es un enfoque unificado para salir de un script con un mensaje de registro sin depender de un software externo. De todos modos, gracias por la pista :) – nab

+0

NO está enrojecido. – zupa

0

Creo que este es el camino correcto:

process.on('exit', function(){ 
    // You need to use a synchronous, blocking function, here. 
    // Not streams or even console.log, which are non-blocking. 
    console.error('Something bad happened\n'); 
}); 
3

vaciar todos los mensajes de registro en un archivo antes exitting uno podría querer envolver una ejecución del script en un bloque try-catch. Una vez que ha ocurrido algo malo, que está siendo registrada y se produce una excepción que será atrapado por el exterior try de la que es seguro para salir de forma asíncrona:

#!/usr/local/bin/node 

var fs = require('fs'); 
var stream = fs.createWriteStream('delme.log', { flags: 'a' }); 
var SOMETHING_BAD = 'Die now'; 

try { 
    // Any code goes here... 
    if (somethingIsBad) { 
    stream.write('Something bad happened\n'); 
    throw new Error(SOMETHING_BAD); 
    } 
} catch (e) { 
    if (e.message === SOMETHING_BAD) { 
    stream.on('drain', function() { 
     process.exit(1); 
    }); 
    } else { 
    throw e; 
    } 
} 
3

mejorada.

var fs = require('fs'); 
var stream = fs.createWriteStream('delme.log', {flags: 'a'}); 

// Gracefully close log 
process.on('uncaughtException', function() { 
    stream.write('\n'); // Make sure drain event will fire (queue may be empty!) 
    stream.on('drain', function() { 
     process.exit(1); 
    }); 
}); 

// Any code goes here... 
stream.write('Something bad happened\n'); 
throw new Error(SOMETHING_BAD); 

El bloque try-catch obras pero es feo. Aún así, los créditos van a @nab, simplemente lo embellecí.

Cuestiones relacionadas