2013-06-04 7 views
5

Voglio scrivere una funzione di indicatore di avanzamento all'interno del mio script che esegue il loop di un messaggio "please wait" fino a quando l'attività che lo ha chiamato non è terminata.Come faccio a visualizzare una funzione di indicatore di avanzamento in uno script di shell?

Voglio che sia una funzione in modo che possa riutilizzarla in altri script.

Per ottenere ciò, la funzione deve essere liberamente associata ad altre funzioni, vale a dire che la funzione che la chiama non deve conoscere il suo codice interno.

Ecco quello che ho finora. Questa funzione riceve il pid del chiamante e dei loop fino al completamento dell'attività.

function progress() { 
    pid="$1" 

    kill -n 0 "${pid}" &> /dev/null && echo -ne "please wait" 
    while kill -n 0 "${pid}" &> /dev/null ; do 
    echo -n "." 
    sleep 1 
    done 
} 

Funziona bene quando lo si utilizza in uno script, come ad esempio:

#imports the shell script with the progress() function 
. /path/to/progress.sh 

echo "testing" 
# $$ returns the pid of the script. 
progress $$ & 
sleep 5 
echo "done" 

uscita:

$ testing 
$ please wait..... 
$ done 

Il problema è quando lo chiamo io da un'altra funzione, come funzioni non avere pid:

function my_func() { 
    progress $$ & 
    echo "my func is done" 
} 

. /path/to/progress.sh 
echo "testing" 
my_func 
sleep 10 
echo done 

Uscita:

$ testing 
$ please wait..... 
$ my func. is done. 
$ .......... 
$ done 

risposta

2

Potresti essere interessato allo dialog - sistema di menu orientato alle maledizioni di bash.

Per la barra di avanzamento è possibile controllare la, un altro progetto più semplice http://bash.cyberciti.biz/guide/A_progress_bar_(gauge_box)

o: http://www.theiling.de/projects/bar.html

se non interessati, si può provare il prossimo:

dotpid= 
rundots() { (trap 'exit 0' SIGUSR1; while : ; do echo -n '.' >&2; sleep 0.2; done) & dotpid=$!; } 
stopdots() { kill -USR1 $dotpid; wait $dotpid; trap EXIT; } 
startdots() { rundots; trap "stopdots" EXIT; return 0; } 

longproc() { 
    echo 'Start doing something long... (5 sec sleep)' 
    sleep 5 
    echo 
    echo 'Finished the long job' 
} 

run() { 
    startdots 
    longproc 
    stopdots 
} 

#main 
echo start 
run 
echo doing someting other 
sleep 2 
echo end of prog 
+0

questo è vicino al mio precedente tentativo, ma stavo cercando di evitare di doverlo uccidere al di fuori della mia funzione progress() ... Forse non può essere fatto con uno script di shell, però. Grazie! – Tarek

+0

Ciao, ho provato il codice fornito, ma soffre dello stesso problema da quando SIGTERM viene inviato quando il programma è terminato. Non posso usarlo all'interno di una funzione a meno che non invii esplicitamente il segnale kill. – Tarek

+1

@Tarek non capisco cosa intendi con "all'interno di una funzione" e "se non mandare l'uccisione" ... ma: ho modificato lo script mostrando come usarlo all'interno di una funzione, e per il secondo, ovviamente tu __need__ invia un segnale - in qualche modo devi dire al processo in background: "fermati ora" .... Se intendi qualcosa di diverso - non può aiutare ... – jm666

1

eseguendolo in background si ottiene il suo output mescolato con il resto del codice, in modo da non devono uscita nulla altrove mentre il progress è in esecuzione.

Per implementarlo come funzione, è necessario disporre di una variabile globale da controllare quando il progresso deve terminare (è possibile passare il nome della variabile come argomento allo progress quando lo si chiama).

+0

grazie, ma una variabile globale non avrebbe funzionato, in quanto non cambierebbe all'interno della funzione. – Tarek

+0

sì, lo farebbe. Ecco come funziona lo script di shell. Le funzioni non hanno valori di ritorno, devi usare anche variabili globali per questo. – yaccz

+0

stai parlando di esportare la variabile?Perché ho fatto un rapido test di ieri: param = "test" test di funzionamento() { echo $ 1 sonno 5 echo $ 1 \t echo $ {param} } prova $ {param} & param = "cambiato" attendere $ 1 echo $ {param} l'output è: $ test $ test $ test $ cambiati forse ho frainteso quello che volevi dire con variabile globale. – Tarek

1

Ho sentito parlare di questo project. Non l'ho usato quindi non sono sicuro di quanto sia facile da integrare, ma puoi dargli una lettura.

+0

grazie! Non ho bisogno di qualcosa che sia avanzato (solo un "per favore aspetta ..." mentre il programma è in esecuzione). Vado a dare un'occhiata al codice. – Tarek

0

Purtroppo ho wasn' Sono in grado di fare ciò che volevo usando lo script di shell. Ecco quello che ho fatto:

function progress() { 
    echo -ne "please wait" 
    while : 
    do 
    echo -n '.' 
    sleep 1 
    done 
} 

utilizzo:

aguarde & 
dotpid=$! 
# code 
eval "kill ${dotpid}" 
Problemi correlati