Integrato puro bash
, senza coreutils
Ho scoperto che questa soluzione funziona bash
basandosi su un comando integrato senza chiamare un eseguibile esterno. Funziona su un sistema dove alla fine non sono stati nemmeno installati i coreutils [ 1 ]
YourCommand & read -t 300 ; kill $! # 1st version
YourCommand & read -t 300 || kill $! # 2nd version
Spiegazioni : come al solito quando si invia un comando in background con &
, il suo PID è memorizzato nella variabile interna $!
(presente nella versione moderna di dash
, csh
, bash
, tcsh
, zsh
...).
Ciò che fa davvero la differenza tra le shell è la presenza del comando integrato read
[ 2 ] e dell'opzione -t
. Nella prima versione se l'utente non completerà una riga di input prima del numero di secondi specificato, l'istruzione verrà chiusa e verrà generato un codice di ritorno dell'errore.
-t TIMEOUT Consente di leggere il timeout e di restituire l'errore se non viene letta una riga di input completa entro TIMEOUT secondi.
La seconda versione funziona come la prima ma è possibile interrompere il timeout dell'uccisione semplicemente premendo enter.
In effetti l'operatore o ||
esegue l' kill
istruzione solo se il read
comando esce con un codice di ritorno diverso da zero, come quando il timeout è scaduto. Se premi enterprima di quel momento, restituirà 0 e non ucciderà il tuo comando precedente.
Coreutils solutions [ 1 ]
Quando coreutils sono presenti sul sistema e non avete bisogno di risparmiare il tempo e le risorse per chiamare un programma esterno, timeout
e sleep
e sono entrambi i modi perfetti per raggiungere il tuo obiettivo.
timeout
L'uso di timeout
è semplice.
Alla fine puoi considerare di usare anche l' -k
opzione per inviare un segnale di kill aggiuntivo se il primo fallisce.
timeout 5m YourCommand # 3rd version
sleep
Con sleep
te puoi usare la tua fantasia o prendere qualche ispirazione [ 3 ] . Nota che puoi lasciare il tuo comando in background o in primo piano (ad esempio, di top
solito deve essere in primo piano).
YourCommand & sleep 5m; kill $! # 4th Background
YourCommand & pid=$! ; (sleep 5m; kill $pid;) & # 5th Background
bash -c '(sleep 5m; kill $$) & exec YourCommand' # 6th Foreground
(cmdpid=$BASHPID; (sleep 5m; kill $cmdpid) & exec YourCommand) # 7th Foreground
spiegazioni
- Nella quarta versione esegui in background,
YourCommand
quindi la tua shell sleep
s per 5 minuiti. Al termine, l'ultimo processo in background ( $!
) verrà interrotto. Smetti di sgusciare.
-
Nella quinta versione invece si esegue in background
YourCommand
e si memorizza immediatamente quel PID nella variabile $pid
. Quindi esegui in background un pisolino di 5 minuti e il conseguente comando che ucciderà quel PID memorizzato. Poiché hai inviato questo gruppo di comandi in background, non fermi la shell. È necessario archiviare il PID in una variabile perché il valore di $!
può essere aggiornato da un'eventuale esecuzione di un altro programma in background. In parole semplici, si evita il rischio di uccidere il processo sbagliato o nessun processo.
- Nella sesta versione si chiama una nuova shell bash che si suiciderà in 5 minuti tramite
$$
, quindi viene eseguito il comando che rimane in primo piano.
- Nella 7a versione viene invocata una subshell
()
che memorizza il suo PID in una variabile ( cmdpid
) e si uccide con un'altra subshell inviata nell'esecuzione in background, quindi esegue YourCommand in primo piano.
Ovviamente in ogni versione è possibile inviare il segnale di interruzione necessario, da quello predefinito all'estremo kill -9
, da utilizzare solo quando realmente necessario.
Riferimenti
- [ 1 ] The Coreutils
- [ 2 ] La guida per principianti di Bash
- [ 3 ] BashFAQ