Afin de savoir combien de temps prennent certaines opérations dans un script Bash (v4 +), j'aimerais analyser le résultat de la time
commande "séparément" et (au final) le capturer dans une variable Bash ( let VARNAME=...
).
Maintenant, j'utilise time -f '%e' ...
(ou plutôt à command time -f '%e' ...
cause de Bash intégré), mais comme je redirige déjà la sortie de la commande exécutée, je suis vraiment perdu quant à la manière dont je voudrais capturer la sortie de la time
commande. En gros, le problème est de séparer la sortie de time
la sortie de la ou des commandes exécutées.
Ce que je veux, c'est la fonctionnalité qui consiste à compter le temps en secondes (entiers) entre le lancement d'une commande et son achèvement. Il n'est pas nécessaire que ce soit la time
commande ou l'intégré respectif.
Edit: étant donné les deux réponses utiles ci-dessous, je voulais ajouter deux clarifications.
- Je ne veux pas jeter la sortie de la commande exécutée, mais peu importe si elle se termine sur stdout ou stderr.
- Je préférerais une approche directe à une approche indirecte (c.-à-d. Capturer la sortie directement plutôt que de la stocker dans des fichiers intermédiaires).
La solution en utilisant date
jusqu'ici vient fermer à ce que je veux.
la source
fork()
,execvp()
etwait3()/wait4()
. C'est finalement ce que font le temps et les amis. Je ne suis pas au courant d'une manière simple de le faire dans bash / perl sans rediriger vers un fichier ou une approche similaire.Réponses:
Pour obtenir le résultat de
time
dans une variable, utilisez ce qui suit:Vous pouvez également simplement demander un type d'heure unique, par exemple utime:
Pour obtenir le temps que vous pouvez également utiliser
date +%s.%N
, prenez-le donc avant et après l'exécution et calculez le diff:la source
DIFF=$((END-START))
, utilisant les expressions arithmétiques. :) ... Merci d'avoir répondu. +1.%N
dans le code de binfalse), vous avez besoin debc
calculs plus élaborés.time (cmd) 2> something
redirection vers la sortie de chronométrage soit efficacefile
, elle n’est pas censée (conformément à la documentation), pas dans les autres shells oùtime
un mot clé est considéré et qui pourrait être considéré comme un bogue . Je ne m'appuierais pas dessus car cela pourrait ne pas fonctionner dans les futures versions debash
.Sous bash, la sortie de la
time
construction va à son erreur standard et vous pouvez rediriger l'erreur standard du pipeline qu'elle affecte. Alors commençons par une commande qui écrit à sa sortie et erreur streamas:sh -c 'echo out; echo 1>&2 err'
. Afin de ne pas confondre le flux d'erreur de la commande avec le résultattime
, nous pouvons temporairement renvoyer le flux d'erreur de la commande vers un autre descripteur de fichier:Cela écrit
out
à jour 1,err
à jour 3 et les temps à jour 2:Il serait plus agréable d’avoir
err
le deuxième et l’heure du troisième, nous les échangeons, ce qui est fastidieux car il n’ya pas de moyen direct d’échanger deux descripteurs de fichier:Cela montre comment vous pouvez post-traiter le résultat de la commande, mais si vous souhaitez capturer à la fois le résultat de la commande et son heure, vous devez travailler plus fort. L'utilisation d'un fichier temporaire est une solution. En fait, c'est la seule solution fiable si vous devez capturer à la fois l'erreur standard de la commande et sa sortie standard. Mais sinon, vous pouvez capturer toute la sortie et tirer parti du fait que
time
son format est prévisible (si vous utiliseztime -p
pour obtenir le format POSIX ou laTIMEFORMAT
variable spécifique à bash ).Si vous ne vous souciez que de l'heure de l'horloge murale, exécuter
date
avant et après est une solution simple (si elle est légèrement plus imprécise en raison du temps supplémentaire passé à charger la commande externe).la source
Avec le temps, la sortie de la commande sort sur stdout et le temps sur stderr. Donc, pour les séparer, vous pouvez faire:
Mais, maintenant le temps est dans un fichier. Je ne pense pas que Bash puisse mettre stderr dans une variable directement. Si cela ne vous dérange pas de rediriger la sortie de la commande quelque part, vous pouvez faire:
Lorsque vous effectuez cette opération, le résultat de la commande sera
outputfile
entré et le temps qu’il aura fallu pour s’exécuter sera également$FOO
.la source
time
stderr était écrit, mais je ne savais pas que cela fusionnerait stdout et stderr de la commande exécutée dans sa stdout. Mais généralement, il n’existe pas de méthode directe (sans fichier intermédiaire)? +1time
ne fusionne pas les commandesstdout
etstderr
. La façon dont j'ai montré suppose que vous n'aviez besoin que de la sortie stdout de la commande. Comme vousbash
ne stockez que ce qui sortstdout
, vous devez rediriger. Dans le cas où vous pouvez supprimer en toute sécurité le stderr de votre commande: l'heure sera toujours sur la dernière ligne de stderr. Si vous avez besoin des deux flux de sortie de votre commande, je vous suggère de l'envelopper dans un autre script.Si vous êtes
bash
(et passh
) et que vous n'avez PAS besoin d'une précision inférieure à la seconde, vous pouvez ignorer l'appeldate
et le faire entièrement sans générer de processus supplémentaires, sans avoir à séparer la sortie combinée, ni à capturer et à analyser la sortie. à partir de toutes commandes:la source
A cette fin , il est probablement préférable d'utiliser
times
(quetime
) dansbash
lequel imprime les durées cumulées utilisateur et système pour le shell et les processus lancés à partir du shell, utilisez exemple:Voir:
help -m times
pour plus d'informations.la source
Dans la synthèse de toutes les réponses précédentes, lorsque sous OSX
tu peux faire comme
la source
Installer
/bin/time
(par exemplepacman -S time
)Donc au lieu d'erreur en essayant
-f
flag:Vous pouvez réellement l'utiliser:
Et obtenez ce que vous voulez - temps en variable (exemple d'utilisation
%e
pour le temps écoulé réel, pour vérifier les autres optionsman time
):la source
/usr/bin/time
sur de nombreux systèmestime
est un shell intégré à Bash (et probablement à d’autres shell), mais tant que le chemin de l’time
exécutable est activéPATH
, nous pouvonscommand time
nous assurer que nous exécutons la commande external et non l’intégré.Juste comme un avertissement lorsque vous travaillez avec les déclarations ci-dessus et en prenant particulièrement en compte la réponse de Grzegorz. J'ai été surpris de voir sur mon système Ubuntu 16.04 Xenial ces deux résultats:
Je n'ai pas de pseudonymes définis et je ne sais donc pas pourquoi cela se produit.
la source
time
est aussi un shell intégré.command
, si vous voulez vous assurer que vous exécutez la commande intégrée, utilisezbuiltin
. Il n'y a pas de magie ici. Permethelp
de déterminer les commandes disponibles outype <command>
de déterminer le type<command>
(par exemple, une commande interne, une commande externe, une fonction ou un alias).command
commande. C’est ce qui garantit que / usr / bin / time est appelé. Cela signifie que les deux déclarations suivantes sont compatibles:$ command time -f %e sleep 4
et$ /usr/bin/time -f %e sleep
essayez ceci, il exécute une commande simple avec des arguments et met les temps $ real $ user $ sys et préserve le code de sortie.
De plus, il ne crée pas de sous-shell et ne piétine aucune variable, à l'exception du système utilisateur réel, et n'interfère pas avec l'exécution du script.
par exemple
remarque: il ne fait que multiplier la commande simple par un pipeline, dont les composants sont exécutés dans un sous-shell
Cette version vous permet de spécifier comme $ 1 le nom des variables devant recevoir les 3 fois:
par exemple
et peut être utile si elle est appelée récursivement pour éviter de piétiner les temps; mais alors rus etc. devraient être déclarés locaux dans leur utilisation.
http://blog.sam.liddicott.com/2016/01/timeing-bash-commands.html
la source