2017-08-23 3 views
0

Ich muss ein Bash-Skript von der nodejs-App ausführen. Normalerweise würde ich etwas wie folgt aus:So führen Sie das Shell-Skript ordnungsgemäß aus: nodejs

var childProcess = require('child_process'); 
childProcess.execFile('./test.sh', function (error, stdout, stderr) { 
    console.log(error, stdout, stderr); 
}) 

Aber ich vor kurzem lief in ein Bash-Skript, das nie beendet, wenn es so ausgeführt wurde. Dies ist ein minimales Beispiel, das das Problem reproduziert:

#!/bin/bash 
LC_CTYPE=C cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 8 | head -n 1 
  • LC_CTYPE=C - die tr zwingen, alles als ASCII-Zeichen
  • tr -dc "a-zA-Z0-9" < /dev/urandom zu interpretieren - lesen Pseudo-Zufalls-Bytes, verwirft alles außer a-zA-Z0-9
  • fold -w 8 - wickeln Ausgang in Zeilen 8 Zeichen lang
  • head -n 1 - lesen Sie die erste Zeile (8 Zeichen)

Wenn vom Terminal ausgeführt funktioniert es gut und es sofort beendet:

# ./test.sh 
0J5hsGeh 

Wenn die oben ausgeführt unter Verwendung von NodeJS Skript hängt er einfach:

# node test.js 

screenshot from htop command

Es scheint, dass die head -n 1 ist bereits beendet, aber die cat /dev/urandom läuft noch.

Frage: Wie führt man das Skript von Nodejs, so dass es nicht hängt?

Env:

  • OS: Ubuntu 16.04
  • NodeJS Version: v6.11.2
+0

Versuchen Sie, das Ende der Bash-Skript 'exit' Befehl hinzufügen –

+0

in Ihrem shebang Set -x oder es über bash -x ausführen, werden wir ein klareres Bild von dem, was –

+0

Jungen passiert, vielen Dank für Vorschläge. Sie helfen jedoch nicht. 'exit' am Ende des Skripts tut nichts und in diesem Fall wird es nicht einmal ausgeführt, weil die vorherige Zeile niemals endet.Das '-x' hilft auch nicht, weil das Skript nie beendet wird, so dass die von' -x' erzeugte Ausgabe nicht gedruckt wird. Wie auch immer, ich versuche nicht, das Bash-Skript zu debuggen. Ich versuche herauszufinden, warum die Ausführung durch nodejs einen Unterschied macht. – Prvaak

Antwort

0

Dies wird durch die Tatsache verursacht, dass NodeJS ignores SIGPIPE signal. Wenn ein Subprozess erzeugt wird, wird das SIGPIPE-Signal vom erzeugten Subprozess ebenfalls ignoriert.

Aus diesem Grund wird der Befehl cat nicht beendet, wenn die Leitung unterbrochen wird, nachdem head nach dem Lesen der ersten Zeile beendet wurde. So liest die cat Daten von /dev/urandom für immer.

Es sollte fixed in einer der zukünftigen Versionen von NodeJS sein (nicht sicher, was aber). Für den Moment verwende ich nur den Workaround von that issue.

var childProcess = require('child_process'); 
process.on('SIGPIPE', noop); // <---- 
childProcess.execFile('./test.sh', function (error, stdout, stderr) { 
    console.log(error, stdout, stderr); 
}) 
process.removeListener('SIGPIPE', noop); // <---- 
Verwandte Themen