En fait, c'est ce que timeout est pour :
TIMEOUT(1) User Commands TIMEOUT(1)
NAME
timeout - run a command with a time limit
SYNOPSIS
timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]
DESCRIPTION
Start COMMAND, and kill it if still running after DURATION.
[email protected]:~$ dpkg -S /usr/bin/timeout
coreutils: /usr/bin/timeout
Il existe (au moins) deux programmes qui proposent cette fonctionnalité :
NOM
timelimit— limiter efficacement le temps d'exécution absolu d'un processusSYNOPSIS
timelimit [-pq] [-S killsig] [-s warnsig] [-T killtime] [-t warntime] command [arguments ...]
et
NOM
timeout- exécuter une commande avec une limite de tempsSYNOPSIS
timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]
Ils sont conditionnés comme suit :
$ dlocate `which timeout timelimit`
timelimit: /usr/bin/timelimit
coreutils: /usr/bin/timeout
Comparaison :
/-----------------------------+------------+----------------\
| Feature | timelimit | timeout |
+=============================+============+================+
| time to run | -t time | first argument |
+-----------------------------+------------+----------------+
| terminate signal | -s signal | -s signal |
+-----------------------------+------------+----------------+
| grace period | -T time | -k time |
+-----------------------------+------------+----------------+
| kill signal | -S signal | (note 1) |
+-----------------------------+------------+----------------+
| propagate signals | -p | (note 2) |
\-----------------------------+------------+----------------/
Remarques :
timeoututilise toujoursSIGKILLcomme signal de dernier recours.timeoutn'a aucune fonctionnalité pour quitter avec un signal lorsque le programme enfant le fait.
Le statut de sortie des deux programmes diffère, mais c'est difficile à résumer clairement, donc je vous suggère de consulter vous-même les pages du manuel pour cela.
Comme timeout est installé sur plusieurs systèmes par défaut (coreutils est un package standard dans de nombreuses distributions), je vous suggère de l'utiliser à moins que vous n'ayez besoin des fonctionnalités supplémentaires fournies par timelimit .
Pur bash intégré, sans coreutils
J'ai trouvé que cette solution fonctionne en bash s'appuyant sur un intégré commande sans appeler d'exécutable externe. Cela fonctionne sur le système où finalement ne sont même pas installés les coreutils
YourCommand & read -t 300 ; kill $! # 1st version
YourCommand & read -t 300 || kill $! # 2nd version
Explications :comme d'habitude lorsque vous envoyez une commande en arrière-plan avec & , son PID est stocké dans la variable interne $! (présent dans la version moderne de dash , csh , bash , tcsh , zsh ...).
Ce qui fait vraiment la différence entre les coques, c'est la présence du intégré commande read et de l'option -t .Dans la 1ère version, si l'utilisateur ne complète pas une ligne de saisie avant le nombre de secondes spécifié, l'instruction sera terminée et un code de retour d'erreur sera généré.
La deuxième version fonctionne comme la 1ère mais vous pouvez annuler le délai de mise à mort en appuyant simplement sur enter .
En effet l'opérateur ou || exécute le kill déclaration uniquement si le read La commande se termine avec un code de retour différent de zéro, comme lorsque le délai d'attente est expiré. Si vous appuyez sur enter avant ce moment, il retournera 0 et il ne tuera pas votre commande précédente.
Solutions Coreutils
Quand coreutils sont présents sur votre système et vous n'avez pas besoin de gagner du temps et des ressources pour appeler un programme externe, timeout et sleep et sont deux moyens parfaits pour atteindre votre objectif.
timeout L'utilisation de timeout est simple.
Eventuellement vous pouvez envisager d'utiliser aussi le -k option pour envoyer un signal d'arrêt supplémentaire si le premier échoue.
timeout 5m YourCommand # 3rd version
sleep Avec sleep vous pouvez utiliser votre fantaisie ou vous inspirer. Notez que vous pouvez laisser votre commande en arrière-plan ou au premier plan (par exemple top doit généralement être au premier plan).
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
Explications
Bien sûr, dans chaque version, vous pouvez envoyer le signal d'arrêt dont vous avez besoin, du signal par défaut à l'extrême kill -9 , à n'utiliser qu'en cas de besoin.
Références
- [1] Les Coreutils
- [2] Le guide du débutant de Bash
- [3] La FAQ de Bash