2011-02-02 9 views
6

Deseo enviar algunos datos a un proceso raíz con un canalización con nombre. Aquí está la secuencia de comandos y funciona muy bien:Script Bash con lectura no bloqueada

#!/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 

De hecho, tengo varios guiones como este. Me gustaría incluirlos a todos en un solo script. El problema es que los bloques de ejecución en la primera "lectura" y no puedo ejecutar varias "lecturas" en un solo proceso. ¿No hay nada que pueda hacer? ¿Es posible tener una lectura bash "sin bloqueo"?

+0

¿Por qué quiere combinar operaciones separadas en una sola ¿guión? Si cada uno funciona correctamente de manera independiente, déjelos independientes. Es mucho más fácil que intentar doblar el caparazón para hacer lecturas sin bloqueo. Los procesos son baratos. Los procesos simples también son más seguros que los complejos, y los procesos raíz deben ser seguros. –

+0

Estoy de acuerdo con usted, pero cada proceso come 628K de RAM (es una copia del bash) y estoy en un entorno incrustado. Preferiría guardar tanta memoria como sea posible. – michelemarcon

+0

Si es un gran problema, escriba el código en C. –

Respuesta

3

Sólo hay que poner el ciclo de lectura en el fondo (añadir & después de hacerlo)?

+0

¡Genial! ¡Reduje a la mitad el consumo de memoria! – michelemarcon

+0

@michelemarcon: ¿estás seguro de que estás guardando la memoria? Cuando lo probé, agregando '&' forzó el ciclo while para ejecutar en una subcadena = otro proceso = más memoria utilizada. –

+0

Probado con ps, cada secuencia de comandos come 628K. Con '&', cada proceso come 240K. Y por cierto, dado que cada 'while' está en segundo plano, la secuencia de comandos "madre" salió y liberó su memoria – michelemarcon

0

Puede usar stty para establecer un tiempo de espera. IIRC es algo como

stty -F $pipe -icanon time 0 
+0

Obtengo el argumento Inválido. Pero esto es probablemente porque estoy trabajando con busybox [http://en.wikipedia.org/wiki/Busybox] – michelemarcon

+0

@michelemarcon Obtengo lo mismo, y actualmente no estoy usando busybox. Pero cuando lo hago, he encontrado que esta página es extremadamente útil: http://www.busybox.net/BusyBox.html –

+0

También recibo un error de argumento no válido, con Ubuntu 12.04. – Hibou57

13

lectura incrustado comandos de Bash tiene un parámetro -t para establecer un tiempo de espera:

-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. 

Esto debería ayudar a resolver este problema.

Editar:

hay algunas restricciones para que esta solución funciona como la página del manual indica: Esta opción no tiene efecto si se lee no es la lectura de entrada de la terminal o una pipa.

Así que si puedo crear una tubería en/tmp:

mknod /tmp/pipe p 

lectura directamente de la tubería no está funcionando:

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

se bloquea para siempre.

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

Está funcionando pero el gato no se está yendo.

Una solución es asignar el tubo a un descriptor de archivo:

$ exec 7<>/tmp/pipe 

y luego leer de este descriptor de archivo, ya sea mediante el redireccionamiento:

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

o la opción -u de read:

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

El * esta opción no tiene efecto si la lectura no está leyendo la entrada desde el terminal o una tubería. * Tiene alguna implicación. Estoy editando la respuesta para incluir ejemplos de trabajo – gabuzo

+0

Todavía no funciona para mí, pero tal vez estoy ejecutando un golpe personalizado. – michelemarcon

+0

¿'read -h' muestra un mensaje de ayuda con la opción' -t'? – gabuzo

Cuestiones relacionadas