Délai d'attente d'une commande bash, sans retard inutile,
Cette réponse à Commande en ligne de commande à l'auto-tuer une commande après un certain laps de temps
propose un 1-méthode de la ligne de délai d'attente d'une commande à partir de la ligne de commande bash:
( /path/to/slow command with options ) & sleep 5 ; kill $!
Mais il est possible que d'une "longue" de la commande peut se terminer plus tôt que le délai d'attente. (Nous allons l'appeler une "typiquement au long de la course-mais-parfois-rapide de la commande", ou tlrbsf pour le plaisir.)
Donc cette chouette 1-liner approche a un couple de problèmes. Tout d'abord, le sleep
n'est pas conditionnel, ça crée une contrainte de borne inférieure sur le temps pris pour la séquence à la fin. Envisager de 30s ou 2m ou même de 5m pour le sommeil, quand le tlrbsf commande se termine en 2 secondes — est à proscrire. Deuxièmement, la kill
est inconditionnel, de sorte que cette séquence va tenter de tuer un non-processus en cours d'exécution et se plaindre.
Donc...
Est-il un moyen en attente d'une-longue-mais-parfois-rapide ("tlrbsf") commande
- a un bash de mise en œuvre (l'autre question a déjà Perl et C réponses)
- prendra fin à la plus rapprochée des deux: tlrbsf de fin de programme, ou le délai d'attente écoulé
- ne sera pas tuer les non-existant/non-processus en cours d'exécution (ou, en option: ne se plaindre sur une mauvaise tuer)
- n'a pas à être un 1-liner
- peut s'exécuter sous Cygwin ou Linux
... et, pour les points de bonus, exécute la tlrbsf de commande dans le premier plan et le tout en mode "veille" ou extra processus en arrière-plan, tels que le stdin/stdout/stderr de la tlrbsf de commande peuvent être redirigés, même que si elle avait été exécuté directement?
Si oui, merci de partager votre code. Si non, veuillez expliquer pourquoi.
J'ai passé un certain temps à essayer de pirater le susmentionnés exemple, mais je suis frapper à la limite de mon bash compétences.
- Une autre question: stackoverflow.com/questions/526782/... (mais je pense que les timeout3 réponse ici est beaucoup mieux).
- Aucune raison de ne pas utiliser la gnu
timeout
utilitaire?
Vous devez vous connecter pour publier un commentaire.
Je pense que c'est précisément ce que vous demandez:
http://www.bashcookbook.com/bashinfo/source/bash-4.0/examples/scripts/timeout3
exec
est nécessaire, car ce que ce script n'est à mettre en place pour ses propres "suicide" à l'aide de$$
un peu de temps pour obtenir à la MIP, puis il remplace lui-même avec le processus à surveiller (en préservant son PID).:
bien.Terminate
commentaires. Pour le code:bash timeout.sh -t 0 gcc helloworld.c |& tee output.txt
- je obtenir une console de chaîne, mais de toute façonTerminate
n'est pas courante output.txt mais je veux qu'il soit là.Vous êtes probablement à la recherche pour le
timeout
commande en coreutils. Puisque c'est une partie de coreutils, il est techniquement un C solution, mais c'est toujours coreutils.info timeout
pour plus de détails.Voici un exemple:
run-one
etcurl
pour le reporting.gtimeout
command
àgcommand
sur la non-Linux Os.timeout
verrue: sur certains Linux (par exemple Cents 6.7),timeout
répond comme prévu à SIGINT et SIGQUIT moins de l'exécuter à l'intérieur d'un script bash. À l'intérieur d'un script bash,timeout
en quelque sorte ignore à la fois.brew install coreutils
, et puis vous pouvez utilisergtimeout
.timeout 5m /path/to/slow/command with options
pendant 5 heures, la commande seratimeout 5h /path/to/slow/command with options
Cette solution fonctionne indépendamment de bash en mode moniteur. Vous pouvez utiliser le bon signal pour mettre fin à your_command
L'observateur tue your_command après de temps donnée; le script attend pour la lenteur de la tâche et met fin à l'observateur. Notez que
wait
ne fonctionne pas avec les processus qui sont les enfants d'un environnement différent.Exemples:
wait
renvoie le code de sortie du processus qui l'attend. Donc, si votre commande n'sortie et dans le temps imparti, mais avec une valeur non nulle alors la logique ici va se comporter comme il l'a expiré, c'est à dire imprimeryour_command interrupted
. Au lieu de cela vous pourrait lawait
sansif
et de vérifier ensuite si la$watcher
pid existe encore, si c'est le cas alors vous savez que vous n'avez pas de délai d'attente.kill
dans un cas, maispkill
dans l'autre. J'avais besoin d'utiliserpkill
pour les deux pour faire ce travail correctement. Je m'attends à ce que si vous enroulez une commande dans()
, alors vous aurez besoin d'utiliserpkill
pour le tuer. Mais peut-être qu'il fonctionne différemment s'il n'existe qu'une seule commande à l'intérieur de la()
.Là vous allez:
vous pouvez changer le
SIGINT
et10
que vous le désirez 😉Je préfère l'expression "délai", qui a un forfait à moins de debian.
http://devel.ringlet.net/sysutils/timelimit/
C'est un peu plus agréable que la coreutils "timeout", parce que l'impression de quelque chose quand tuer le processus, et il envoie également SIGKILL après un certain temps par défaut.
timelimit -t1 ./a_forking_prog
tuer l'un des deux seulement), mais délai d'attente de travaux.Vous pouvez le faire entièrement avec
bash 4.3
et ci-dessus:_timeout 5 longrunning_command args
{ _timeout 5 producer || echo KABOOM $?; } | consumer
producer | { _timeout 5 consumer1; consumer2; }
Exemple:
{ while date; do sleep .3; done; } | _timeout 5 cat | less
Besoins Bash 4.3 pour
wait -n
Si vous n'avez pas besoin du code de retour, cela peut être encore plus simple:
Notes:
Strictement parlant, vous n'avez pas besoin de la
;
dans; )
, mais il rend la chose plus conforme à la; }
cas. Et leset +b
probablement peut être laissé à l'écart, trop, mais mieux vaut prévenir que guérir.Sauf pour
--forground
(probablement), vous pouvez mettre en œuvre toutes les variantestimeout
prend en charge.--preserve-status
est un peu difficile, cependant. Ceci est laissé comme exercice pour le lecteur 😉Cette recette peut être utilisée de façon "naturelle" dans le shell (aussi naturel que pour
flock fd
):Cependant, comme expliqué ci-dessus, vous ne pouvez pas re-exporter les variables d'environnement dans l'affichage de la coquille de cette façon, naturellement.
Edit:
L'exemple du monde réel: le Temps
__git_ps1
dans le cas où il prend trop de temps (pour des choses comme la lente SSHFS-Liens):Edit2: Correction De Bugs. J'ai remarqué que
exit 137
n'est pas nécessaire et rend_timeout
peu fiable dans le même temps.Edit3:
git
est un die-hard, donc il a besoin d'un double-truc fonctionne de manière satisfaisante.Edit4: Oublié un
_
dans la première_timeout
pour le monde réel GIT exemple.wait -n
était la fête magique dont j'avais besoin. Belle écriture.cc. The 'wait' builtin has a new '-n' option to wait for the next child to change status.
À partir de: tiswww.case.edu/php/chet/bash/NEWSVoir aussi la http://www.pixelbeat.org/scripts/timeout script de la fonctionnalité de ce qui a été intégrée dans le plus récent coreutils
délai est probablement la première approche pour essayer. Vous pouvez avoir besoin d'une notification ou d'une autre commande à exécuter si elle arrive à expiration. Après un peu de recherche et à l'expérimentation, je suis venu avec cette bash script:
Un peu hacky, mais il fonctionne. Ne fonctionne pas si vous avez d'autres processus de premier plan (merci de m'aider à résoudre ce!)
En fait, je pense que vous pouvez l'inverser, de rencontrer votre "bonus" critères:
Simple script avec le code de la clarté. Enregistrer pour
/usr/local/bin/run
:Fois sur une commande qui s'exécute trop long:
Se termine immédiatement pour une commande complète:
Le temps de temporisation de la
slowcommand
après 1 seconde:timeout 1 slowcommand || echo "I failed, perhaps due to time out"
Si vous connaissez déjà le nom du programme (supposons
program
) à la fin après le délai d'attente (à titre d'exemple3
secondes), je peux contribuer un simple et un peu sale solution alternative:Cela fonctionne parfaitement si je l'appelle indice de référence des processus avec des appels système.
argv[0]
, peut-être avec d'autres hacks pour faire plus de place).(sleep 3 && docker stop <container>) &
travaillent bien. Merci!{ sleep 5 && kill -9 $(ps -fe | grep "program" | grep $$ | tr -s " " | cut -d" " -f2); } & SLEEPPID=$!; bash -c "program" && kill -9 $SLEEPPID"
de Cette façon, il va tuer des seuls emplois dans le shell courant.Il y a aussi
cratimeout
par Martin Cracauer (écrit en C pour les systèmes Unix et Linux).OS X ne pas utiliser bash 4 pourtant, ni l' /usr/bin/délai d'attente, donc voici une fonction qui fonctionne sur OS X sans home-brew ou macports, qui est similaire à /usr/bin/timeout (basé sur Tino de réponse). Paramètre de validation, d'aide, d'utilisation et de support pour les autres signaux sont un exercice pour le lecteur.
J'ai été présenté avec un problème de préserver la coquille contexte et de permettre les délais d'attente, le seul problème c'est qu'il va arrêter l'exécution du script sur le délai d'attente - mais c'est bien avec les besoins, j'ai été présenté:
avec les sorties:
bien sûr, je suppose, il y avait un dir appelé
scripts
Mon problème était peut-être un peu différent : j'ai lancer une commande via ssh sur une machine distante et veulent tuer le shell et les childs si la commande se bloque.
J'utilise désormais le suivant :
De cette façon, la commande retourne 255 lorsqu'il y a un délai d'attente ou de la code_retour de la commande en cas de succès
Veuillez noter que la mise à mort des processus à partir d'une session ssh est gérée différents à partir d'un shell interactif. Mais vous pouvez aussi utiliser l'option-t pour ssh pour allouer un pseudo terminal, de sorte qu'il agit comme un shell interactif
Ici est une version qui ne dépend pas de la ponte d'un processus enfant - j'ai besoin d'un script autonome qui intégré cette fonctionnalité. Il le fait aussi d'une fraction de l'intervalle d'interrogation, de sorte que vous pouvez interroger plus rapide. délai d'attente aurait été préféré - mais je suis bloqué sur un ancien serveur
Bâtiment sur @loup répondre...
Si vous voulez délai d'un processus et de réduire au silence le tuer d'emploi/de sortie du pid, exécutez:
Cela met le backgrounded processus dans un shell interne est exécuté de sorte que vous ne voyez pas la sortie de l'emploi.
J'ai une tâche cron qui appelle un script php et, quelques fois, il reste bloqué sur un script php. Cette solution a été parfait pour moi.
J'utilise:
Dans 99% des cas, la réponse n'est PAS à mettre en œuvre tout délai d'attente de la logique. Délai d'attente logique est dans presque toutes les situations rouge, signe d'avertissement que quelque chose d'autre est mauvais et doit être fixé au lieu.
Est votre processus de pendaison ou de rupture après n secondes, parfois? Puis de trouver le pourquoi et le fixer à la place.
Comme un de côté, pour ne strager la solution de droit, vous devez utiliser wait "$SPID" au lieu de fg 1, puisque dans les scripts que vous n'avez pas de contrôle sur leur travail (et d'essayer de l'allumer est stupide). En outre, fg, 1 repose sur le fait que vous n'avez pas à démarrer tous les autres travaux déjà dans le script qui est une mauvaise hypothèse à faire.
Une façon très simpliste:
avec pkill (option -f), vous pouvez tuer votre commande avec des arguments ou indiquez-n pour éviter de tuer l'ancien processus.