Tengo un script de configuración para un cuadro Vagrant donde solía medir pasos individuales con time. Ahora me gustaría habilitar o deshabilitar condicionalmente las mediciones de tiempo.
Por ejemplo, anteriormente una línea se vería así:
time (apt-get update > /tmp/last.log 2>&1)
Ahora pensé que simplemente podría hacer algo como esto:
MEASURE_TIME=true
[[ $MEASURE_TIME = true ]] && TIME="time --format=%e" || TIME=""
$TIME (apt-get update > /tmp/last.log 2>&1)
Pero esto no funcionará:
syntax error near unexpected token `apt-get'
`$TIME (apt-get update > /tmp/last.log 2>&1)'
¿Cuál es el problema aquí?

Respuestas:
Para poder medir el tiempo de un subnivel, necesita la
timepalabra clave , no de comandos.La
timepalabra clave, parte del lenguaje, solo se reconoce como tal cuando se ingresa literalmente y como la primera palabra de un comando (y en el caso deksh93, el siguiente token no comienza con a-). Incluso ingresar"time"no funcionará y mucho menos$TIME(y se tomaría como una llamada altimecomando).Puede usar alias aquí que se expanden antes de que se realice otra ronda de análisis (por lo que permitiría que el shell reconozca esa
timepalabra clave):La
timepalabra clave no toma opciones (excepto-pinbash), pero el formato se puede establecer con laTIMEFORMATvariable inbash. (lashoptparte también esbashespecífica, otras conchas generalmente no lo necesitan).fuente
info -f bash --index-search=timeSi bien una
aliases una forma de hacerlo, esto también se puede hacereval: es solo que no desea tantoevalla ejecución del comando comoevalla declaración del comando .Me gustan
aliaslos: los uso todo el tiempo, pero me gustan más las funciones, especialmente su capacidad para manejar parámetros y que no necesariamente se deben expandir en la posición de comando como se requiere para losaliases.Así que pensé que quizás también quieras probar esto:
El
$IFSbit es principalmente sobre$*. Es importante que el( subshell bit )es también el resultado de un desarrollo del forro y así con el fin de ampliar los argumentos en una cadena de uso parsable I"$*"(no hacerloeval"$@", por cierto, a menos que esté seguro de todos los argumentos se pueden unir bajo espacios) . El delimitador dividido entre args in"$*"es el primer byte in$IFS, por lo que podría ser peligroso proceder sin asegurarse de su valor. Por lo que la función guarda$IFS, lo configura a un\newline el tiempo suficiente paraset ... "$*"dentro"$3",unsetes que, a continuación, restablece su valor si antes tenía uno.Aquí hay una pequeña demostración:
Verá, pongo dos comandos en el valor de
$TIMEallí: cualquier número está bien, incluso ninguno, pero asegúrese de que se escape y se cite correctamente, y lo mismo ocurre con los argumentos_time(). Todos se concatenarán en una sola cadena de comando cuando se ejecuten, pero cada\nargumento tiene su propia línea de conexión y, por lo tanto, se pueden distribuir con relativa facilidad. O bien, puede agruparlos todos en uno, si lo desea, y separarlos en\nlíneas electrónicas o punto y coma o lo que sea que tenga. Solo asegúrese de que un solo argumento represente un comando con el que se sienta cómodo al poner su propia línea en un script cuando lo llame.\(, por ejemplo, está bien, siempre que finalmente se siga con\). Básicamente las cosas normales.Cuando
evalse alimenta el fragmento anterior, se ve así:Y, sus resultados parecen ...
SALIDA
El
hasherror indica que no tengo/usr/bin/timeinstalado (porque no lo tengo) ycommandnos permite saber a qué hora se está ejecutando. El seguimientoset +xes otro comando ejecutado despuéstime(lo cual es posible) : es importante tener cuidado con los comandos de entrada al hacerevalcualquier cosa.fuente
_time() { eval "$TIME $@"; }? El uso de una función tiene el inconveniente de introducir un alcance diferente para las variables (no es un problema para las subcapas)"$@"expansión. Me gusta un solo argumentoeval: de lo contrario, da miedo. Ummm ... ¿qué quieres decir con el alcance diferente? Yo creía que era sólofunctionfunciones ...evalune sus argumentos antes de ejecutar, que es lo que está tratando de hacer de una manera muy complicada. Quise decir que eso_time 'local var=1; blah'haría que eso fueravarlocal_time, o que_time 'echo "$#"'imprimiría la función$#de esa_timefunción, no la de la persona que llama.evalconcatena sus argumentos en espacios, que es, como usted dice, exactamente lo que hago aquí, aunque no fue una intención inicial. Voy a arreglar eso.evalEn"$*"contraste con esto,"$@"es un hábito que aprendí después de muchos encuentros concommand not foundargs cuando se unieron en el lugar equivocado. En cualquier caso, aunque los args finalmente se ejecutan en la función, creo que es lo suficientemente simple como para expandirlos en la invocación. Es lo que haría con de"$#"todos modos.