2012-08-02 12 views
6

me pregunto cómo crear una tuberíatubo de Linux con múltiples programas pidiendo la entrada del usuario

program 1 | ... | program N 

donde varios de los programas de pedir la entrada del usuario. El problema es que | inicia los programas en paralelo y, por lo tanto, comienzan a leer desde el terminal en paralelo.

En tales casos, sería útil tener una tubería | que inicie el programa (i + 1) solo después de que el programa i haya producido alguna salida.

Editar:

Ejemplo:

cat /dev/sda | bzip2 | gpg -c | ssh [email protected] 'cat > backup' 

Aquí, tanto gpg -c, así como ssh pedir una contraseña.

Una solución alternativa para este ejemplo en particular sería la creación de pares de claves ssh, pero esto no es posible en todos los sistemas, y me preguntaba si existe una solución general. También gpg permite pasar la frase de contraseña como argumento de línea de comando, pero esto no se sugiere por razones de seguridad.

+1

Una vez que conecte un programa para un tubo, que toma su entrada de otro programa, no el usuario. ¿Estás seguro de que quieres una pipa? Realmente no puedo pensar en un programa que tome las entradas * y * del usuario desde la entrada estándar. – chepner

+0

No es una respuesta, pero una idea que puede apuntar en la dirección correcta: ¿podría incluir código en cada programa para verificar el resultado de una cadena en particular, actualizar una bandera una vez encontrada y hacer que las otras llamadas repunten hasta que la bandera del programa anterior actualizado, luego les permite ejecutar? – JohnLBevan

+2

Muestra un ejemplo específico de lo que está sucediendo. Un programa podría leer de 'stdin' y de'/dev/tty', pero esto sería inusual. –

Respuesta

1

Puede utilizar esta construcción:

(read a; echo "$a"; cat) > file 

Por ejemplo:

$ (read a; echo "$a"; echo cat is started > /dev/stderr; cat) > file 
1 
cat is started 
2 
3 

Aquí 1, 2 y 3 fueron introducidos desde el teclado; cat is started fue escrito por echo.

Contenido de file después de la ejecución del comando:

$ cat file 
1 
2 
3 
0

por una gpg le puede dar la contraseña con la opción --passphrase.

Para ssh el mejor solución sería iniciar sesión por la clave. Pero si necesita hacer una contraseña, el comando expect será bueno. Aquí hay un buen ejemplo: Use expect in bash script to provide password to SSH command

Espere también le permite tener alguna entrada, por lo que si no desea codificar sus contraseñas este podría ser el camino a seguir.

1

ahora estoy utilizando:

#!/bin/bash 
sudo echo "I am root!" 
sudo cat /dev/disk0 | bzip2 | gpg -c | (read -n 1 a; (echo -n "$a"; cat) | ssh [email protected] 'cat > backup') 

La primera sudo evitará que el segundo de pedir de nuevo la contraseña. Como se sugirió anteriormente, el read pospone el inicio de ssh. Usé -n 1 para read ya que no quiero esperar a la nueva línea, y -n para echo para suprimir la nueva línea.

+1

'sudo -v' extenderá el tiempo de espera, solicitando la contraseña si todavía no se ha validado. Esto te permite evitar tener que generar un comando extraño ('echo' soy root! '') Para ejecutar. – chepner

0

He necesitado algo similar unas cuantas veces, donde el primer comando en la tubería requiere que se ingrese una contraseña, y el siguiente comando no atiende automáticamente esto (como la forma en que lo hace less).

Similar a la respuesta de Igor, creo que el uso de leer dentro de un subnivel útil:

cmd1 | (read; cat - | cmd2) 
Cuestiones relacionadas