¿Cómo puede el tiempo de la pared de la última orden puede poner en la línea de golpe?

StackOverflow https://stackoverflow.com/questions/1862510

  •  16-09-2019
  •  | 
  •  

Pregunta

¿Hay una manera de integrar el tiempo transcurrido de la pared del último comando en un Bash pedirá? Estoy esperando por algo que se vería así:

[last: 0s][/my/dir]$ sleep 10
[last: 10s][/my/dir]$

Fondo

A menudo ejecutar trabajos largos de datos-crujido y es útil saber cuánto tiempo que han tomado para que pueda estimar cuánto tiempo tomará para que los trabajos futuros. Para tareas muy regulares, sigo adelante y registrar esta información rigurosamente el uso de técnicas de extracción apropiadas. Para las tareas menos formal, sólo voy a anteponga el comando con time.

Sería bueno que time automáticamente cada solo comando interactivo y tener la información de tiempo impreso en unos pocos caracteres en lugar de 3 líneas.

¿Fue útil?

Solución

Se puede utilizar este gancho-zsh prestado para bash: http: // www.twistedmatrix.com/users/glyph/preexec.bash.txt

El tiempo hecho con este gancho (Mac OS X): uso Growl para supervisar largo ejecutar comandos shell

Otros consejos

Este es el código autónomo mínimo para conseguir lo que quiere:

function timer_start {
  timer=${timer:-$SECONDS}
}

