2012-08-02 14 views
6

Mi chiedo come creare un tubo ditubo di linux con più programmi chiedere per l'input dell'utente

program 1 | ... | program N 

dove multipla dei programmi chiedere per l'input dell'utente. Il problema è che | avvia i programmi in parallelo e quindi iniziano a leggere dal terminale in parallelo.

Per tali casi sarebbe utile disporre di una pipe | che avvii il programma (i + 1) solo dopo che il programma ha prodotto qualche output.

Edit:

Esempio:

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

Qui sia gpg -c nonché ssh chiedere una password.

Una soluzione per questo specifico esempio sarebbe la creazione di coppie di chiavi ssh, ma questo non è possibile su tutti i sistemi e mi chiedevo se esiste una soluzione generale. Anche gpg consente di passare la passphrase come argomento della riga di comando, ma questo non è consigliato per motivi di sicurezza.

+1

Una volta che ci si connette un programma ad un tubo, si ottiene il suo ingresso da un altro programma, non l'utente. Sei sicuro di volere una pipa? Non riesco davvero a pensare a un programma che sia in grado di catturare l'input dell'utente * e * legge dallo standard input. – chepner

+0

Non una risposta, ma un'idea che potrebbe indirizzarti nella giusta direzione: potresti includere il codice attorno a ciascun programma per controllare l'output di una particolare stringa, aggiornare un flag una volta trovato e avere l'altro loop di chiamate fino a quando la flag del programma precedente non è stata aggiornato, quindi consentire loro di correre? – JohnLBevan

+2

Mostra un esempio specifico di questo evento. Un programma potrebbe leggere da 'stdin' e da'/dev/tty', ma ciò sarebbe inusuale. –

risposta

1

È possibile utilizzare questa costruzione:

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

Ad esempio:

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

Qui 1, 2 e 3 sono stati immessi dalla tastiera; cat is started è stato scritto da echo.

Contenuto del file dopo l'esecuzione del comando:

$ cat file 
1 
2 
3 
0

per quello che si può dare la password gpg con l'opzione --passphrase.

Per ssh il migliore soluzione sarebbe di accedere tramite chiave. Ma se devi fare una password, il comando expect sarà buono. Ecco un buon esempio: Use expect in bash script to provide password to SSH command

Expect consente anche di avere un po 'di input - quindi se non si vuole hardcode le password questa potrebbe essere la strada da percorrere.

1

ora sto usando:

#!/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 prima sudo impedirà il secondo di chiedere nuovamente la password. Come suggerito sopra, lo read rimanda l'avvio di ssh. Ho utilizzato -n 1 per read poiché non desidero attendere la nuova riga e -n per echo per sopprimere la nuova riga.

+1

'sudo -v' estenderà il timeout, richiedendo la password se non è stato ancora convalidato. Ciò consente di evitare di dover eseguire un comando estraneo ('echo" I am root! "') Per l'esecuzione. – chepner

0

Ho avuto bisogno di qualcosa di simile un paio di volte prima, dove il primo comando nella pipeline richiede una password da inserire, e il comando successivo non gestisce automaticamente questo (come il modo in cui lo fa less).

Simile alla risposta di Igor, trovo l'uso di lettura all'interno di una subshell utile:

cmd1 | (read; cat - | cmd2) 
Problemi correlati