Commande en ligne de commande à l'auto-tuer une commande après un certain laps de temps
J'aimerais tuer automatiquement une commande après un certain laps de temps. J'ai à l'esprit une interface comme ceci:
% constrain 300 ./foo args
Qui irait à l' "./foo" par "args" mais automatiquement le tuer si il est toujours en cours après 5 minutes.
Il pourrait être utile de généraliser l'idée à d'autres contraintes, telles que les autokilling un processus s'il utilise trop de mémoire.
Existe-t-il des outils qui font ça, ou quelqu'un a écrit une telle chose?
AJOUTÉ: Jonathan solution est précisément ce que j'avais dans l'esprit, et il fonctionne comme un charme sur linux, mais je ne peux pas le faire fonctionner sur Mac OSX. Je me suis débarrassé de la SIGRTMIN qui permet de compiler amende, mais le signal n'est pas envoyé dans le processus enfant. Quelqu'un sait comment faire ce travail sur Mac?
[Ajouté: Notez qu'une mise à jour est disponible à partir de Jonathan qui fonctionne sur Mac et ailleurs].
- Quel est exactement votre question?
- Oui, pour de vrai. Vous n'êtes pas à poser une question ici.
- Question semblable, certaines des réponses différentes: stackoverflow.com/questions/687948
- Lié à unix.stackexchange.com/questions/21542/...
- Double Possible de Comment tuer un processus enfant après un délai d'attente en Bash? Tout ceci demande des généralisations sur la question du corps, le délai d'attente a dominé, et je pense qu'il serait préférable de demander à une généralisation par question.
Vous devez vous connecter pour publier un commentaire.
Je suis arrivé un peu tard pour cette partie, mais je ne vois pas mon préféré truc figurant dans les réponses.
Sous *NIX, un
alarm(2)
est héritée à travers unexecve(2)
et SIGALRM est fatale par défaut. Ainsi, vous pouvez souvent simplement:ou d'installer un trivial C wrapper le faire pour vous.
Avantages un Seul PID est impliqué, et le mécanisme est simple. Vous ne tuez pas le mauvais processus si, par exemple,
./foo.sh
sorti de "trop vite" et son PID a été ré-utilisé. Vous n'avez pas besoin de plusieurs shell sous-processus en travaillant de concert, ce qui peut être fait correctement, mais est plutôt la course sur le ventre.Inconvénients Le temps limité processus ne peut pas manipuler son réveil (par exemple,
alarm(2)
,ualarm(2)
,setitimer(2)
), car cela serait susceptible d'effacer l'héritage de l'alarme. Évidemment, on ne peut bloquer ou d'ignorer SIGALRM, bien que la même chose peut être dit de SIGINT, SIGTERM, etc. pour certaines autres approches.(Très vieux, je crois), systèmes de mise en œuvre
sleep(2)
en termes dealarm(2)
, et, même aujourd'hui, certains programmeurs utilisentalarm(2)
comme un brut interne mécanisme d'expiration pour les I/O et d'autres opérations. Dans mon expérience, cependant, cette technique est applicable à la grande majorité des processus que vous souhaitez limite de temps.doalarm 7200 echo "Cool"
fonctionne parfaitement,testfun () { echo $1 } ; testfun "Cool"
fonctionne parfaitement, maisdoalarm 7200 testfun "Cool"
ne fonctionne pas. Merci pour toutes les suggestions.$?
dans le shell va encoder statut de sortie. Le Signal de la mort est$? & 127
, qui, par exemple, est de 14 sur mon système pour mort par SIGALRM. Ordinaire de sortie, le succès ou l'échec est$? >> 8
présumant pas de mort par le signal.142
(128 + 14
;14
est le numéro normalisé de laSIGALRM
signal); sinon, la commande est propre code de sortie est passé à travers.GNU Coreutils comprend la délai commande, installé par défaut sur de nombreux systèmes.
https://www.gnu.org/software/coreutils/manual/html_node/timeout-invocation.html
Regarder
free -m
pendant une minute, puis la tuer par l'envoi d'un signal TERM:brew install coreutils
et puisgtimeout
est disponible.Peut-être que je ne suis pas à comprendre la question, mais cela semble faisable directement, au moins dans bash:
Cela va de la première commande, à l'intérieur de la parenthèse, pendant cinq secondes, puis le tue. L'ensemble de l'opération s'exécute de façon synchrone, c'est à dire que vous ne serez pas en mesure d'utiliser votre shell alors qu'il est occupé attente de la lenteur de la commande. Si ce n'est pas ce que tu voulais, il devrait être possible d'ajouter un autre &.
La
$!
variable est un Bash builtin qui contient l'ID de processus de la plus récente a commencé shell interne est exécuté. Il est important de ne pas avoir l' & à l'intérieur de la parenthèse, faire de cette façon perd l'ID de processus.J'ai un programme appelé
timeout
qui ne qui écrit en C, à l'origine, en 1989, mais périodiquement mis à jour depuis.Mise à jour: ce code ne peut pas compiler sur mac os X, car SIGRTMIN n'est pas défini, et pas de délai d'attente lorsqu'il est exécuté sur MacOS X parce que la
signal()
fonction, il reprend lewait()
après l'alarme de temps - ce qui n'est pas le comportement requis. J'ai une nouvelle version detimeout.c
qui traite à la fois de ces problèmes (à l'aide desigaction()
au lieu designal()
). Comme avant, contactez-moi pour un 10K fichier tar compressé, avec le code source et une page de manuel (voir mon profil).Si vous voulez que les "officiels" code " stderr.h " et " stderr.c', contactez-moi (voir mon profil).
Il est également ulimit, qui peut être utilisé pour limiter le temps d'exécution à la disposition des sous-processus.
Limite le processus à 10 secondes de temps CPU.
À fait l'utiliser pour limiter un nouveau processus, plutôt que l'actuel processus, vous pouvez utiliser un script de lancement:
autres-commande peut être n'importe quel outil. J'ai été en cours d'exécution Java, Python, C et d'un Système de versions de différents algorithmes de tri, et la journalisation de combien de temps ils ont pris, tout en limitant les temps d'exécution de 30 secondes. Un Cacao-application en Python généré les différentes lignes de commande - y compris les arguments - et assemblés à la fois dans un fichier CSV, mais c'était vraiment juste à la bourre sur le dessus de la commande indiquée ci-dessus.
Perl un liner, juste pour le plaisir:
Cette affiche " foo " pendant dix secondes, puis expire. Remplacer '10' avec un nombre de secondes, et "oui foo' avec toute commande.
Le délai de commande de Ubuntu/Debian, lors de la compilation de la source à travailler sur le Mac. Darwin
10.4.*
http://packages.ubuntu.com/lucid/timeout
Ma variation sur le perl one-liner vous donne le statut de sortie sans coucher avec fork() et wait() et sans le risque de tuer le mauvais processus:
Fondamentalement le fork() et wait() sont cachés à l'intérieur du système(). Le SIGALRM est remis au processus parent qui tue alors lui-même et de son enfant par l'envoi d'un SIGTERM à l'ensemble du processus de groupe (-$$). Dans le cas peu probable que l'enfant quitte l'enfant et la pid obtient réutilisés avant de le tuer() se produit, ce ne sera PAS tuer le mal, car le nouveau processus avec l'ancien enfant pid ne sera pas dans le même groupe de processus de la mère perl processus.
Comme un avantage supplémentaire, le script se termine avec ce qui est probablement le bon état de sortie.
Essayez quelque chose comme:
Il a l'inconvénient que si votre processus de pid est réutilisée dans le délai, il peut tuer le mauvais processus. C'est très peu probable, mais vous pouvez commencer 20000+ processus par seconde. Ce pourrait être résolu.
- Je utiliser "délai", qui est un paquet disponible dans le dépôt debian.
http://devel.ringlet.net/sysutils/timelimit/
L'observateur tue la lenteur de la tâche après de temps donnée; le script attend pour la lenteur de la tâche et met fin à l'observateur.
Exemples:
Une légère modification de l'perl one-liner obtiendrez le statut de sortie à droite.
En gros, exit ($? >> 8) mettra en avant le statut de sortie de la sous-processus. J'ai juste choisi de 77 à la sortie de statut pour les délais d'attente.
Comment sur l'utilisation de l'attendre outil?
pur bash:
N'est-il pas un moyen de fixer une heure précise avec "à" pour ce faire?
Semble beaucoup plus simple.
Si vous ne savez pas ce que le numéro de pid va être, je suppose, il y a un moyen de lecture de scénario avec le ps aux et grep, mais vous ne savez pas comment mettre cela en œuvre.
Votre script devrait avoir lu le pid et l'affecter à une variable.
Je ne suis pas trop habile, mais suppose que c'est faisable.