Динамический счетчик патчей для Shell Script - PullRequest
1 голос
/ 20 марта 2012

Я разрабатываю скрипт на машине Solaris 10 SPARC, чтобы вычислить, сколько исправлений было успешно установлено во время доставки исправлений. Я хотел бы отобразить пользователю:

(X) из 33 исправлений были успешно установлены

Я бы хотел, чтобы мой скрипт выводил динамически, заменяя «X», чтобы пользователь знал, что происходит какое-то действие; вроде как счетчик. Я могу показать счет, но только на новой линии. Как сделать так, чтобы скобки обновлялись динамически, когда скрипт выполняет свои проверки? Не беспокойтесь о «пройти / потерпеть неудачу» ... Меня больше всего интересует, как обновить вывод в скобке.

for x in `cat ${PATCHLIST}`
do
    if ( showrev -p $x | grep $x > /dev/null 2>&1 ); then
        touch /tmp/patchcheck/* | echo "pass" >> /tmp/patchcheck/$x
        wc /tmp/patchcheck/* | tail -1 | awk '{print $1}'
    else
        touch /tmp/patchcheck/* | echo "fail" >> /tmp/patchcheck/$x
        wc /tmp/patchcheck/* | tail -1 | awk '{print $1}'
    fi
done

Ответы [ 2 ]

2 голосов
/ 20 марта 2012

Обычный способ сделать это - выдать \r возврат каретки (CR) в некоторой точке и пропустить \n перевод строки или перевод строки (LF) в конце строки.Поскольку вы используете awk, вы можете попробовать:

awk '{printf "\r%s", $1} END {print ""}'

Для большинства строк он возвращает возврат каретки и данные в поле 1 (без перевода строки в конце).В конце ввода печатается пустая строка, за которой следует новая строка.

Еще одна возможность заключается в том, что вы должны поместить скрипт awk вне цикла for:

for x in `cat ${PATCHLIST}`
do
    if ( showrev -p $x | grep $x > /dev/null 2>&1 ); then
        touch /tmp/patchcheck/* | echo "pass" >> /tmp/patchcheck/$x
        wc /tmp/patchcheck/* | tail -1
    else
        touch /tmp/patchcheck/* | echo "fail" >> /tmp/patchcheck/$x
        wc /tmp/patchcheck/* | tail -1
    fi
done | awk '{ printf "\r%s", $1} END { print "" }'

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

for x in `cat ${PATCHLIST}`
do
    if showrev -p $x | grep -s $x
    then echo "pass"
    else echo "fail"
    fi >> /tmp/patchcheck/$x
    wc /tmp/patchcheck/* | tail -1
done | awk '{ printf "\r%s", $1} END { print "" }'

Это устраняет touch (который, кажется, мало что делает), и особенно, когда пустой вывод touch передается по каналу echo, который игнорирует его стандартный ввод.Устраняет субоболочку в строке if;он использует опцию -s, равную grep, чтобы сохранять спокойствие.

Я все еще немного сомневаюсь относительно линии wc.Я думаю, что вы хотите подсчитать количество файлов, так как каждый файл должен содержать одну строку (проход или неудача), если вы не указали какой-то патч дважды в файле, обозначенном ${PATCHLIST}.В этом случае я бы, вероятно, использовал:

for x in `cat ${PATCHLIST}`
do
    if showrev -p $x | grep -s $x
    then echo "pass"
    else echo "fail"
    fi >> /tmp/patchcheck/$x
    ls /tmp/patchcheck | wc -l
done | awk '{ printf "\r%s", $1} END { print "" }'

. Здесь перечислены файлы в / tmp / patchcheck и подсчитано количество выводимых строк.Это означает, что вы можете просто напечатать $0 в скрипте awk, поскольку $0 и $1 одинаковы.В той степени, в которой эффективность имеет значение (не много), это более эффективно, потому что ls сканирует только каталог, а не wc открывает каждый файл.Но это, в частности, более точное описание того, что вы пытаетесь сделать.Если позже вы захотите посчитать проходы, вы можете использовать:

for x in `cat ${PATCHLIST}`
do
    if showrev -p $x | grep -s $x
    then echo "pass"
    else echo "fail"
    fi >> /tmp/patchcheck/$x
    grep '^pass$' /tmp/patchcheck/* | wc -l
done | awk '{ printf "\r%s", $1} END { print "" }'

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

1 голос
/ 26 апреля 2012

Вот как мой скрипт установки патча работает так, как я хотел:

while read pkgline
do
    patchadd -d ${pkgline} >> /var/log/patch_install.log 2>&1
    # Create audit file for progress indicator
    for x in ${pkgline}
    do
        if ( showrev -p ${x} | grep -i ${x} > /dev/null 2>&1 ); then
            echo "${x}" >> /tmp/pass
        else
            echo "${x}" >> /tmp/fail
        fi
    done
    # Progress indicator
    for y in `wc -l /tmp/pass | awk '{print $1}'`
    do
        printf "\r${y} out of `wc -l /patchdir/master | awk '{print $1}'` packages installed for `hostname`.  Last patch installed: (${pkgline})"
    done
done < /patchdir/master
...