Rediriger la sortie d'une commande dans `time command`

11

J'essaie de chronométrer quelque chose en utilisant:

/usr/bin/time myCommand

Cependant, depuis l' /usr/bin/timeécriture sur stderr, si myCommand écrit également sur stderr, j'obtiendrai plus qu'une simple sortie de temps sur le flux. Ce que je veux faire, c'est rediriger toute la sortie de myCommand vers /dev/null, mais toujours écrire la sortie du temps vers stderr. En utilisant un exemple myCommand qui écrit dans stderr de ls /nofile, nous voyons (évidemment) qu'il n'y a pas de sortie du tout avec ce qui suit:

$ /usr/bin/time ls /nofile 2> /dev/null
$

Sans aucune redirection, nous voyons à la fois la sortie de ls(vers stderr) et la sortie de temps (également vers stderr):

$ /usr/bin/time ls /nofile
ls: cannot access /nofile: No such file or directory
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

Ce que je veux, c'est quelque chose qui produit simplement:

$ /usr/bin/time ls /nofile > RedirectThatImAskingFor
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

Des idées?

David Doria
la source
J'utilise la commande time dans le fichier script. je veux une sortie de temps dans stdout au lieu de stderr. comment puis-je obtenir cela?
en relation: stackoverflow.com/questions/13356628/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Réponses:

20

Dans ksh, bash et zsh, timeest un mot-clé, pas un builtin. Les redirections sur la même ligne s'appliquent uniquement à la commande en cours de temporisation, pas à la sortie d' timeelle - même.

$ time ls -d / /nofile >/dev/null 2>/dev/null

real    0m0.003s
user    0m0.000s
sys     0m0.000s

Pour rediriger la sortie de timelui-même dans ces shells, vous devez utiliser un niveau supplémentaire de regroupement.

{ time mycommand 2>&3; } 3>&2 2>mycommand.time

Si vous utilisez la version GNU de l' timeutilitaire autonome , il a une -ooption pour écrire la sortie timeailleurs que stderr. Vous pouvez faire timeécrire sur le terminal:

/usr/bin/time -o /dev/tty mycommand >/dev/null 2>/dev/null

Si vous souhaitez conserver la sortie de timeson erreur standard, vous avez besoin d'un niveau supplémentaire de brassage des descripteurs de fichiers.

/usr/bin/time -o /dev/fd/3 mycommand 3>&2 >/dev/null 2>/dev/null

Avec n'importe quel timeutilitaire, vous pouvez invoquer un shell intermédiaire pour effectuer les redirections souhaitées. Invoquer un shell intermédiaire pour effectuer des actions supplémentaires telles que des cdredirections, etc. est assez courant - c'est le genre de petites choses que les shells sont conçues pour faire.

/usr/bin/time sh -c 'exec mycommand >/dev/null 2>/dev/null'
Gilles 'SO- arrête d'être méchant'
la source
Quelques suivis: 1) Que fait «l'exec» dans votre dernière suggestion? Il semble fonctionner sans lui: / usr / bin / time sh -c 'exec ls / nofile &> ./ output.dat' 2) Est un "shell intermédiaire" identique à un "sous-shell" (que vous obtiendrez I pensez à utiliser des parenthèses?). J'avais essayé des choses comme / usr / bin / time (ls / nofile &> ./ output.dat) en vain. 3) Qu'est-ce que / dev / tty? Je sais que tty0 est stdin, tty1 = stdout, tty2 = stderr, mais qu'en est-il seulement de «tty»?
David Doria
4) Avec l'option / dev / fd3, il semble que vous disiez d'écrire la sortie -o sur 3, puis de rediriger 3 sur 2, 1 sur null et 2 sur null. Cela ne devrait-il pas envoyer 3 à null également puisque les redirections se produisent de gauche à droite?
David Doria
1
@DavidDoria execremplace le shell par le programme spécifié au lieu d'exécuter ce programme en tant que sous-processus. Certains shells effectuent cette optimisation automatiquement lorsqu'une commande est la dernière d'un script. «Shell intermédiaire» signifie exactement cela: un shell qui est entre timeet mycommand; il n'est pas lié aux sous-coquilles. /dev/ttyest le terminal sur lequel la commande s'exécute (cela n'a aucun rapport avec /dev/ttyNUMles consoles physiques; vous confondez avec les descripteurs de fichiers: stdin est /dev/fd/0, etc.).
Gilles 'SO- arrête d'être méchant'
@DavidDoria Changer ce à quoi un descripteur de fichier est connecté se produit de gauche à droite, ce qui a l'effet inverse. Voir unix.stackexchange.com/questions/23964/… ou unix.stackexchange.com/questions/37660/order-of-redirections
Gilles 'SO- stop being evil'
0
[artur@asus-ux21e ~]$ find /etc/pki/CA/private/
/etc/pki/CA/private/
find: ‘/etc/pki/CA/private/’: Permission denied
[artur@asus-ux21e ~]$ time (find /etc/pki/CA/private/ &> /dev/null)

real    0m0.006s
user    0m0.001s
sys 0m0.004s
Artur Szymczak
la source
Ce n'est pas le même «temps» (c'est un alias bash je crois). Notez qu'il ne suit aucune règle de redirection sensée? $ time &> / dev / null real 0m0.000s user 0m0.000s sys 0m0.000s
David Doria
1
Que diriez-vous de ceci: / usr / bin / time -o time / usr / bin / find / etc / pki / CA / private / &> / dev / null; temps des chats
Artur Szymczak
Oui, je l'ai vu, mais j'étais plus curieux de savoir comment le faire sans utiliser un mécanisme interne comme -o.
David Doria
@DavidDoria Qu'est-ce qui vous donne l'impression qu'il times'agit d'un alias bash? which times'affiche /usr/bin/timedans CentOS 5.7.
Timothy Martin
type timevous montrera:time is a shell keyword
Artur Szymczak