Redireccionar la salida de un comando en `time command`

11

Estoy tratando de cronometrar algo usando:

/usr/bin/time myCommand

Sin embargo, dado que /usr/bin/timeescribe en stderr, si myCommand también escribe en stderr, obtendré más que solo la salida del tiempo en la transmisión. Lo que quiero hacer es redirigir toda la salida de myCommand /dev/null, pero aún así escribir la salida del tiempo en stderr. Usando un ejemplo de myCommand que escribe en stderr of ls /nofile, vemos que (obviamente) no hay salida en absoluto con lo siguiente:

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

Sin ninguna redirección, vemos tanto la salida de ls(a stderr) como la salida de tiempo (también a 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

Lo que quiero es algo que simplemente produce:

$ /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

¿Algunas ideas?

David Doria
fuente
Estoy usando el comando de tiempo en el archivo de script. Quiero salida de tiempo en stdout en lugar de stderr. ¿Cómo puedo conseguir esto?
relacionado: stackoverflow.com/questions/13356628/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Respuestas:

20

En ksh, bash y zsh, timees una palabra clave, no una incorporada. Las redirecciones en la misma línea se aplican solo al comando que se está cronometrando, no a la salida de timesí mismo.

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

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

Para redirigir la salida de timesí mismo en estos shells, debe usar un nivel adicional de agrupación.

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

Si usa la versión GNU de la timeutilidad independiente , tiene una -oopción para escribir la salida de timeotro lugar que no sea stderr. Puedes hacer timeescribir en la terminal:

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

Si desea mantener la salida de timesu error estándar, necesita un nivel adicional de barajado de descriptores de archivo.

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

Con cualquier timeutilidad, puede invocar un shell intermedio para realizar las redirecciones deseadas. Invocar un shell intermedio para realizar acciones adicionales como cdredirecciones, etc. es bastante común: es el tipo de pequeñas cosas para las que están diseñados los shells.

/usr/bin/time sh -c 'exec mycommand >/dev/null 2>/dev/null'
Gilles 'SO- deja de ser malvado'
fuente
Un par de seguimientos: 1) ¿Qué hace el 'ejecutivo' en su última sugerencia? Parece funcionar sin él: / usr / bin / time sh -c 'exec ls / nofile &> ./ output.dat' 2) Es un "shell intermedio" igual que un "subshell" (que obtendría I piensa usando paréntesis? Había estado intentando cosas como / usr / bin / time (ls / nofile &> ./ output.dat) en vano. 3) ¿Qué es / dev / tty? Sé que tty0 es stdin, tty1 = stdout, tty2 = stderr, pero ¿qué pasa con 'tty'?
David Doria el
4) Con la opción / dev / fd3, parece que está diciendo que escriba la salida -o en 3, luego redirija 3 a 2, 1 a nulo y 2 a nulo. ¿No debería enviar 3 a nulo también ya que las redirecciones ocurren de izquierda a derecha?
David Doria el
1
@DavidDoria execreemplaza el shell por el programa especificado en lugar de ejecutar ese programa como un subproceso. Algunos shells realizan esta optimización automáticamente cuando un comando es el último en un script. "Shell intermedio" significa eso: un shell que está entre timey mycommand; no está relacionado con las subcapas. /dev/ttyes el terminal en el que se ejecuta el comando (no está relacionado con /dev/ttyNUMcuáles son las consolas físicas; estás confundiendo con los descriptores de archivo: stdin is /dev/fd/0, etc.).
Gilles 'SO- deja de ser malvado'
@DavidDoria Cambiar a qué está conectado un descriptor de archivo ocurre de izquierda a derecha, lo que tiene el efecto contrario. Ver unix.stackexchange.com/questions/23964/… o unix.stackexchange.com/questions/37660/order-of-redirections
Gilles 'SO- deja de ser malvado'
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
fuente
Ese no es el mismo 'tiempo' (creo que es un alias bash). Tenga en cuenta que no sigue ninguna regla de redireccionamiento sensata? $ time &> / dev / null real 0m0.000s usuario 0m0.000s sys 0m0.000s
David Doria
1
¿Qué tal esto: / usr / bin / time -o time / usr / bin / find / etc / pki / CA / private / &> / dev / null; hora del gato
Artur Szymczak
Sí, he visto eso, pero tenía más curiosidad acerca de cómo hacerlo sin usar un mecanismo interno como -o.
David Doria el
@DavidDoria ¿Qué te da la impresión de que timees un alias bash? which timese muestra /usr/bin/timeen CentOS 5.7.
Timothy Martin el
type timete mostrará:time is a shell keyword
Artur Szymczak