Was ist das Windows-Äquivalent von process.on ('SIGINT') in node.js?

84

Ich folge hier den Anweisungen (auf SIGINTEreignisse warten), um meine von Windows-8 gehostete Anwendung node.js als Reaktion auf das Herunterfahren von Ctrl+ Coder Server ordnungsgemäß herunterzufahren.

Aber Windows hat nicht SIGINT. Ich habe es auch versucht process.on('exit'), aber das scheint zu spät, um etwas Produktives zu tun.

Unter Windows gibt mir dieser Code: Fehler: Kein solches Modul

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

Unter Windows wird dieser Code ausgeführt, ist jedoch zu spät, um etwas Anmutiges zu tun :

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

Gibt es ein SIGINTgleichwertiges Ereignis unter Windows?

Pappadog
quelle
Dieses Problem ist mir heute zufällig aufgetreten und ich denke, es hat etwas mit dem Readline-Modul selbst zu tun. Ich konnte keine Tests durchführen, aber seit ich dieses Modul hinzugefügt habe, trat das Problem auf.
Sv443

Antworten:

148

Sie müssen das Readline-Modul verwenden und auf ein SIGINT-Ereignis warten:

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
quelle
Das beste Update, danke! Dies als Antwort festzulegen, da die vorherige Antwort (auf Tastendruck warten) nicht mehr funktioniert.
Pappadog
43
Das ist lächerlich. Warum wird dies nicht vom Knotenkern erledigt?
Balupton
3
Denn wenn Sie stdin hören, wird der Prozess erst beendet, wenn Sie explizit ein SIGINT-Signal senden.
Gabriel Llamas
2
Daher müssen Sie eine zufällige Nachricht vom Elternteil an das Kind senden, zum Beispiel: "SIGINT".
Gabriel Llamas
8
Es sieht so aus, als ob dies vor einiger Zeit gelöst wurde: github.com/nodejs/node-v0.x-archive/issues/5054
SimonSimCity
23

Ich bin mir nicht sicher, wann, aber auf Knoten 8.x und Windows 10 funktioniert der ursprüngliche Fragencode jetzt einfach.

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 );

Geben Sie hier die Bildbeschreibung ein

funktioniert auch mit einer Windows-Eingabeaufforderung.

Meirion Hughes
quelle
Das ist mir auch aufgefallen. Windows 7 ist ein großes Problem für mich hier
Gregory Nowakowski
Diese Methode funktioniert für mich mit Node 8.11.1 unter Windows 7 - aber ich habe sie von einer Git-Bash-Shell ausgeführt. Ich dachte, ich würde zuerst den einfachen Weg versuchen und es hat funktioniert.
user944849
7

Sofern Sie den Import "readline" nicht für andere Aufgaben benötigen, würde ich empfehlen, "readline" zu importieren, sobald das Programm überprüft hat, dass es unter Windows ausgeführt wird. Darüber hinaus funktioniert dies sowohl für Windows 32-Bit- als auch für Windows 64-Bit-Systeme (die das Schlüsselwort "win32" zurückgeben). Danke für diese Lösung 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
quelle
5

Heutzutage funktioniert es nur auf allen Plattformen , einschließlich Windows.

Der folgende Code protokolliert und wird unter Windows 10 ordnungsgemäß beendet:

process.on('SIGINT', () => {
    console.log("Terminating...");
    process.exit(0);
});
Heinrich Ulbricht
quelle
2
Dies funktioniert bei mir unter Cygwin NICHT. Verwenden Sie das neueste Windows 10 (automatische Updates), Knotenversion 8.11.4. Mit "es funktioniert NICHT" meine ich, dass 1) der Prozess beendet wird, aber 2) die Nachricht nicht an der Konsole protokolliert wird und 3) die erstellten HTTP-Verbindungen nicht heruntergefahren werden. Ich sollte jedoch hinzufügen, dass ich es unter PowerShell versucht habe und es dort wie erwartet funktioniert. Aber ich bin zu Cygwin gewechselt, weil PowerShell einen schlechten Curl-Befehl hat. Verflixt!
John Deighan
2
Es hat gerade heute ohne ersichtlichen Grund aufgehört zu arbeiten (überhaupt keine Updates) und ich weiß immer noch nicht warum. Die akzeptierte Antwort hat es behoben.
Sv443
4

Derzeit gibt es im Knoten noch keine Unterstützung für die Erfassung der Windows-Konsolensteuerungsereignisse. Daher gibt es keine Entsprechungen zu den POSIX-Signalen:

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

Die Dokumentation zum tty-Modul enthält jedoch ein Beispiel für einen Mechanismus zum Erfassen der Tastendrücke, um ein ordnungsgemäßes Herunterfahren einzuleiten. Dies funktioniert jedoch nur für 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.
quelle
Vielen Dank, ich habe nach diesen Informationen gesucht. Dies ist eine akzeptable Ersetzung für mich, solange ich sie auf dem Server für STRG + C implementieren kann. +1 (Aber .. Irgendeine Idee, ob dies die Leistung durch Hinzufügen von Ereignis-Listenern zum Prozess beeinflusst?)
Cory Gross
Ich habe dies versucht, aber wenn auf meinem Server die Spielschleife ausgeführt wird, scheint stdin nicht verfügbar zu sein. STRG + C funktioniert nicht, wenn ich die oben genannten Funktionen verwende.
Cory Gross
0

Seit node.js 0.8 existiert das keypressEreignis nicht mehr. Es gibt jedoch ein npm-Paket namens keypress , das das Ereignis erneut implementiert.

Installieren Sie mit npm install keypressund machen Sie dann etwas wie:

// 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
quelle