Votre exemple et la réponse acceptée sont trop compliqués, pourquoi ne faites-vous pas seulement utilisez timeout
puisque c'est exactement son cas d'utilisation ? Le timeout
La commande a même une option intégrée (-k
) pour envoyer SIGKILL
après avoir envoyé le signal initial pour terminer la commande (SIGTERM
par défaut) si la commande est toujours en cours d'exécution après l'envoi du signal initial (voir man timeout
).
Si le script ne nécessite pas nécessairement de wait
et reprendre le flux de contrôle après avoir attendu, c'est simplement une question de
timeout -k 60s 60s app1 &
timeout -k 60s 60s app2 &
# [...]
Si c'est le cas, cependant, c'est tout aussi simple en enregistrant le timeout
PID à la place :
pids=()
timeout -k 60s 60s app1 &
pids+=($!)
timeout -k 60s 60s app2 &
pids+=($!)
wait "${pids[@]}"
# [...]
Par exemple
$ cat t.sh
#!/bin/bash
echo "$(date +%H:%M:%S): start"
pids=()
timeout 10 bash -c 'sleep 5; echo "$(date +%H:%M:%S): job 1 terminated successfully"' &
pids+=($!)
timeout 2 bash -c 'sleep 5; echo "$(date +%H:%M:%S): job 2 terminated successfully"' &
pids+=($!)
wait "${pids[@]}"
echo "$(date +%H:%M:%S): done waiting. both jobs terminated on their own or via timeout; resuming script"
.
$ ./t.sh
08:59:42: start
08:59:47: job 1 terminated successfully
08:59:47: done waiting. both jobs terminated on their own or via timeout; resuming script
Écrivez les PID dans les fichiers et démarrez les applications comme ceci :
pidFile=...
( app ; rm $pidFile ; ) &
pid=$!
echo $pid > $pidFile
( sleep 60 ; if [[ -e $pidFile ]]; then killChildrenOf $pid ; fi ; ) &
killerPid=$!
wait $pid
kill $killerPid
Cela créerait un autre processus qui dort pendant le délai d'attente et tue le processus s'il n'est pas terminé jusqu'à présent.
Si le processus se termine plus rapidement, le fichier PID est supprimé et le processus tueur est terminé.
killChildrenOf
est un script qui récupère tous les processus et tue tous les enfants d'un certain PID. Voir les réponses à cette question pour différentes manières d'implémenter cette fonctionnalité :Meilleure façon de tuer tous les processus enfants
Si vous souhaitez sortir de BASH, vous pouvez écrire des PID et des délais d'attente dans un répertoire et surveiller ce répertoire. Toutes les minutes environ, lisez les entrées et vérifiez quels processus sont toujours présents et s'ils ont expiré.
MODIFIER Si vous voulez savoir si le processus est mort avec succès, vous pouvez utiliser kill -0 $pid
EDIT2 Ou vous pouvez essayer des groupes de processus. kevinarpe a dit :Pour obtenir le PGID d'un PID (146322) :
ps -fjww -p 146322 | tail -n 1 | awk '{ print $4 }'
Dans mon cas :145974. Ensuite, PGID peut être utilisé avec une option spéciale de kill pour terminer tous les processus d'un groupe :kill -- -145974