¿Cómo detener un script Bash con la barra espaciadora?

¿Cómo detener un script Bash con la barra espaciadora?

Estoy trabajando en un cronómetro del Cubo de Rubik escrito en Bash y me gustaría detenerlo presionando la barra espaciadora ya que Ctrl+ Cno es factible cuando tienes que terminarlo lo más rápido que puedas.

Entonces, ¿hay alguna manera de detener el programa simplemente con la barra espaciadora?

Miré el comando killpero no pude entenderlo.

La parte del cronómetro del código se encuentra a continuación:

TMP0=$(date +%s%N)
while true; do
    TMP1=$(date +%s%N)
    DTMP=$(($TMP1-$TMP0))
    printf "\r$(($DTMP/1000000000)).${DTMP:(-9):2}"
done

Respuesta1

Es su terminal quien envía SIGINT al grupo de procesos de primer plano cuando presiona Ctrl+ c. Puede configurarlo para que haga esto con cualquier personaje, pero desea restaurar la configuración anterior cuando finalice el script.

#!/bin/bash

settings="$(stty -g)"
trap 'stty "$settings"' EXIT
stty intr ' '

TMP0=$(date +%s%N)
while true; do
    TMP1=$(date +%s%N)
    DTMP=$(($TMP1-$TMP0))
    printf '\r%s' "$(($DTMP/1000000000)).${DTMP:(-9):2}"
done

settings="$(stty -g)"guarda la configuración anterior; stty intr ' 'hace que el terminal reaccione en Spacelugar de Ctrl+ c; trap 'stty "$settings"' EXITes responsable de restaurar la configuración anterior cuando se cierra el script.

Notas:

  • En el código de la trampa, stty $settingses mejor que stty "$settings". Es una excepción del "cita siempre" regla. Las comillas evitan la división de palabras y la generación de nombres de archivos (globbing), pero algunas implementaciones de sttypueden requerir la división de palabras, para ellas la variable no debe estar entre comillas. Para evitar efectos secundarios dañinos de la generación de nombres de archivos, laespecificaciónrequiere stty -ggenerar una cadena que no active esta característica.

    Editar:eso fue un defecto en la especificación POSIX. El código anterior ha sido corregido.

  • En caso de que algo salga mal y te encuentres en un shell interactivo donde Spaceaún se genera SIGINT, debes invocarlo stty intr ^Cmanualmente. Hay espacios en el comando, pero tenga en cuenta que aún puede escribir un carácter de espacio literal presionando Ctrl+ v Space.

  • Lo usé printf '\r%s' …porque creo que un formato estático y datos dinámicos se ajustan printfmejor a la "filosofía" que el formato dinámico que usaste.

" Spaceen lugar de Ctrl+ c" significa que cuando Spacese vuelve especial, Ctrl+ cdeja de ser especial. Puedes llamarlo un defecto porquelos usuarios esperarán que Ctrl+ csiga siendo especial. Sin embargo, hacer que ambos sean especiales al mismo tiempo no es trivial, creo que no se puede hacer configurando el terminal.

Esta versión alternativa se detiene en casi cualquier tecla, mientras que Ctrl+ cfunciona como siempre:

#!/bin/bash

while read -r -t 0.001; do :; done    # dump the buffer
TMP0=$(date +%s%N)
until read -r -n 1 -t 0.001; do
    TMP1=$(date +%s%N)
    DTMP=$(($TMP1-$TMP0))
    printf '\r%s' "$(($DTMP/1000000000)).${DTMP:(-9):2}"
done
echo

Para que reaccione Spacesólo es necesario comprobar lo leído:


until read -r -n 1 -t 0.001 && [ "$REPLY" = ' ' ]; do

Tenga en cuenta que el mecanismo para Spacedetener el script ahora es muy diferente al funcionamiento de Ctrl+ c.

Respuesta2

Si no necesitas el cronómetro, después de todo, solo quieres saber el tiempo que tomó al final, puedes usar:

time read -r -n 1

te dará una salida como:

time read -r -n 1

real    1m30.909s
user    0m0.000s
sys     0m0.000s

y detenerse con prácticamente cualquier pulsación de tecla (similar a cómo usa Kamil read)

o si solo quieres la parte del tiempo:

{ time read -r -n 1; } 2>&1 | grep real | awk '{ print $2 }'

cortesía derico

información relacionada