Tampilkan Spinner sambil menunggu beberapa proses selesai


13

Bagaimana saya bisa menunjukkan pemintal sampai baris perintah selesai itu pekerjaan? Dengan kata lain, Jika saya menjalankan skrip dan saya ingin menunjukkan pemintal saat skrip ini berjalan dan pemintal menghilang ketika skrip selesai itu adalah pekerjaan.

Di bawah adalah kode pemintal yang umum:

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

Bagaimana saya bisa menautkan kode pemintal sebelumnya ke sebuah perintah untuk membiarkannya menampilkan pemintal saat perintah sedang berjalan dan pemintal menghilang ketika perintah selesai itu adalah pekerjaan? Jika saya memasukkan perintah di dalam loop itu akan loop dengan spinner jadi apa solusinya dalam kasus ini?

bash 

Jawaban:


21

Suruh whileloop Anda mengawasi perintah Anda yang sebenarnya untuk keluar. Saya akan menganggap lingkungan Linux yang memiliki / proc entri untuk setiap PID, tetapi Anda dapat mengirisnya dengan cara lain:

#!/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

9
Ini adalah loop sibuk yang akan menghabiskan sumber daya cpu. Saya sarankan memiliki penundaan dalam loop sementara Anda.
ACase

16

Script shell ini harus melakukan apa yang Anda cari:

#!/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 "$!"

Dengan asumsi Anda menyimpan skrip shell dalam sebuah file bernama spinner, Anda dapat memanggilnya seperti ini untuk menampilkan pemintal saat perintah sleep 10sedang berjalan:

$ spinner sleep 10


Ini mengasumsikan skrip shell disebut spinner, jadi tidak. Saya pikir contohnya benar, dengan asumsi Anda memberi nama skrip spinner.
jsears

3

Inilah pemintal mewah lain yang dapat Anda gunakan seperti ini:

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

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

Ini memiliki 12 tema dan mengambil satu secara acak.

#!/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 $!

2

Jika Anda menginginkan spinner denominator umum terendah yang berfungsi dengan / bin / sh dan tidak bergantung pada substitusi parameter bash yang diperluas, ini seharusnya berfungsi:

#!/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}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.