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 :
timeout
utilise toujoursSIGKILL
comme signal de dernier recours.timeout
n'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