Forzar un alias 'agregado' a cada comando

11

¿Es posible agregar a la fuerza un alias de tiempo (por falta de una mejor manera de expresarlo) a cada comando bash?

Por ejemplo, me gustaría tener un usuario específico que siempre que se ejecuta un comando, siempre se envuelve con dateantes y después, o time.

¿Es posible? y si lo es, cómo?

madriguera
fuente
Miré antes, y no pude encontrar una manera de hacer exactamente esto. Como dice Caleb, puede usar preexec, pero no desea ejecutarlo dentro del preexec(por ejemplo preexec() { time $1; }), porque el shell todavía lo ejecuta después de que preexecregrese. Entonces, lo mejor que podemos hacer es algo similar.
Mikel
@Mikel Creo que podría usar la preexec()función para envolver lo que se estaba ejecutando al buscar el comando, ejecutarlo usted mismo desde dentro de la función y luego devolver algún tipo de error para que el shell no ejecute el comando en sí.
Caleb

Respuestas:

10

Puede registrar la hora en que se inicia una línea de comando y la hora en que se muestra una solicitud. Bash ya realiza un seguimiento de la fecha de inicio de cada línea de comando en su historial, y puede observar la hora en que muestra el siguiente mensaje.

print_command_wall_clock_time () {
  echo Wall clock time: \
    $(($(date +%s) - $(HISTTIMEFORMAT="%s ";
                       set -o noglob;
                       set $(history 1); echo $2)))
}
PROMPT_COMMAND=print_command_wall_clock_time$'\n'"$PROMPT_COMMAND"

Esto solo le brinda una segunda resolución y solo el tiempo del reloj de pared. Si desea una mejor resolución, debe usar un datecomando externo que admita el %Nformato para nanosegundos y la DEBUGtrampa para llamar dateantes de ejecutar el comando a tiempo.

call_date_before_command () {
  date_before=$(date +%s.%N)
}
print_wall_clock_time () {
  echo Wall clock time: \
    $((date +"$date_before - %s.%N" | bc))
}
trap call_date_before_command DEBUG
PROMPT_COMMAND=print_command_wall_clock_time

Incluso con la DEBUGtrampa, no creo que haya una manera de mostrar automáticamente los tiempos de procesador para cada comando, o ser más discriminatorio que prompt to prompt.


Si está dispuesto a usar un shell diferente, aquí le mostramos cómo obtener un informe de tiempo para cada comando en zsh (esto no se generaliza a otras tareas):

REPORTTIME=0

Puede establecer REPORTTIMEcualquier valor entero, la información de temporización solo se mostrará para los comandos que usaron más de estos segundos de tiempo de procesador.

Zsh tomó esta característica de csh donde se llama a la variable time.

Gilles 'SO- deja de ser malvado'
fuente
3

Sus opciones aquí dependerán de su shell. En zshExiste una función de enlace conveniente llamada preexec()que se ejecuta justo antes de que los comandos de shell interactivas. Al crear una función con este nombre, puede hacer que se ejecuten cosas. También puede realizar un seguimiento con una función llamada precmd()que se ejecutará justo antes de que se dibuje el siguiente mensaje, que será justo después de que finalice su comando.

Al crear este par de funciones, puede ejecutar los comandos arbitrarios que desee ejecutar antes y después de los comandos emitidos en el indicador. Puede usar esto para registrar el uso de shell, crear bloqueos, probar el entorno o, como en su ejemplo, calcular el tiempo o los recursos gastados mientras se ejecuta un comando.

En este ejemplo, crearemos una marca de tiempo de referencia antes de ejecutar un comando usando, preexec()luego calcularemos el tiempo empleado en ejecutar el comando precmd()y lo enviaremos antes del aviso o lo desconectaremos. Ejemplo:

preexec() {
   CMDSTART=$(date +%s%N)
}
precmd() {
   CMDRUNTIME=$(($(date +%s%N)-$CMDSTART))
   echo "Last command ran for $CMDRUNTIME nanoseconds."
}

Nota: Para este ejemplo en particular, hay una función incorporada aún más fácil. Todo lo que tiene que hacer es activar los informes de tiempo de ejecución en ZSH y lo hará automáticamente.

$ export REPORTTIME=0
$ ls -d
./
ls -BF --color=auto -d  0.00s user 0.00s system 0% cpu 0.002 total

En una aplicación más práctica de preexec(), lo uso ver si el shell se ejecuta dentro de tmuxo screeny, si es así, para enviar información sobre el comando de aguas arriba está ejecutando actualmente para que se muestre en el nombre de la ficha.

Desafortunadamente en bash este pequeño mecanismo no existe. Aquí está el intento de un hombre de replicarlo . También vea la respuesta de Gilles para un pequeño truco ingenioso similar.

Caleb
fuente
1
Y aquí hay una versión simplificada del truco precmd-through-DEBUG .
Gilles 'SO- deja de ser malvado'
¡Ojalá esto estuviera disponible en bash!
Warren
Vea los enlaces de Gilles y otros, es implementable en bash con un poco de violín extra. De nuevo, ¿por qué no ejecutas zsh? ¡Es un caparazón oscilante con más buenas razones para cambiar que solo esto!
Caleb
2
Si está usando zsh, hay una forma aún mejor de hacerlo. La variable de entorno REPORTTIME cuando se establece generará la información del tiempo de ejecución (como si hubiera ejecutado el comando con 'tiempo' delante) para cualquier comando que tarde más de $ REPORTTIME segundos. Simplemente configúrelo en 0 y debería indicarle la hora de cada comando, con el desglose de usuario / sistema para arrancar.
Joseph Garvin el
1

La forma más fácil probablemente sería establecer PROMPT_COMMAND. Ver Variables de Bash :

PROMPT_COMMAND
Si se establece, el valor se interpreta como un comando para ejecutar antes de la impresión de cada solicitud primaria ( $PS1).

Por ejemplo, para evitar sobrescribir cualquier comando de solicitud existente, puede hacer lo siguiente:

PROMPT_COMMAND="date ; ${PROMPT_COMMAND}"
cjm
fuente
no sabía sobre eso - parece un buen comienzo, @cjm
warren
1
Es un comienzo, pero no aborda el problema de saber cuándo se ejecutó un comando. La solicitud en sí misma puede dibujarse minutos, horas o días antes de que se escriba y ejecute un comando.
Caleb
0

csh/ tcshtiene el mejor soporte para esta función (y siempre la ha tenido).

  The `time` shell variable can be set to execute the time builtin  command
  after the completion of any process that takes more than a given number
  of CPU seconds.

En otras palabras, set time=1imprimirá el tiempo consumido (sistema, usuario, transcurrido) por cualquier comando que tomó más de 1 segundo de tiempo de CPU. Plain set timepermitirá imprimir la hora de todos los comandos.

alexis
fuente