Commande Timeout sur Mac OS X?

90

Existe-t-il une alternative à la commande timeout sur Mac OSx. L'exigence de base est que je suis capable d'exécuter une commande pendant une durée spécifiée.

par exemple:

timeout 10 ping google.com

Ce programme exécute un ping pendant 10 secondes sous Linux.

sheki
la source
Voir aussi unix.stackexchange.com/questions/43340/…
Joshua Goldberg

Réponses:

134

Vous pouvez utiliser

brew install coreutils

Et puis chaque fois que vous avez besoin de délai, utilisez

gtimeout

..au lieu. Pour expliquer pourquoi, voici un extrait de la section Homebrew Caveats:

Mises en garde

Toutes les commandes ont été installées avec le préfixe «g».

Si vous avez vraiment besoin d'utiliser ces commandes avec leurs noms normaux, vous pouvez ajouter un répertoire "gnubin" à votre PATH depuis votre bashrc comme:

PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"

De plus, vous pouvez accéder à leurs pages de manuel avec des noms normaux si vous ajoutez également le répertoire "gnuman" à votre MANPATH depuis votre bashrc:

MANPATH="/usr/local/opt/coreutils/libexec/gnuman:$MANPATH"
kvz
la source
21
Puis: alias timeout = gtimeout
nkadwa
1
Ou ln -s /usr/local/bin/gtimeout /usr/local/bin/timeoutpour simplement activer la commande one (la solution d'alias fonctionne pour une utilisation CLI interactive, mais pas lorsqu'elle est appelée à partir de scripts bash).
John Y
1
De mon côté, après avoir installé coerutils, j'ai eu timeout disponible comme timeout: ln -s / usr / local / bin / gtimeout / usr / local / bin / timeout ln: / usr / local / bin / timeout: Le fichier existe
talsibony
Mise à jour: je viens d'installer coreutils en utilisant brew install coreutils, et la timeoutcommande était disponible sans le préfixe.
tdensmore
24

Une autre approche simple qui fonctionne à peu près multiplateforme (car elle utilise perl qui est presque partout) est la suivante:

function timeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }

Accroché d'ici: https://gist.github.com/jaytaylor/6527607

Au lieu de le mettre dans une fonction, vous pouvez simplement mettre la ligne suivante dans un script, et cela fonctionnera aussi:

timeout.sh

perl -e 'alarm shift; exec @ARGV' "$@";

ou une version avec aide / exemples intégrés:

timeout.sh

#!/usr/bin/env bash

function show_help()
{
  IT=$(cat <<EOF

Runs a command, and times out if it doesnt complete in time

Example usage:
 
   # Will fail after 1 second, and shows non zero exit code result
   $ timeout 1 "sleep 2" 2> /dev/null ; echo \$?
   142

   # Will succeed, and return exit code of 0.
   $ timeout 1 sleep 0.5; echo \$?
   0

   $ timeout 1 bash -c 'echo "hi" && sleep 2 && echo "bye"' 2> /dev/null; echo \$?
   hi
   142

   $ timeout 3 bash -c 'echo "hi" && sleep 2 && echo "bye"' 2> /dev/null; echo \$?
   hi
   bye
   0
EOF
)
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

#
# Mac OS-X does not come with the delightfully useful `timeout` program.  Thankfully a rough BASH equivalent can be achieved with only 2 perl statements.
#
# Originally found on SO: http://stackoverflow.com/questions/601543/command-line-command-to-auto-kill-a-command-after-a-certain-amount-of-time
# 
perl -e 'alarm shift; exec @ARGV' "$@";
Brad Parks
la source
À quoi cela ressemble-t-il de l'utiliser directement, sans l'envelopper dans une fonction?
mwfearnley
c'est à peu près juste supprimer la fonction et laisser la ligne perl ... Je mets plus de détails ci-dessus!
Brad Parks
À quoi cela ressemble-t-il en tant que doublure à usage unique? Quelque chose comme perl -e 'alarm shift; exec "ping google.com"?
mwfearnley
Malheureusement, cela génère un Alarm clockmessage lorsque la minuterie expire, et son élimination devient compliquée .
RichVel
1
Ce serait bien d'ajouter la version ualarm lorsque vous avez besoin de plus de précision: function timeout() { perl -e 'use Time::HiRes "ualarm"; ualarm shift; exec @ARGV' "$@"; } (Notez que cela nécessite Perl> = 5.8 selon perldoc.perl.org/functions/alarm.html )
gib
6

Vous pouvez limiter le temps d'exécution de n'importe quel programme à l'aide de cette commande:

ping -t 10 google.com & sleep 5; kill $!
deadmoto
la source
9
Ce n'est probablement pas ce que vous voulez. Le résultat est que la commande s'exécutera exactement 5 secondes. Cela signifie que si vous voulez que ce soit un temps maximum mais pas aussi le minimum, ce n'est pas ce que vous recherchez
gesell
2

Le package Timeout d'Ubuntu / Debian peut être compilé sur Mac et cela fonctionne. Le package est disponible sur http://packages.ubuntu.com/lucid/timeout

sheki
la source
2
Un moyen plus simple est d'utiliser Homebrew: brew install coreutils- puis utilisez gtimeoutou définissez votre PATH pour utiliser le timeoutnom.
RichVel
1

Tu peux faire ping -t 10 google.com >nul

le> nul supprime la sortie. Donc, au lieu d'afficher 64 BYTES FROM 123.45.67.8 BLAH BLAH BLAH, il affichera simplement une nouvelle ligne vide jusqu'à ce qu'elle expire. L'indicateur -t peut être changé en n'importe quel nombre.

redCube
la source
2
Ping était vraiment un échantillon. Je veux exécuter un programme pour collecter des métriques
sheki