Come limitare il tempo di esecuzione di un programma in Linux?


10

Ho diverse simulazioni da fare, ognuna delle quali viene invocata python simulate.py <parameter list>. Il problema con queste simulazioni è che alcuni di essi si bloccano senza uscire, il che mi impedisce di eseguirli in batch con un semplice script.

Ciò di cui avrei bisogno, è una qualche forma di comando "run-time-limiting", che ucciderebbe automaticamente il processo (preferibilmente premendo virtualmente Ctrl + C , ma penso che anche la semplice uccisione lo farà) dopo un tempo specificato, se il processo non è terminato con grazia da solo.

Certo che posso scrivere script di me stesso, ma ho il sospetto che qualcuno ha già fatto prima di me, quindi non è necessario reinventare la ruota passare ore con ps, timee manuali bash.

Risposte:


15

Soluzione potenziale n. 1

Usa il timeoutcomando:

$ date
Mon May  6 07:35:07 EDT 2013
$ timeout 5 sleep 100
$ date
Mon May  6 07:35:14 EDT 2013

Puoi anche inserire una guardia nel timeoutcomando se killil processo non si è fermato dopo un certo periodo di tempo.

$ date
Mon May  6 07:40:40 EDT 2013
$ timeout -k 20 5 sleep 100
$ date
Mon May  6 07:40:48 EDT 2013

Questo attenderà fino a 20 secondi dopo l'interruzione del processo sleep 100, se è ancora in esecuzione, quindi timeoutinvierà un killsegnale.

Soluzione potenziale n. 2

Un modo alternativo, sebbene un metodo più rischioso sarebbe il seguente:

./myProgram &
sleep 1
kill $! 2>/dev/null && echo "myProgram didn't finish"

Ho trovato questa tecnica su Stack Overflow in una domanda intitolata: Limitare il tempo di esecuzione di un programma su Linux . Nello specifico questa risposta .

NOTA: per un commento lasciato da @mattdm il metodo sopra può essere rischioso dato che presuppone che non siano stati avviati nuovi processi da quando il processo è stato avviato. Quindi non sono stati assegnati nuovi PID. Detto questo, questo approccio probabilmente non dovrebbe essere usato, ma è qui solo come riferimento per un approccio generale al problema. Il timeoutmetodo è l'opzione migliore del 2.


Ma poi sarà garantito che lo script richiederà sempre tutto quel tempo. Nel mio caso non è 1 secondo, ma piuttosto 15 minuti.
Adam Ryczkowski

Ma l'altra soluzione trovata in quella domanda dovrebbe essere proprio quello di cui ho bisogno. Grazie!
Adam Ryczkowski

2
Supponiamo che termini myProgram in meno tempo di sleep(non un presupposto irragionevole poiché l'obiettivo è impostare un tempo di esecuzione massimo consentito). Quindi si invia un segnale a un PID inesistente (nessun danno reale fatto) o a qualsiasi processo casuale sul sistema (potenzialmente fatale).
un CVn

1
@ MichaelKjörling, grazie per il rimborso. Ho aggiornato la mia risposta con lo stesso commento lasciato dall'OP. Sembra che il timeoutcomando faccia esattamente quello che sta cercando, aspettando che l'OP risponda ai miei commenti.
slm

@slm timeoutdovrebbe essere la soluzione di cui ho bisogno. Al momento lo sto testando
Adam Ryczkowski

4

Ho trovato qualcosa di un po 'meglio, di timeout: timelimit.

Ha diversi vantaggi; uno è che l'utente può interrompere manualmente l'esecuzione premendo "Ctrl + C".

Il timelimitprogramma è disponibile nel repository Debian.


1
Cercare di comprendere le differenze tra timelimit e timeout. il timeout può essere arrestato con un Ctrl + C. Quali sono gli altri vantaggi?
slm

Bene, il mio timeout non può. Uso Mint 14 (basato su Ubuntu Quantal).
Adam Ryczkowski

3

Puoi sintonizzare il tempo della CPU e altre cose ulimit, in particolare per il tempo della CPU:

$ ulimit -t 60      # limit to 60 seconds
$ program

Consulta le Domande e risposte su U&L: unix.stackexchange.com/a/4666/7453 . @Gilles offre una buona panoramica dell'uso di ulimit a questo scopo.
slm

0

Bash utilizza una variabile chiamata $BASHPIDche può essere utilizzata in tale situazione, ad esempio:

#!/bin/bash
do_face() {
    local parent=$1
    echo $BASHPID > pid
    sleep 10
    echo "Killing parent $parent"
    kill $parent
}

ME=$BASHPID
eval $(echo "do_face $ME &")
sleep 20 && kill $(cat pid) && echo "killed child $(cat pid)"
exit 1

È possibile modificare l'argomento nella chiamata a sleepin do_face()al 100posto di 10e vedere cosa succede quando il bambino richiede troppo tempo per fare le sue faccende. Basta cambiare la chiamata per dormire in do_face()una chiamata al tuo eseguibile e se impiega troppo tempo lo script la ucciderà, 20secondi è il valore limite in questo esempio. I parametri possono essere implementati in modo che questo diventi un semplice script da chiamare e possa essere chiamato da un altro script in batch o altro. La gestione dei file pid per ogni processo simultaneo è un problema che dovrà essere gestito, forse usare diverse directory secondarie ...

NB: Su GNU Linux sleeppuò accettare argomenti in virgola mobile come sleep 0.1dormire per un decimo di secondo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.