Sia il tuo esempio che la risposta accettata sono eccessivamente complicati, perché non solo usa timeout
poiché è esattamente il suo caso d'uso? Il timeout
command ha anche un'opzione incorporata (-k
) per inviare SIGKILL
dopo aver inviato il segnale iniziale per terminare il comando (SIGTERM
per impostazione predefinita) se il comando è ancora in esecuzione dopo aver inviato il segnale iniziale (vedi man timeout
).
Se lo script non richiede necessariamente wait
e riprendere il flusso di controllo dopo aver atteso è semplicemente una questione di
timeout -k 60s 60s app1 &
timeout -k 60s 60s app2 &
# [...]
In tal caso, tuttavia, è altrettanto facile salvare il timeout
PID invece:
pids=()
timeout -k 60s 60s app1 &
pids+=($!)
timeout -k 60s 60s app2 &
pids+=($!)
wait "${pids[@]}"
# [...]
Ad esempio
$ 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
Scrivi i PID nei file e avvia le app in questo modo:
pidFile=...
( app ; rm $pidFile ; ) &
pid=$!
echo $pid > $pidFile
( sleep 60 ; if [[ -e $pidFile ]]; then killChildrenOf $pid ; fi ; ) &
killerPid=$!
wait $pid
kill $killerPid
Ciò creerebbe un altro processo che dorme per il timeout e termina il processo se non è stato completato finora.
Se il processo viene completato più velocemente, il file PID viene eliminato e il processo killer viene terminato.
killChildrenOf
è uno script che recupera tutti i processi e uccide tutti i figli di un certo PID. Vedi le risposte a questa domanda per i diversi modi di implementare questa funzionalità:Il modo migliore per terminare tutti i processi figlio
Se vuoi uscire da BASH, puoi scrivere PID e timeout in una directory e guardare quella directory. Ogni minuto circa, leggi le voci e controlla quali processi sono ancora attivi e se sono scaduti.
MODIFICA Se vuoi sapere se il processo è terminato con successo, puoi usare kill -0 $pid
EDIT2 Oppure puoi provare i gruppi di processi. kevinarpe ha detto:Per ottenere PGID per un PID(146322):
ps -fjww -p 146322 | tail -n 1 | awk '{ print $4 }'
Nel mio caso:145974. Quindi PGID può essere utilizzato con un'opzione speciale di kill per terminare tutti i processi in un gruppo:kill -- -145974