function timer_stop {
  timer_show=$(($SECONDS - $timer))
  unset timer
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

PS1='[last: ${timer_show}s][\w]$ '

Usando sus respuestas y algunos otros hilos, escribí este mensaje que quiero compartir con ustedes. Tomé una captura de pantalla en los que se podrá ver:

  • White: Último código de retorno
  • verde y marca de la señal que significa el éxito (código de retorno de 0)
  • Red y marca de cruz significa error (código de retorno fue> 0)
  • (verde o rojo): tiempo de ejecución de comandos Última entre paréntesis
  • (verde o rojo): fecha y hora actual (\ t)
  • (verde si no tiene raíz, rojo si la raíz): el nombre de usuario registrado
  • (verde): el nombre del servidor
  • (azul): el directorio PWD y los habituales $

Custom pronta

Este es el código para poner en su archivo ~ / .bashrc:

function timer_now {
    date +%s%N
}

function timer_start {
    timer_start=${timer_start:-$(timer_now)}
}

function timer_stop {
    local delta_us=$((($(timer_now) - $timer_start) / 1000))
    local us=$((delta_us % 1000))
    local ms=$(((delta_us / 1000) % 1000))
    local s=$(((delta_us / 1000000) % 60))
    local m=$(((delta_us / 60000000) % 60))
    local h=$((delta_us / 3600000000))
    # Goal: always show around 3 digits of accuracy
    if ((h > 0)); then timer_show=${h}h${m}m
    elif ((m > 0)); then timer_show=${m}m${s}s
    elif ((s >= 10)); then timer_show=${s}.$((ms / 100))s
    elif ((s > 0)); then timer_show=${s}.$(printf %03d $ms)s
    elif ((ms >= 100)); then timer_show=${ms}ms
    elif ((ms > 0)); then timer_show=${ms}.$((us / 100))ms
    else timer_show=${us}us
    fi
    unset timer_start
}


set_prompt () {
    Last_Command=$? # Must come first!
    Blue='\[\e[01;34m\]'
    White='\[\e[01;37m\]'
    Red='\[\e[01;31m\]'
    Green='\[\e[01;32m\]'
    Reset='\[\e[00m\]'
    FancyX='\342\234\227'
    Checkmark='\342\234\223'


    # Add a bright white exit status for the last command
    PS1="$White\$? "
    # If it was successful, print a green check mark. Otherwise, print
    # a red X.
    if [[ $Last_Command == 0 ]]; then
        PS1+="$Green$Checkmark "
    else
        PS1+="$Red$FancyX "
    fi

    # Add the ellapsed time and current date
    timer_stop
    PS1+="($timer_show) \t "

    # If root, just print the host in red. Otherwise, print the current user
    # and host in green.
    if [[ $EUID == 0 ]]; then
        PS1+="$Red\\u$Green@\\h "
    else
        PS1+="$Green\\u@\\h "
    fi
    # Print the working directory and prompt marker in blue, and reset
    # the text color to the default.
    PS1+="$Blue\\w \\\$$Reset "
}

trap 'timer_start' DEBUG
PROMPT_COMMAND='set_prompt'

Otro enfoque es muy mínimo:

trap 'SECONDS=0' DEBUG
export PS1='your_normal_prompt_here ($SECONDS) # '

Esto muestra el número de segundos desde que se inició el último comando simple. El contador no se restablece si simplemente pulsa Enter sin introducir un comando - que puede ser muy útil cuando lo que desea es ver cuánto tiempo el terminal ha sido hasta desde la última vez hizo algo en ella. Funciona bien para mí en Red Hat y Ubuntu. No funcionó para mí bajo Cygwin, pero no estoy seguro si eso es un error o simplemente una limitación de intentar ejecutar Bash bajo Windows.

Un posible inconveniente de este enfoque es que se mantenga SEGUNDOS rearme, pero si realmente necesita conservar SEGUNDOS como el número de segundos desde el intérprete invocado inicial, puede crear su propia variable para el contador de PS1 en lugar de utilizar directamente SEGUNDOS. Otro posible inconveniente es que un gran valor de los segundos como "999999" podría ser mejor representada como días + horas + minutos + segundos, pero es fácil de añadir un filtro sencillo como por ejemplo:

seconds2days() { # convert integer seconds to Ddays,HH:MM:SS
  printf "%ddays,%02d:%02d:%02d" $(((($1/60)/60)/24)) \
  $(((($1/60)/60)%24)) $((($1/60)%60)) $(($1%60)) |
  sed 's/^1days/1day/;s/^0days,\(00:\)*//;s/^0//' ; }
trap 'SECONDS=0' DEBUG
PS1='other_prompt_stuff_here ($(seconds2days $SECONDS)) # '

Esto se traduce "999999" en "11 días, 13: 46: 39". La sed al final cambia "1 día" a "1 día", y corta los valores principales vacíos como "0 días, 00:". Ajustar al gusto.

Si no había puesto en cualquiera de las otras respuestas antes de que se inició su trabajo de larga duración y lo que desea saber cuánto tiempo tomó el trabajo, se puede hacer la sencilla

$ HISTTIMEFORMAT="%s " history 2

y que responderá con algo como

  654  1278611022 gvn up
  655  1278611714 HISTTIMEFORMAT="%s " history 2

y se puede restar a continuación, sólo visualmente las dos marcas de tiempo (Alguien sabe cómo capturar la salida del comando de la historia interna del shell?)

Tomé la respuesta de Ville Laurikari y mejorado con el comando time para mostrar una precisión inferior al segundo:

function timer_now {
  date +%s%N
}

function timer_start {
  timer_start=${timer_start:-$(timer_now)}
}

function timer_stop {
  local delta_us=$((($(timer_now) - $timer_start) / 1000))
  local us=$((delta_us % 1000))
  local ms=$(((delta_us / 1000) % 1000))
  local s=$(((delta_us / 1000000) % 60))
  local m=$(((delta_us / 60000000) % 60))
  local h=$((delta_us / 3600000000))
  # Goal: always show around 3 digits of accuracy
  if ((h > 0)); then timer_show=${h}h${m}m
  elif ((m > 0)); then timer_show=${m}m${s}s
  elif ((s >= 10)); then timer_show=${s}.$((ms / 100))s
  elif ((s > 0)); then timer_show=${s}.$(printf %03d $ms)s
  elif ((ms >= 100)); then timer_show=${ms}ms
  elif ((ms > 0)); then timer_show=${ms}.$((us / 100))ms
  else timer_show=${us}us
  fi
  unset timer_start
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

PS1='[last: ${timer_show}][\w]$ '

Por supuesto, esto requiere un proceso que se inicie, por lo que es menos eficiente, pero aún lo suficientemente rápido que no se daría cuenta.

He descubierto que trap ... DEBUG estaba corriendo cada vez que $PROMPT_COMMAND fue llamado, al restablecer el temporizador, y por lo tanto siempre volviendo 0.

Sin embargo, he encontrado que los registros history veces, y aprovechó estos para obtener mi respuesta:

HISTTIMEFORMAT='%s '
PROMPT_COMMAND="
  START=\$(history 1 | cut -f5 -d' ');
  NOW=\$(date +%s);
  ELAPSED=\$[NOW-START];
  $PROMPT_COMMAND"
PS1="\$ELAPSED $PS1"

No es perfecto sin embargo:

  • Si history no registra el comando (por ejemplo, comandos ignorados o repetida), la hora de inicio será un error.
  • comandos de varias líneas no reciben la fecha extraído correctamente desde history.

Otro enfoque para 4.x golpe y por encima sería utilizar coproc con PS0 y PS1, como a continuación:

cmd_timer()
{
    echo $(( SECONDS - $(head -n1 <&"${CMD_TIMER[0]}") ))
}

coproc CMD_TIMER ( while read; do echo $SECONDS; done )
echo '' >&"${CMD_TIMER[1]}" # For value to be ready on first PS1 expansion
export PS0="\$(echo '' >&${CMD_TIMER[1]})"
export PS1="[ \$(cmd_timer) ] \$"

Este es un fragmento listo .bashrc. Es especialmente útil para todo el mundo que utiliza undistract-me que sobrescribe trap DEBUG para sus propios fines.

se pone a \ t en el trabajo PS1 para usted?

No da el tiempo transcurrido, pero debería ser bastante fácil de restar los momentos en que sea necesario.

$ export PS1='[\t] [\w]\$ '
[14:22:30] [/bin]$ sleep 10
[14:22:42] [/bin]$

Siguiendo el comentario de la OP que ya está utilizando \ t. Si puede utilizar Tcsh lugar de fiesta, se puede establecer la variable de tiempo.

/bin 1 > set time = 0
/bin 2 > sleep 10
0.015u 0.046s 0:10.09 0.4%      0+0k 0+0io 2570pf+0w
/bin 3 >

Puede cambiar el formato de la impresión de ser menos feo (SE la página man tcsh).

/bin 4 > set time = ( 0 "last: %E" )
/bin 5 > sleep 10
last: 0:10.09
/bin 6 >

No sé de una instalación similar en bash

Este es mi versión

  • fecha de uso para formatear el tiempo, sólo unos días calc
  • set título terminal de
  • Uso de \ $ en PS1 para el usuario $ + root #
  • Mostrar código de retorno / código de salida
  • -u para desactivar el horario de verano Fecha de uso
  • Utilice nombres ocultos como _foo
_x_dt_min=1 # minimum running time to show delta T
function _x_before {
    _x_t1=${_x_t1:-$(date -u '+%s.%N')} # float seconds
}
function _x_after {
    _x_rc=$? # return code
    _x_dt=$(echo $(date -u '+%s.%N') $_x_t1 | awk '{printf "%f", $1 - $2}')
    unset _x_t1
    #_x_dt=$(echo $_x_dt | awk '{printf "%f", $1 + 86400 * 1001}') # test
    # only show dT for long-running commands
    # ${f%.*} = int(floor(f))
    (( ${_x_dt%.*} >= $_x_dt_min )) && {
        _x_dt_d=$((${_x_dt%.*} / 86400))
        _x_dt_s='' # init delta T string
        (( $_x_dt_d > 0 )) && \
            _x_dt_s="${_x_dt_s}${_x_dt_d} days + "
        # format time
        # %4N = four digits of nsec
        _x_dt_s="${_x_dt_s}$(date -u -d0+${_x_dt}sec '+%T.%4N')"
        PS1='rc = ${_x_rc}\ndT = ${_x_dt_s}\n\$ '
    } || {
        PS1='rc = ${_x_rc}\n\$ '
    }
    # set terminal title to terminal number
    printf "\033]0;%s\007" $(tty | sed 's|^/dev/\(pts/\)\?||')
}
trap '_x_before' DEBUG
PROMPT_COMMAND='_x_after'
PS1='\$ '

salida de ejemplo:

$ sleep 0.5
rc = 0
$ sleep 1
rc = 0
dT = 00:00:01.0040
$ sleep 1001d
rc = 0
dT = 1001 days + 00:00:00.0713
$ false
rc = 1
$ 

Esta es mi opinión sobre Thomas'

utiliza date +%s%3N para obtener milisegundos como unidad de base, simplificada siguiente código (menos ceros)

function t_now {
    date +%s%3N
}

function t_start {
    t_start=${t_start:-$(t_now)}
}

function t_stop {
    local d_ms=$(($(t_now) - $t_start))
    local d_s=$((d_ms / 1000))
    local ms=$((d_ms % 1000))
    local s=$((d_s % 60))
    local m=$(((d_s / 60) % 60))
    local h=$((d_s / 3600))
    if ((h > 0)); then t_show=${h}h${m}m
    elif ((m > 0)); then t_show=${m}m${s}s
    elif ((s >= 10)); then t_show=${s}.$((ms / 100))s
    elif ((s > 0)); then t_show=${s}.$((ms / 10))s
    else t_show=${ms}ms
    fi
    unset t_start
}
set_prompt () {
t_stop
}

trap 't_start' DEBUG
PROMPT_COMMAND='set_prompt' 

A continuación, añadir a su $t_show PS1

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top