2015-10-08 13 views
5

Ho un comando vorrei correre per generare stringa casuale:Piping a testa risultati in tubo rotto in script di shell chiamato in pitone

var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8` 

Quando eseguo questo comando in sessione bash interattiva ricevo assolutamente nessun errore . Ma quando inserisco questo comando nello script e lo eseguo come script, viene visualizzato l'errore Broken pipe indicato da tr. Ho letto diversi argomenti correlati, ma non ho ancora una risposta sul perché lo script e il comportamento interattivo sono diversi e c'è un modo per controllarlo con le opzioni della shell o con qualcos'altro?

Edit I:

Per quanto riguarda Commenti forniti Ho trovato che indica errori tubo rotto può essere controllato mediante:

trap - SIGPIPE # to ignore errors 

e

trap "" SIGPIPE # to display errors 

Edit II:

Bene, ho fornito informazioni errate sulle condizioni di riproduzione. Infine, sembra che problema causato con l'involucro pitone che ha chiamato lo script con l'os.system():

python -c "import os; os.system('sh -c \"< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8\"')" 

linea proposta produce errori tubo rotto indipendentemente OS usate.

Edit III:

Questo argomento è stato discusso qui: https://mail.python.org/pipermail/python-dev/2005-September/056341.html

+1

suona come il problema in discussione [qui] (https://github.com/koalaman/shellcheck/issues/494) e nel numero di riferimento. (lo shellcheck non è coinvolto qui è solo una discussione su questo problema esatto e la discussione sull'avere uno shellcheck, che è un ottimo strumento, che avverte esattamente di questo genere di cose.) –

+0

Funziona perfettamente con Cygwin/bash-4.1.10 (4) ... (Imposta la tua linea più un 'echo $ var' in uno script, nient'altro eccetto '#!/Bin/sh'.) – Amessihel

+1

Stai intercettando SIGPIPE nello script? – PSkocik

risposta

3

Se uno dei processi genitore intrappola sigpipe, poi il gasdotto erediterà la disposizione ignore del segnale, che farà sì che questo problema stai vivendo.

Questo può essere (in modo sicuro) riprodotto con:

(trap '' pipe; var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8) 

Normalmente, il comando head -c8 sarà fatto molto presto ea quel punto la sua stdin è chiuso. Poiché è stdin una pipe collegata allo stdout di tr, ora non ha più senso scrivere tr nello stdout. Una volta provato, il sistema lo ucciderà con SIGPIPE. A meno che il tr ignori questo segnale o abbia ereditato la disposizione ignore (SIG_IGN) per questo segnale dal suo genitore. Quindi un rotto da a stdout causerà semplicemente un errore regolare e imposta errno a EPIPE a cui il punto tr molto probabilmente sarà unificatore e restituirà questo errore al suo stderr e uscirà.

Problemi correlati