Muestre Spinner mientras espera que termine algún proceso

13

¿Cómo puedo mostrar la ruleta hasta que la línea de comando termine es trabajo? En otras palabras, si estoy ejecutando un script y quiero mostrar el spinner mientras este script se está ejecutando y el spinner desaparece cuando el script termina, es trabajo.

A continuación se muestra un código de ruleta común:

i=1
sp="/-\|"
echo -n ' '
while true
do
printf "\b${sp:i++%${#sp}:1}"
done

¿Cómo puedo vincular el código anterior de la ruleta a un comando para que muestre la ruleta mientras el comando se está ejecutando y la ruleta desaparece cuando el comando termina es trabajo? Si incluyo el comando dentro del bucle, se repetirá con la ruleta, ¿cuál es la solución en este caso?


fuente

Respuestas:

21

Haga que su whilebucle esté atento a su comando real para salir. Asumiré un entorno Linux que tiene entradas / proc para cada PID, pero podría dividirlo de otras maneras:

#!/bin/bash
# your real command here, instead of sleep
sleep 7 &
PID=$!
i=1
sp="/-\|"
echo -n ' '
while [ -d /proc/$PID ]
do
  printf "\b${sp:i++%${#sp}:1}"
done
Jeff Schaller
fuente
99
Este es un ciclo ocupado que consumirá recursos de la CPU. Sugeriría tener un retraso de algún tipo en su ciclo while.
ACase
16

Este script de shell debe hacer lo que estás buscando:

#!/usr/bin/env bash

show_spinner()
{
  local -r pid="${1}"
  local -r delay='0.75'
  local spinstr='\|/-'
  local temp
  while ps a | awk '{print $1}' | grep -q "${pid}"; do
    temp="${spinstr#?}"
    printf " [%c]  " "${spinstr}"
    spinstr=${temp}${spinstr%"${temp}"}
    sleep "${delay}"
    printf "\b\b\b\b\b\b"
  done
  printf "    \b\b\b\b"
}

("$@") &
show_spinner "$!"

Suponiendo que almacene el script de shell en un archivo llamado spinner, puede invocarlo de esta manera para mostrar una flecha giratoria mientras sleep 10se ejecuta el comando :

$ spinner sleep 10
jsears
fuente
Esto supone que se llama al script de shell spinner, por lo que no. Creo que el ejemplo es correcto, suponiendo que nombre el guión spinner.
jsears
3

Aquí hay otro spinner elegante que puedes usar así:

spinner ping google.com
echo "ping exited with exit code $?"

spinner sleep 10
echo "sleep exited with exit code $?"

Tiene 12 temas y elige uno al azar.

#!/bin/bash
# Shows a spinner while another command is running. Randomly picks one of 12 spinner styles.
# @args command to run (with any parameters) while showing a spinner. 
#       E.g. ‹spinner sleep 10›

function shutdown() {
  tput cnorm # reset cursor
}
trap shutdown EXIT

function cursorBack() {
  echo -en "\033[$1D"
}

function spinner() {
  # make sure we use non-unicode character type locale 
  # (that way it works for any locale as long as the font supports the characters)
  local LC_CTYPE=C

  local pid=$1 # Process Id of the previous running command

  case $(($RANDOM % 12)) in
  0)
    local spin='⠁⠂⠄⡀⢀⠠⠐⠈'
    local charwidth=3
    ;;
  1)
    local spin='-\|/'
    local charwidth=1
    ;;
  2)
    local spin="▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
    local charwidth=3
    ;;
  3)
    local spin="▉▊▋▌▍▎▏▎▍▌▋▊▉"
    local charwidth=3
    ;;
  4)
    local spin='←↖↑↗→↘↓↙'
    local charwidth=3
    ;;
  5)
    local spin='▖▘▝▗'
    local charwidth=3
    ;;
  6)
    local spin='┤┘┴└├┌┬┐'
    local charwidth=3
    ;;
  7)
    local spin='◢◣◤◥'
    local charwidth=3
    ;;
  8)
    local spin='◰◳◲◱'
    local charwidth=3
    ;;
  9)
    local spin='◴◷◶◵'
    local charwidth=3
    ;;
  10)
    local spin='◐◓◑◒'
    local charwidth=3
    ;;
  11)
    local spin='⣾⣽⣻⢿⡿⣟⣯⣷'
    local charwidth=3
    ;;
  esac

  local i=0
  tput civis # cursor invisible
  while kill -0 $pid 2>/dev/null; do
    local i=$(((i + $charwidth) % ${#spin}))
    printf "%s" "${spin:$i:$charwidth}"

    cursorBack 1
    sleep .1
  done
  tput cnorm
  wait $pid # capture exit code
  return $?
}

("$@") &

spinner $!
Jonas Eberle
fuente
2

Si desea un spinner de mínimo común denominador que funcione con / bin / sh y no se base en la sustitución del parámetro bash extendido, esto debería funcionar:

#!/bin/sh

# The command you are waiting on goes between the ( ) here
# The example below returns a non zero return code

(sleep 20 ; /bin/false) &

pid=$! ; i=0
while ps -a | awk '{print $1}' | grep -q "${pid}"
do
    c=`expr ${i} % 4`
    case ${c} in
       0) echo "/\c" ;;
       1) echo "-\c" ;;
       2) echo "\\ \b\c" ;;
       3) echo "|\c" ;;
    esac
    i=`expr ${i} + 1`
    # change the speed of the spinner by altering the 1 below
    sleep 1
    echo "\b\c"
done

# Collect the return code from the background process

wait ${pid}
ret=$?

# You can report on any errors due to a non zero return code here

exit ${ret}
Rob Bartlett
fuente