Bonjour,
J'ai besoin d'écrire un script bash qui lance une commande qui peut
être longue ou même bloquante, et l'interrompre si c'est le cas au bout
d'un certain délai. Je lance donc ma commande dans un sous-shell, un
« sleep » dans un autre, et le premier des deux qui se termine nettoie
l'autre. Cela marche bien lorsque je lance mon script depuis une ligne
de commande, mais en fait, je veux récupérer la sortie standard de ce
programme dans une variable bash, et là, problème : le programme
s'exécute bien, mais si la commande voulue se termine rapidement et
nettoie le « sleep », une fois mon programme terminé, il semble que
bash attende la durée programmée du sleep avant de continuer !!
Voici une version simplifiée du programme (avec une commande « ls » qui
ne devrait pas trop prendre de temps, et un sleep de 10 secondes) :
#!/bin/bash
cmd='ls >/dev/null'
function test1() {
set -x
trap 'kill -TERM $fils2 >/dev/null 2>&1' USR1
( eval $cmd && \
sleep 0.1 && \
kill -USR1 $$ ) &
fils1=$!
( sleep 10 && \
kill $fils1 >/dev/null 2>&1 ) &
fils2=$!
# attend que tout se termine
wait $fils2
trap - USR1
return 0
}
test1
exit $?
* Si je lance le programme depuis l'invite du shell, tout va bien :
$ time ./testSleep
+ trap 'kill -TERM $fils2 >/dev/null 2>&1' USR1
+ fils1=13248
+ sleep 10
+ fils2=13249
+ wait 13249
+ eval ls '>/dev/null'
++ ls
+ sleep 0.1
+ kill -USR1 13247
++ kill -TERM 13249
+ trap - USR1
+ return 0
+ exit 0
real 0m0.116s
user 0m0.000s
sys 0m0.004s
* si je récupère la sortie standard du programme dans une variable
bash, ma commande prend 10 secondes :
$ time res=$(./testSleep)
+ trap 'kill -TERM $fils2 >/dev/null 2>&1' USR1
+ eval ls '>/dev/null'
++ ls
+ fils1=14416
+ sleep 10
+ fils2=14418
+ wait 14418
+ sleep 0.1
+ kill -USR1 14415
++ kill -TERM 14418
+ trap - USR1
+ return 0
+ exit 0
real 0m10.015s
user 0m0.000s
sys 0m0.008s
[les traces jusqu'à « + exit 0 » apparaissent immédiatement]
Auriez-vous une explication à ce phénomène ? Ou encore mieux une
solution ;-) ?
Fred.