Comment exécuter l'heure sur plusieurs commandes ET écrire la sortie de l'heure dans un fichier?

66

Je veux exécuter la timecommande pour mesurer le temps de plusieurs commandes.

Ce que je veux faire c'est:

  • Mesurer le temps de fonctionnement de tous ajoutés
  • Écrire la timesortie dans un fichier
  • Écrivez le à STDERRpartir de la commande que je mesureSTDERR

Ce que je ne veux PAS faire est

  • Ecrivez les différentes commandes dans un script séparé (pourquoi? Parce que tout cela est déjà un script que je génère par programme, et créer un autre script temporaire serait plus compliqué que je ne le souhaiterais)

Ce que j'ai essayé jusqu'à présent:

/usr/bin/time --output=outtime -p echo "a"; echo "b";

Ne fonctionne pas, timeest exécuté uniquement sur le premier.

/usr/bin/time --output=outtime -p ( echo "a"; echo "b"; )

Ne fonctionne pas, (est un jeton inattendu.

/usr/bin/time --output=outtime -p { echo "a"; echo "b"; }

Ne fonctionne pas, "aucun fichier ou répertoire de ce type".

/usr/bin/time --output=outtime -p ' echo "a"; echo "b";'

Ne fonctionne pas, "aucun fichier ou répertoire de ce type".

time ( echo "a"; echo "b"; ) 2>outtime

Ne fonctionne pas, car il redirige tout STDERRdans outtime; Je ne veux que la timesortie là-bas.

Et bien sur

time --output=outime echo "a";

Ça ne marche pas, depuis --output=outime: command not found.

Comment puis-je le faire?

Karel Bílek
la source

Réponses:

90

Utilisez sh -c 'commands'comme commande, par exemple:

/usr/bin/time --output=outtime -p sh -c 'echo "a"; echo "b"'
Jim Paris
la source
2
une version plus courte:time -p sh -c 'echo "a"; echo "b"'
Geo
8

Essaye ça:

% (time ( { echas z; echo 2 } 2>&3 ) ) 3>&2 2>timeoutput
zsh: command not found: echas
2
% cat timeoutput                                
( { echas z; echo 2; } 2>&3; )  0.00s user 0.00s system 0% cpu 0.004 total

Explication:

Premièrement, nous devons trouver un moyen de rediriger la sortie de time. Comme timec'est un shell intégré, il faut la ligne de commande complète comme commande à mesurer, y compris les redirections. Ainsi,

% time whatever 2>timeoutput
whatever 2> timeoutput  0.00s user 0.00s system 0% cpu 0.018 total
% cat timeoutput 
zsh: command not found: whatever

[Remarque: le commentaire de janos implique que ce n'est pas le cas pour bash.] Nous pouvons réaliser la redirection de timela sortie de en exécutant timedans un sous-shell, puis en redirigeant la sortie de ce sous-shell.

% (time whatever) 2> timeoutput
% cat timeoutput 
zsh: command not found: whatever
whatever  0.00s user 0.00s system 0% cpu 0.018 total

Nous avons maintenant réussi à rediriger la sortie de time, mais sa sortie est mélangée à la sortie d'erreur de la commande que nous mesurons. Pour séparer les deux, nous utilisons un descripteur de fichier supplémentaire.

Sur le "dehors" nous avons

% (time ... ) 3>&2 2>timeout

Cela signifie que tout ce qui est écrit dans le descripteur de fichier 3 sera envoyé au même endroit. Le descripteur de fichier 2 (erreur standard) est en cours de sortie (le terminal). Et puis nous redirigeons l'erreur type vers le fichier timeout.

Nous avons donc maintenant: tout ce qui est écrit sur stdout et fd 3 ira au terminal, et tout ce qui est écrit sur stderr ira dans le fichier. Ce qui reste est de rediriger le stderr de la commande mesurée vers fd 3.

% (time whatever 2>&3) 3>&2 2>timeout

Maintenant, pour que le temps mesure plus d'une commande, nous devons les exécuter dans un sous-shell (autre!) (Entre parenthèses). Et pour rediriger la sortie d'erreur de tous vers Fd 3, nous devons les regrouper entre accolades.

Nous arrivons donc finalement à:

% (time ( { whatever; ls } 2>&3 ) ) 3>&2 2>timeoutput

C'est ça.

Angus
la source
Ceci est une erreur de syntaxe dans un shell POSIX. Probablement un bashisme?
josch
@ josch le shell utilisé ici est zsh.
angus
6

Pas la bonne réponse mais très liée à la question.
Obtenir des statistiques de synchronisation pour plusieurs programmes, des parenthèses combinées sont requises. Séparez les commandes avec des points-virgules.

time ( command1 ; command2 )
Martin T.
la source
1
C'est sympa. Mieux encore, utilisez && entre les commandes, comme si de time ( command1 && command2 )manière que la première commande échoue; il ne procédera pas à l'exécution de l'autre.
bikashg