2011-02-02 19 views
6

Desidero inviare alcuni dati a un processo radice con una named pipe. Ecco la sceneggiatura e funziona benissimo:Script Bash con lettura non bloccante

#!/bin/sh 
pipe=/tmp/ntp 

if [[ ! -p $pipe ]]; then 
    mknod -m 666 $pipe p 
fi 

while true 
do 
    if read line <$pipe; then 
     /root/netman/extra/bin/ntpclient -s -h $line > $pipe 2>&1 
    fi 
done 

In realtà ho diversi script come questo. Vorrei racchiuderli tutti in una singola sceneggiatura. Il problema è che i blocchi di esecuzione sulla prima "lettura" e io non posso eseguire più "letture" in un singolo processo. Non c'è niente che posso fare? È possibile avere una lettura bash "non bloccante"?

+0

Perché si desidera combinare operazioni separate in un unico sceneggiatura? Se funzionano correttamente, lasciali indipendenti. È molto più facile che provare a piegare la shell per eseguire letture non bloccanti. I processi sono economici. I processi semplici sono anche più sicuri di quelli complessi e i processi di root devono essere sicuri. –

+0

Sono d'accordo con te, ma ogni processo consuma 628K di RAM (è una copia della bash) e sono in un ambiente embedded. Preferirei salvare più memoria possibile. – michelemarcon

+0

Se questo è un grosso problema, scrivere il codice in C. –

risposta

3

Basta mettere il ciclo di lettura in background (aggiungere & dopo a farsi)?

+0

Ottimo! Ho dimezzato il consumo di memoria! – michelemarcon

+0

@michelemarcon: sei sicuro di voler risparmiare memoria? Quando l'ho testato, aggiungendo '&' forzato il ciclo while da eseguire in una subshell = un altro processo = più memoria utilizzata. –

+0

Testato con ps, ogni script mangia 628K. Con "&", ogni processo consuma 240 K. E dal momento che ogni 'while' è in background, lo script "madre" è uscito e ha liberato la sua memoria – michelemarcon

0

È possibile utilizzare stty per impostare un timeout. IIRC la sua qualcosa come

stty -F $pipe -icanon time 0 
+0

Ottengo argomento non valido. Ma questo è probabilmente perché sto lavorando con busybox [http://en.wikipedia.org/wiki/Busybox] – michelemarcon

+0

@michelemarcon Ho la stessa cosa, e attualmente non sto usando busybox. Ma quando lo sono, ho trovato questa pagina estremamente utile: http://www.busybox.net/BusyBox.html –

+0

Ho anche un errore di argomento non valido, con Ubuntu 12.04. – Hibou57

13

comando di lettura integrato di Bash ha un parametro -t per impostare un timeout:

-t timeout 
    Cause read to time out and return failure if a complete line of input is not 
    read within timeout seconds. This option has no effect if read is not reading 
    input from the terminal or a pipe. 

Questo dovrebbe aiutare a risolvere questo problema.

Edit:

Ci sono alcune restrizioni per questa soluzione per lavorare come la pagina man indica: Questa opzione non ha effetto se letto non è la lettura di ingresso dal terminale o un tubo.

Quindi, se creo un tubo in/tmp:

mknod /tmp/pipe p 

lettura direttamente dal tubo non funziona:

$ read -t 1 </tmp/pipe ; echo $? 

si blocca sempre.

$ cat /tmp/pipe | (read -t 1 ; echo $?) 
1 

Sta funzionando ma il gatto non sta uscendo.

Una soluzione è quella di assegnare il tubo per un file di descrizione:

$ exec 7<>/tmp/pipe 

E poi leggere da questo descrittore di file o utilizzando il reindirizzamento:

$ read -t 1 <&7 ; echo $? 
1 

o l'opzione -u di read:

$ read -t 1 -u 7 ; echo $? 
1 
+0

* questa opzione non ha alcun effetto se read non sta leggendo l'input dal terminale o da una pipe. * Ha qualche implicazione. Sto modificando la risposta per includere esempi di lavoro – gabuzo

+0

Ancora non funziona per me, ma forse sto eseguendo una bash personalizzata. – michelemarcon

+0

'read -h' mostra un messaggio di aiuto con l'opzione' -t'? – gabuzo