Как изменить индикатор выполнения в соответствии с доступным пространством? - PullRequest
3 голосов
/ 18 февраля 2011

Я хочу получить эффект, когда длина моего индикатора выполнения изменяется в соответствии с моим окном PuTTY. Этот эффект достигается с помощью индикатора прогресса wget.

Вот моя программа, которую я использую в скриптах bash для создания индикатора выполнения:

_progress_bar

#!/bin/bash

maxwidth=50     # line length (in characters)
filled_char="#"
blank_char="."

current=0 max=0 i=0

current=${1:-0} 
max=${2:-100} 

if (( $current > $max )) 
then 
    echo >&2 "current value must be smaller max. value" 
    exit 1 
fi
percent=`awk 'BEGIN{printf("%5.2f", '$current' / '$max' * 100)}'`

chars=($current*$maxwidth)/$max
echo -ne " ["

while (( $i < $maxwidth )) 
do 
    if (( $i <= $chars ));then
        echo -ne $filled_char 
    else
        echo -ne $blank_char
    fi 
    i=($i+1)
done 

echo -ne "] $percent%\r" 


if (( $current == $max )); then
    echo -ne "\r"
    echo
fi

Вот пример того, как я его использую, этот пример находит все прокси-серверы Tor Onion в Exit и блокирует IP-адрес в пользовательской цепочке:

#!/bin/bash


IPTABLES_TARGET="DROP"
IPTABLES_CHAINNAME="TOR"

WORKING_DIR="/tmp/"

# get IP address of eth0 network interface
IP_ADDRESS=$(ifconfig eth0 | awk '/inet addr/ {split ($2,A,":"); print A[2]}')



if ! iptables -L "$IPTABLES_CHAINNAME" -n >/dev/null 2>&1 ; then            #If chain doesn't exist
    iptables -N "$IPTABLES_CHAINNAME" >/dev/null 2>&1               #Create it
fi


cd $WORKING_DIR


wget -q -O - http://proxy.org/tor_blacklist.txt -U NoSuchBrowser/1.0 > temp_tor_list1
sed -i 's|RewriteCond %{REMOTE_ADDR} \^||g' temp_tor_list1
sed -i 's|\$.*$||g' temp_tor_list1
sed -i 's|\\||g' temp_tor_list1
sed -i 's|Rewrite.*$||g' temp_tor_list1

wget -q -O - "https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=$IP_ADDRESS&port=80" -U NoSuchBrowser/1.0 > temp_tor_list2
wget -q -O - "https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=$IP_ADDRESS&port=9998" -U NoSuchBrowser/1.0 >> temp_tor_list2
sed -i 's|^#.*$||g' temp_tor_list2



iptables -F "$IPTABLES_CHAINNAME"


CMD=$(cat temp_tor_list1 temp_tor_list2 | uniq | sort)
UBOUND=$(echo "$CMD" | grep -cve '^\s*$')

for IP in $CMD; do
    let COUNT=COUNT+1
    _progress_bar $COUNT $UBOUND
    iptables -A "$IPTABLES_CHAINNAME" -s $IP -j $IPTABLES_TARGET
done

iptables -A "$IPTABLES_CHAINNAME" -j RETURN


rm temp_tor*

Edit:

Я понял, что в первом примере люди могут не захотеть использовать, поэтому вот более простая концепция:

#!/bin/bash

for i in {1..100}; do
    _progress_bar $i 100
done

Ответы [ 3 ]

1 голос
/ 18 февраля 2011

После некоторого поиска в Google я нашел следующее:

tput cols вернет количество столбцов, очень похоже на предложенное Sdaz COLUMNS var.

Поэтому я иду с: maxwidth=$(tput cols), если у кого-то еще нет более пуленепробиваемого способа без необходимости tput

1 голос
/ 18 февраля 2011

Я сделал несколько изменений в вашем скрипте:

  • Преобразовал его в функцию.Если вы хотите сохранить его в отдельном файле, чтобы он был доступен для нескольких сценариев, просто поставьте файл в каждом из ваших сценариев.Это устраняет необходимость повторного вызова внешнего скрипта.
  • Устранен цикл while (который в любом случае должен был быть for ((i=0; $i < $maxwidth; i++))) для резкого ускорения.
  • Изменил арифметикувыражения, поэтому они вычисляются немедленно, вместо того, чтобы задавать их в виде строк для последующей оценки.
  • Удалены знаки доллара из имен переменных, где они появляются в арифметических контекстах.
  • Изменено echo -en на printf.
  • Сделано несколько других изменений
  • Изменен вывод AWK, чтобы "100,00%" был десятичным, выровненным с меньшими значениями.
  • Изменен в команде AWK, чтобы использовать передачу переменных вместо "inside"-out: цитирование.

Вот результат:

_progress_bar () {
    local maxwidth=50     # line length (in characters)
    local filled_char="#"
    local blank_char="."

    local current=0 max=0 i=0
    local complete remain

    current=${1:-0}
    max=${2:-100}

    if (( current > max ))
    then
        echo >&2 "current value must be smaller than max. value"
        return 1
    fi
    percent=$(awk -v "c=$current" -v "m=$max" 'BEGIN{printf("%6.2f", c / m * 100)}')

    (( chars = current * maxwidth / max))

    # sprintf n zeros into the var named as the arg to -v
    printf -v complete '%0*.*d' '' "$chars" ''
    printf -v remain '%0*.*d' '' "$((maxwidth - chars))" ''

    # replace the zeros with the desired char
    complete=${complete//0/"$filled_char"}
    remain=${remain//0/"$blank_char"}

    printf ' [%s%s] %s%%\r' "$complete" "$remain" "$percent"
}

В чем был вопрос? О, смотрите BashFAQ / 091 . Использование tputили bash -i и $COLUMNS. Однако, если вы используете bash -i, имейте в виду, что он будет иметь дополнительные издержки при обработке ваших файлов запуска

0 голосов
/ 18 февраля 2011

Bash экспортирует envvars LINES и COLUMNS в строки окна и количество столбцов соответственно. Кроме того, при изменении размера окна замазки через протоколы SSH или telnet в протоколе достаточно логики для отправки сигнала WINCH в активную оболочку, которая затем сбрасывает эти значения в новые размеры окна.

В вашем bash-скрипте используйте переменную COLUMNS, чтобы установить текущие измерения, и разделите 100 / progbarlen (прогбарлен, основанный на части переменной COLUMNS), чтобы узнать, сколько процентных точек составляют один символ, и продвигать их как ваш прогресс движется вперед. Чтобы динамически обрабатывать изменение размера, добавьте обработчик для SIGWINCH (через trap) и попросите его перечитать envvar COLUMNS и перерисовать индикатор выполнения, используя новые измерения.

(Я не проверял это в сценарии оболочки, и может потребоваться дополнительная логика, но именно так bash обнаруживает / обрабатывает изменение размера.)

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