2013-03-17 4 views
20

La mia domanda è simile a questa: How to detect if my shell script is running through a pipe?. La differenza è che lo script di shell su cui sto lavorando è scritto in Node.js.Come rilevare se uno script Node.js è in esecuzione attraverso una pipe shell?

Diciamo che entro:

echo "foo bar" | ./test.js 

allora come posso ottenere il valore "foo bar" in test.js?

Ho letto Unix and Node: Pipes and Streams ma sembra solo offrire una soluzione asincrona (a meno che non mi sbagli). Sto cercando una soluzione sincrona. Inoltre, con questa tecnica, non sembra molto semplice rilevare se lo script viene sottoposto a pipe o meno.

TL; DR mia domanda è duplice:

  1. come rilevare se uno script Node.js viene eseguito attraverso un tubo shell, ad esempio echo "foo bar" | ./test.js?
  2. Se sì, come leggere il valore di pipe in Node.js?

risposta

19

I pipe sono fatti per gestire piccoli input come "foo bar" ma anche file enormi.

L'API del flusso consente di iniziare a gestire i dati senza attendere che l'enorme file venga interamente convogliato (è meglio per la memoria di velocità &). Il modo in cui lo fa è fornendoti blocchi di dati.

Non esiste un'API sincrona per le pipe. Se si vuole veramente avere tutto convogliato in ingresso nelle vostre mani prima di fare qualcosa, è possibile utilizzare

nota: utilizzare solo node >= 0.10.0 perché l'esempio utilizza l'API stream2

var data = ''; 
function withPipe(data) { 
    console.log('content was piped'); 
    console.log(data.trim()); 
} 
function withoutPipe() { 
    console.log('no content was piped'); 
} 

var self = process.stdin; 
self.on('readable', function() { 
    var chunk = this.read(); 
    if (chunk === null) { 
     withoutPipe(); 
    } else { 
     data += chunk; 
    } 
}); 
self.on('end', function() { 
    withPipe(data); 
}); 

test con

echo "foo bar" | node test.js 

e

node test.js 
38

Ho appena trovato una risposta più semplice a una parte della mia domanda.

di rilevare rapidamente e in modo sincrono se il contenuto di sottofondo viene passato allo script corrente in Node.js, utilizzare il process.stdin.isTTY booleano:

$ node -p -e 'process.stdin.isTTY' 
true 
$ echo 'foo' | node -p -e 'process.stdin.isTTY' 
undefined 

Così, in uno script, si potrebbe fare qualcosa di simile:

if (process.stdin.isTTY) { 
    // handle shell arguments 
} else { 
    // handle piped content (see Jerome’s answer) 
} 

la ragione per cui non ho trovato questo prima è perché stavo guardando la documentazione per process, dove isTTY non è menzionato affatto. Invece, è menzionato in the TTY documentation.

+0

purtroppo, questo non riuscirà in un processo figlio: 'nodo -p -e "require ('child_process') exec (\." nodo -p -e 'process.stdin.isTTY' \", (err , res) => console.log ('err:', err, 'res:', res)) "' – maxlath

1

Se avete bisogno di tubo nel nodejs utilizzando un inline --eval stringa in bash, cat lavora troppo:

$ echo "Hello" | node -e "console.log(process.argv[1]+' pipe');" "$(cat)" 
# "Hello pipe" 
0

è necessario controllare stdout (non stdin come suggerito altrove) in questo modo:

if (process.stdout.isTTY) { 
    // not piped 
} else { 
    // piped 
}