bash - que - pasar parametros shell script
¿Cómo se puede colocar el tiempo de pared del último comando en el indicador Bash? (8)
¿Hay alguna manera de incrustar el tiempo de pared transcurrido del último comando en un indicador de Bash ? Estoy esperando algo que se vería así:
[last: 0s][/my/dir]$ sleep 10
[last: 10s][/my/dir]$
Fondo
A menudo ejecuto largos trabajos de análisis de datos y es útil saber cuánto tiempo han tardado para poder estimar cuánto tiempo tomará para trabajos futuros. Para tareas muy regulares, sigo y grabo esta información rigurosamente usando las técnicas de registro apropiadas. Para tareas menos formales, voy a anteponer el comando con el time
.
Sería bueno programar automáticamente cada comando interactivo e imprimir la información de tiempo en unos pocos caracteres en lugar de 3 líneas.
¿Te va a poner un / t en PS1?
No da el tiempo transcurrido, pero debería ser lo suficientemente fácil para restar los tiempos cuando sea necesario.
$ export PS1=''[/t] [/w]/$ ''
[14:22:30] [/bin]$ sleep 10
[14:22:42] [/bin]$
Siguiendo el comentario del OP de que ya está usando / t. Si puede usar tcsh en lugar de bash, 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 para que sea menos fea (en la página man de 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
Encontré esa trap ... DEBUG
estaba ejecutando cada vez que se llamaba $PROMPT_COMMAND
, reiniciando el temporizador y, por lo tanto, siempre devolviendo 0.
Sin embargo, descubrí que la history
registra los tiempos, 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"
Aunque no es perfecto:
- Si el
history
no registra el comando (por ejemplo, comandos repetidos o ignorados), la hora de inicio será incorrecta. - Los comandos de varias líneas no obtienen la fecha correctamente extraída del
history
.
Este es un código independiente mínimo para lograr lo que desea:
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]$ ''
Otro enfoque muy mínimo es:
trap ''SECONDS=0'' DEBUG
export PS1=''your_normal_prompt_here ($SECONDS) # ''
Esto muestra la cantidad de segundos desde que se inició el último comando simple. El contador no se restablece si simplemente presiona Enter sin ingresar un comando, lo que puede ser útil cuando solo quieres ver cuánto tiempo ha estado activo el terminal desde la última vez que hiciste algo en él. 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 tratar de ejecutar Bash bajo Windows.
Una posible desventaja de este enfoque es que sigue reiniciando SECONDS, pero si realmente necesita conservar SECONDS como el número de segundos desde la invocación inicial del shell, puede crear su propia variable para el contador de PS1 en lugar de usar SECONDS directamente. Otro posible inconveniente es que un valor grande de segundos como "999999" se puede mostrar mejor como días + horas + minutos + segundos, pero es fácil agregar un filtro simple como:
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 traduce "999999" en "11 días, 13: 46: 39". El sed al final cambia "1days" a "1day", y recorta valores iniciales vacíos como "0days, 00:". Ajustar al gusto.
Podrías utilizar este gancho zsh-borrowed para bash: http://www.twistedmatrix.com/users/glyph/preexec.bash.txt
Sincronización realizada con este gancho (Mac OS X): use Growl para monitorear comandos de shell de ejecución prolongada
Si no había configurado ninguna de las otras respuestas antes de iniciar su trabajo de larga duración y solo desea saber cuánto tiempo tomó el trabajo, puede hacer lo simple.
$ HISTTIMEFORMAT="%s " history 2
y responderá con algo como
654 1278611022 gvn up
655 1278611714 HISTTIMEFORMAT="%s " history 2
y luego puede simplemente restar visualmente las dos marcas de tiempo (¿alguien sabe cómo capturar la salida del comando de historial integrado de shell?)
Tomé la respuesta de Ville Laurikari y la mejoré usando el comando de time
para mostrar una precisión de segundo menor:
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 que se inicie un proceso, por lo que es menos eficiente, pero lo suficientemente rápido para que no lo note.
Usando sus respuestas y algunos otros hilos, escribí este mensaje que quiero compartir con usted. Tomé una captura de pantalla en la que puedes ver:
- Blanco: último código de retorno
- La marca verde y marca significa éxito (el código de retorno fue 0)
- La marca roja y cruzada significa error (el código de retorno era> 0)
- (Verde o rojo): tiempo de ejecución del último comando entre paréntesis
- (Verde o rojo): hora actual (/ t)
- (Verde si no es root, Rojo si es root): el nombre de usuario registrado
- (Verde): el nombre del servidor
- (Azul): el directorio pwd y el usual $
Aquí está 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''