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
time
palabra clave , no de comandos.La
time
palabra 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 altime
comando).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
time
palabra clave):La
time
palabra clave no toma opciones (excepto-p
inbash
), pero el formato se puede establecer con laTIMEFORMAT
variable inbash
. (lashopt
parte también esbash
específica, otras conchas generalmente no lo necesitan).fuente
info -f bash --index-search=time
Si bien una
alias
es una forma de hacerlo, esto también se puede hacereval
: es solo que no desea tantoeval
la ejecución del comando comoeval
la declaración del comando .Me gustan
alias
los: 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 losalias
es.Así que pensé que quizás también quieras probar esto:
El
$IFS
bit 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\n
ewline el tiempo suficiente paraset ... "$*"
dentro"$3"
,unset
es 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
$TIME
allí: 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\n
argumento 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\n
lí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
eval
se alimenta el fragmento anterior, se ve así:Y, sus resultados parecen ...
SALIDA
El
hash
error indica que no tengo/usr/bin/time
instalado (porque no lo tengo) ycommand
nos permite saber a qué hora se está ejecutando. El seguimientoset +x
es otro comando ejecutado despuéstime
(lo cual es posible) : es importante tener cuidado con los comandos de entrada al hacereval
cualquier 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ólofunction
funciones ...eval
une 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 fueravar
local_time
, o que_time 'echo "$#"'
imprimiría la función$#
de esa_time
función, no la de la persona que llama.eval
concatena 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.eval
En"$*"
contraste con esto,"$@"
es un hábito que aprendí después de muchos encuentros concommand not found
args 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.