Несколько Progress Bar - PullRequest
       13

Несколько Progress Bar

1 голос
/ 12 марта 2010

В дополнение к моему предыдущему запросу о многопоточности в сценариях оболочки Мне любопытно, можно ли использовать несколько индикаторов прогресса.

Вот фрагмент кода моего ожидаемого результата:

Output : 1 of 100  Files Completed   # Thread1
Output : 10 of 45 files Completed     # Thread 2    

Обновлены строки, показывающие прогресс. Можно ли будет это реализовать оболочкой. Буду признателен за вашу помощь, если у кого-нибудь есть идеи по этому поводу.

С уважением Киран

Ответы [ 3 ]

2 голосов
/ 12 марта 2010

Да, это очень возможно.

Предполагается, что ваш существующий код (на основе ваших предыдущих сообщений) в настоящее время выглядит примерно так:

do_something() {
  ...
  echo -ne "\r$index of $No_of_Files Completed"
  ...
}

do_something A &
do_something B &
do_something C &
wait

... тогда вы можете выполнить следующие настройки, чтобы добиться того эффекта, который вы имели в виду:

# Background tasks will no longer write directly to the console; instead, 
#  they will write to temporary files which will be read periodically 
#  by a special log printer task (which will display everything nicely.) 
# 
# Name of temporary files 
STATUS_BASENAME="/tmp/~$$.status" 
# Process IDs of backgrounded tasks; we record them so we can wait on them 
#  specifically but not wait on the special log printer task 
TASK_PIDS="" 

do_something() { 
  # First parameter must be a task ID starting at 0 incremented by 1 
  TASK_ID=$1 ; shift 
  ...
  # We write new status to status file (note we don't echo -n, we want that 
  #  trailing newline) 
  # Try to go through a temporary status file which we rename afterwards to 
  #  avoid race conditions with the special log printer task 
  echo "$x of 5 Completed" >"${STATUS_BASENAME}.${TASK_ID}.tmp" 
  mv "${STATUS_BASENAME}.${TASK_ID}.tmp" "${STATUS_BASENAME}.${TASK_ID}" 
  ...
} 

# Special log printer task 
status_printer() { 
  # First time in the loop is special insofar we don't have to 
  #  scroll up to overwrite previous output. 
  FIRST_TIME=1 
  while true ; do 
    # If not first time, scroll up as many lines as we have 
    #  regular background tasks to overwrite previous output. 
    test $FIRST_TIME -eq 0 && for PID in $TASK_PIDS ; do 
      echo -ne '\033M' # scrol up one line using ANSI/VT100 cursor control sequences 
    done 
    FIRST_TIME=0
    TASK_ID=0
    for PID in $TASK_PIDS ; do 
      # If status file exists print first line 
      test -f "${STATUS_BASENAME}.${TASK_ID}" && head -1 "${STATUS_BASENAME}.${TASK_ID}" || echo "waiting..." 
      TASK_ID=`expr $TASK_ID + 1` # using expr for portability :) 
    done 
    test -f "${STATUS_BASENAME}.done" && return
    sleep 1 # seconds to wait between updates 
  done 
} 

do_something 0 A &
 TASK_PIDS="$TASK_PIDS $!" 
do_something 1 B & 
 TASK_PIDS="$TASK_PIDS $!" 
do_something 2 C &
 TASK_PIDS="$TASK_PIDS $!" 

status_printer & 
  PRINTER_PID=$! 

# Wait for background tasks 
wait $TASK_PIDS 

# Stop special printer task instead of doing just
#  kill $PRINTER_PID >/dev/null
touch "${STATUS_BASENAME}.done"
wait $PRINTER_PID

# Cleanup 
rm -f "${STATUS_BASENAME}."* 
1 голос
/ 12 марта 2010

Как то, что делает <a href="http://www.ivarch.com/programs/pv.shtml" rel="nofollow noreferrer">pv</a> -c?

Конечно, см. src / pv / cursor.c . Хотя это не совсем безопасно сделать из оболочки, небольшая утилита C может позаботиться об этом.

0 голосов
/ 12 марта 2010

Если выходные данные вашего подпроцесса являются фильтруемыми, вы можете перенаправить стандартный вывод каждого подпроцесса в другой файловый дескриптор, а затем вызвать функцию для просмотра выходных данных этого файлового дескриптора. Затем вы можете попробовать использовать printf для обновления индикатора выполнения. Это где вы столкнетесь с проблемами, хотя. Не уверен, что встроенный в Bash printf может обработать терминал с этой деталью. Я никогда не пытался написать индикатор прогресса в Bash, который выполняет многострочный вывод. Почему бы не использовать диалог?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...