GNU/Linux >> Linux Esercitazione >  >> Linux

Bash:aspetta con timeout

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


Linux
  1. Bash -c con parametri posizionali?

  2. Matrici Bash con esempi

  3. Bash Istruzione If-Else con esempi

  4. Waitpid equivalente con timeout?

  5. basename con spazi in uno script bash?

Come scrivere uno script Bash con esempi

Bash HereDoc Tutorial con esempi

Bash wait Comando

Attendi comando in Linux con esempi

Come creare documenti con gli script Bash

Bash If Else Sintassi con esempi