Comment rediriger la sortie de la commande time vers un fichier sous Linux?

202

Juste une petite question sur le timing des programmes sous Linux: la commande time permet de mesurer le temps d'exécution d'un programme:

[ed@lbox200 ~]$ time sleep 1

real    0m1.004s
user    0m0.000s
sys     0m0.004s

Ce qui fonctionne bien. Mais si j'essaie de rediriger la sortie vers un fichier, il échoue.

[ed@lbox200 ~]$ time sleep 1 > time.txt

real    0m1.004s
user    0m0.001s
sys     0m0.004s

[ed@lbox200 ~]$ cat time.txt 
[ed@lbox200 ~]$ 

Je sais qu'il existe d'autres implémentations de temps avec l'option -o pour écrire un fichier mais ma question concerne la commande sans ces options.

Aucune suggestion ?

ed82
la source
3
Duplication possible du script bash d'écriture du temps d'exécution dans un fichier , et je suis loin d'être convaincu que c'est la première de ces questions.
Jonathan Leffler
1
Ceci est un doublon de stackoverflow.com/questions/2408981/…
codeforester

Réponses:

267

Essayer

{ time sleep 1 ; } 2> time.txt

qui combine le STDERR de "time" et votre commande dans time.txt

Ou utiliser

{ time sleep 1 2> sleep.stderr ; } 2> time.txt

qui place STDERR de "sleep" dans le fichier "sleep.stderr" et seul STDERR de "time" va dans "time.txt"

janvier
la source
2
Merci, cela répond précisément à ma question. Si j'ai bien compris, le résultat de la commande time peut être obtenu auprès de stderr?
ed82
7
Oui, mais vous devez le mettre entre accolades, sinon la redirection fera partie de la commande qui timeévalue.
Janvier
5
@Daniel Vous pouvez toujours rediriger la sortie de la commande interne séparément (ie {time sleep 1 2> sleepStdErr.txt;} 2> time.txt) et cela ne vous donnera que la sortie de temps. Je ne sais pas s'il y a moyen de l'obtenir indépendamment autrement.
gms7777
10
Si vous voulez utiliser le temps avec quelque chose comme grep qui lit stdout, essayez { time sleep 1; } 2>&1 | grep real. Cela envoie stderr à stdout que grep peut ensuite lire.
clayzermk1
9
N'OUBLIEZ PAS le ';' avant de fermer '}', cela ne fonctionnera PAS sans (je l'ai fait, et ... je me demande pourquoi ne fonctionne pas :))
THESorcerer
38

Wrap timeet la commande que vous chronométrez dans un ensemble de crochets.

Par exemple, les temps suivants lset écrit le résultat lset les résultats du chronométrage dans outfile:

$ (time ls) > outfile 2>&1

Ou, si vous souhaitez séparer la sortie de la commande de la sortie capturée de time:

$ (time ls) > ls_results 2> time_results
sampson-chen
la source
12
Il n'est pas nécessaire d'introduire un sous-shell ici.
Janvier
1
@ sampson-chen Cela ne fonctionne que parce que ls n'écrit rien à stderr non? Comment «sépareriez-vous» la sortie de «time» de celle de la commande à exécuter si la commande écrit à la fois sur stdout et stderr?
David Doria
36

Facile. L' timeutilitaire GNU a une option pour cela.

Mais vous devez vous assurer que vous n'utilisez pas la timecommande intégrée de votre shell , au moins la commande bashintégrée ne fournit pas cette option! C'est pourquoi vous devez donner le chemin complet de l' timeutilitaire:

/usr/bin/time -o time.txt sleep 1
cmaster - réintégrer monica
la source
Vous pouvez également utiliser le non-intégré sans spécifier le chemin complet: stackoverflow.com/questions/29540540/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
14

Si vous vous souciez de la sortie d'erreur de la commande, vous pouvez les séparer comme ceci tout en utilisant la commande de temps intégrée.

