¿Cuál es el equivalente de Windows de process.on ('SIGINT') en node.js?

84

Estoy siguiendo la guía aquí (escuchando SIGINTeventos) para apagar correctamente mi aplicación node.js alojada en Windows-8 en respuesta a Ctrl+ Co al apagado del servidor.

Pero Windows no lo tiene SIGINT. También lo intenté process.on('exit'), pero parece demasiado tarde para hacer algo productivo.

En Windows, este código me da: Error: No existe tal módulo

process.on( 'SIGINT', function() {
  console.log( "\ngracefully shutting down from  SIGINT (Crtl-C)" )
  // wish this worked on Windows
  process.exit( )
})

En Windows, este código se ejecuta, pero es demasiado tarde para hacer algo elegante :

process.on( 'exit', function() {
  console.log( "never see this log message" )
})

¿Existe un SIGINTevento equivalente en Windows?

Pappadog
fuente
Este problema se me ocurrió al azar hoy y creo que tiene algo que ver con el módulo readline en sí. No pude hacer ninguna prueba, pero desde que agregué este módulo comencé a tener el problema.
Sv443

Respuestas:

148

Tienes que usar el módulo readline y escuchar un evento SIGINT:

http://nodejs.org/api/readline.html#readline_event_sigint

if (process.platform === "win32") {
  var rl = require("readline").createInterface({
    input: process.stdin,
    output: process.stdout
  });

  rl.on("SIGINT", function () {
    process.emit("SIGINT");
  });
}

process.on("SIGINT", function () {
  //graceful shutdown
  process.exit();
});
Gabriel Llamas
fuente
excelente actualización, gracias! establecer esto como la respuesta como la respuesta anterior (escuchar la pulsación de tecla) ya no funciona.
pappadog
44
Esto es ridículo. ¿Por qué esto no lo maneja el núcleo del nodo?
Balupton,
3
Porque cuando escuchas stdin, el proceso nunca termina hasta que envías una señal SIGINT explícitamente.
Gabriel Llamas
2
Por lo tanto, debe enviar un mensaje aleatorio del padre al hijo, por ejemplo: "SIGINT".
Gabriel Llamas
8
Parece que esto se resolvió hace bastante tiempo: github.com/nodejs/node-v0.x-archive/issues/5054
SimonSimCity
23

No estoy seguro de cuándo, pero en el nodo 8.xy en Windows 10, el código de pregunta original simplemente funciona ahora.

process.on( "SIGINT", function() {
  console.log( "\ngracefully shutting down from SIGINT (Crtl-C)" );
  process.exit();
} );

process.on( "exit", function() {
  console.log( "never see this log message" );
} );

setInterval( () => console.log( "tick" ), 2500 );

ingrese la descripción de la imagen aquí

también funciona con un símbolo del sistema de Windows.

Meirion Hughes
fuente
Me di cuenta de esto también. Windows 7 es un problema importante para mí aquí
Gregory Nowakowski
Este método me funciona con Node 8.11.1 en Windows 7, pero lo estaba ejecutando desde un shell de git bash. Pensé que primero probaría la forma simple y funcionó.
user944849
7

A menos que necesite la importación "readline" para otras tareas, sugeriría importar "readline" una vez que el programa haya verificado que se está ejecutando en Windows. Además, para aquellos que no lo sepan, esto funciona tanto en sistemas Windows de 32 bits como en Windows de 64 bits (que devolverán la palabra clave "win32"). Gracias por esta solución Gabriel.

if (process.platform === "win32") {
  require("readline")
    .createInterface({
      input: process.stdin,
      output: process.stdout
    })
    .on("SIGINT", function () {
      process.emit("SIGINT");
    });
}

process.on("SIGINT", function () {
  // graceful shutdown
  process.exit();
});
tfmontague
fuente
5

Hoy en día solo funciona en todas las plataformas , incluido Windows.

El siguiente código se registra y luego termina correctamente en Windows 10:

process.on('SIGINT', () => {
    console.log("Terminating...");
    process.exit(0);
});
Heinrich Ulbricht
fuente
2
Esto NO me funciona con cygwin. Utilizando la última versión de Windows 10 (actualizaciones automáticas), versión de nodo 8.11.4. Por "NO funciona" me refiero a que 1) el proceso termina, pero 2) el mensaje no se registra en la consola y 3) las conexiones HTTP creadas no se cierran. Sin embargo, debo agregar que lo probé en PowerShell y que funciona como se esperaba allí. Pero cambié a cygwin porque PowerShell tiene un comando curl incorrecto. ¡Maldito!
John Deighan
2
Dejó de funcionar para mí hoy sin razón aparente (sin actualizaciones) y todavía no sé por qué. La respuesta aceptada lo solucionó.
Sv443
4

Actualmente todavía no hay soporte en el nodo para capturar los eventos de control de la consola de Windows, por lo que no hay equivalentes a las señales POSIX:

https://github.com/joyent/node/issues/1553

Sin embargo, la documentación del módulo tty da un ejemplo de un mecanismo para capturar las pulsaciones de teclas con el fin de iniciar un cierre ordenado, pero esto solo funciona para ctrl+ c.

var tty = require('tty');

process.stdin.resume();
tty.setRawMode(true);

process.stdin.on('keypress', function(char, key) {
  if (key && key.ctrl && key.name == 'c') {
    console.log('graceful exit of process %d', process.pid);
    process.exit();
  }
});
Pero P.
fuente
Gracias, he estado buscando esta información, esta es una sustitución aceptable para mí siempre que pueda implementarla en el servidor para CTRL + C. +1 (Pero ... ¿Alguna idea de si esto afectará el rendimiento al agregar oyentes de eventos en el proceso?)
Cory Gross
Intenté hacer esto, pero cuando mi servidor está ejecutando el bucle de juego stdin no parece estar disponible, CTRL + C no funciona cuando uso lo anterior.
Cory Gross
0

Desde node.js 0.8, el keypressevento ya no existe. Sin embargo, existe un paquete npm llamado keypress que vuelve a implementar el evento.

Instale con npm install keypress, luego haga algo como:

// Windows doesn't use POSIX signals
if (process.platform === "win32") {
    const keypress = require("keypress");
    keypress(process.stdin);
    process.stdin.resume();
    process.stdin.setRawMode(true);
    process.stdin.setEncoding("utf8");
    process.stdin.on("keypress", function(char, key) {
        if (key && key.ctrl && key.name == "c") {
            // Behave like a SIGUSR2
            process.emit("SIGUSR2");
        } else if (key && key.ctrl && key.name == "r") {
            // Behave like a SIGHUP
            process.emit("SIGHUP");
        }
    });
}
mekwall
fuente