GNU/Linux >> Tutoriels Linux >  >> Linux

Bash :attendre avec un délai d'attente

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


Linux
  1. Bash -c avec des paramètres positionnels ?

  2. Tableaux bash avec exemples

  3. Waitpid équivalent avec timeout?

  4. Que fait poll() avec un timeout de 0 ?

  5. Alias ​​avec variable dans bash

Comment écrire un script bash avec des exemples

Tutoriel Bash HereDoc avec exemples

Commande d'attente bash

Commande Wait sous Linux avec des exemples

Comment créer des documents avec des scripts Bash

Syntaxe Bash If Else avec exemples