{ time your_command 2> command.err ; } 2> time.log

ou

{ time your_command 2>1 ; } 2> time.log

Comme vous voyez les erreurs de la commande, allez dans un fichier (puisque stderrest utilisé pourtime ).

Malheureusement, vous ne pouvez pas l'envoyer à une autre poignée (comme 3>&2) car cela n'existera plus en dehors du{...}

Cela dit, si vous pouvez utiliser le temps GNU, faites simplement ce que @Tim Ludwinski a dit.

\time -o time.log command
marque
la source
8

Étant donné que la sortie de la commande «time» est une sortie d'erreur, la rediriger en tant que sortie standard serait plus intuitive pour effectuer un traitement supplémentaire.

{ time sleep 1; } 2>&1 |  cat > time.txt
jaycee xu
la source
6

Si vous utilisez l'heure GNU au lieu du bash intégré, essayez

time -o outfile command

(Remarque: les formats d'heure GNU sont un peu différents de ceux de bash intégré).

Tim Ludwinski
la source
1
Merci. Et vous pouvez utiliser \time -o outfile command(avec ``) pour utiliser GNU au lieu de intégré.
Mark
3
&>out time command >/dev/null

dans ton cas

&>out time sleep 1 >/dev/null

puis

cat out
alinsoar
la source
3
Idée élégante, mais conduit le shell à ne pas utiliser sa commande intégrée. Si vous n'avez pas de véritable timebinaire installé, outcontiendra quelque chose comme bash: time: command not found.
scy
De plus, le format de l'heure GNU n'est pas le même que celui de bash, ce qui pose des problèmes pour l'analyse automatique.
Guss
3

J'ai fini par utiliser:

/usr/bin/time -ao output_file.txt -f "Operation took: %E" echo lol
  • Où "a" est ajouté
  • Où "o" est suivi du nom de fichier à ajouter à
  • Où "f" est un format avec une syntaxe semblable à printf
  • Où "% E" produit 0:00:00; heures: minutes: secondes
  • J'ai dû invoquer / usr / bin / time car le "time" bash le piétinait et n'a pas les mêmes options
  • J'essayais juste d'obtenir la sortie dans un fichier, pas la même chose que OP
Locane
la source
2
#!/bin/bash

set -e

_onexit() {
    [[ $TMPD ]] && rm -rf "$TMPD"
}

TMPD="$(mktemp -d)"
trap _onexit EXIT

_time_2() {
    "$@" 2>&3
}

_time_1() {
    time _time_2 "$@"
}

_time() {
    declare time_label="$1"
    shift
    exec 3>&2
    _time_1 "$@" 2>"$TMPD/timing.$time_label"
    echo "time[$time_label]"
    cat "$TMPD/timing.$time_label"
}

_time a _do_something
_time b _do_another_thing
_time c _finish_up

Cela a l'avantage de ne pas engendrer de sous-coquilles, et le pipeline final a son stderr restauré au vrai stderr.

Adam Heath
la source
0

Si vous ne voulez pas toucher les stdout et stderr du processus d'origine, vous pouvez rediriger stderr vers le descripteur de fichier 3 et inversement:

$ { time { perl -le "print 'foo'; warn 'bar';" 2>&3; }; } 3>&2 2> time.out
foo
bar at -e line 1.
$ cat time.out

real    0m0.009s
user    0m0.004s
sys     0m0.000s

Vous pouvez l'utiliser pour un wrapper (par exemple pour les cronjobs) pour surveiller les temps d'exécution:

#!/bin/bash

echo "[$(date)]" "$@" >> /my/runtime.log

{ time { "$@" 2>&3; }; } 3>&2 2>> /my/runtime.log
Tobias Gödderz
la source
0

Si vous utilisez, cshvous pouvez utiliser:

/usr/bin/time --output=outfile -p $SHELL  -c 'your command'

Par exemple:

/usr/bin/time --output=outtime.txt -p csh -c 'cat file'
Leo Cardona
la source