склонный - получают статус выхода обновления

(Так как алгоритмы только для оболочки оказались значительно медленнее, чем внешние инструменты, я просто удалил любые ссылки на них. Исходные данные могли бы быть интересными все же.)

Данные тестирования:

Prepare to remove role foo
Delete Successful
Prepare to remove role bar
Failed to delete role bar: 1
Prepare to remove policy baz
Delete Successful
Prepare to remove role ban
Delete Successful
something
else
Prepare to remove role bay
Failed to delete role bar: 2
Prepare to remove role bat
Failed to delete role bar: 1

Сравнительный тест с данными тестирования выше повторил миллион раз (это составляет 306 МБ), лучше всего из трех чередованных выполнений, отсортированных путем увеличения real время:

Тестовый код:

for index in {1..3}
do
    for path in grep.sh awk.sh
    do
        echo "$path:"
        time bash "$path"
        echo
    done
done

Система тестирования: Intel Core i7 3,07 ГГц с 6 ГБ RAM.

8
20.12.2014, 14:21
5 ответов

В вашем примере apt-get update не выходил с ошибкой, потому что считал проблемы предупреждениями, а не смертельно плохими. Если есть действительно фатальная ошибка, то она выйдет со статусом ненулевого.

Одним из способов распознавания аномалий является проверка этих закономерностей в stderr:

  • Линии, начинающиеся с W: - это предупреждения
  • Lines, начинающиеся с E: являются ошибками

Можно использовать нечто подобное, чтобы эмулировать сбой в случае совпадения вышеуказанных шаблонов, или код выхода самого apt-get update ненулевой:

if ! { sudo apt-get update 2>&1 || echo E: update failed; } | grep -q '^[WE]:'; then
    echo success
else
    echo failure
fi

Обратите внимание на ! в if. Это потому, что grep успешно выходит, если шаблон был совпаден, то есть, если бы были ошибки. Когда ошибок нет, сам grep grep не будет работать. Поэтому условием if является отрицание кода выхода grep.

6
27.01.2020, 20:12

Если вы хотите, чтобы apt-get out / err не был съеден (например, если запись в файл журнала), это может быть более простой альтернативой:

sudo apt-get update 2> & 1 | тройник /tmp/apt.err &&! grep -q '^ [WE]' /tmp/apt.err

Было бы неплохо, если бы это не оставило новый файл, который можно было удалить позже, но если мы, скажем, процесс заменим grep на тройник output кажется сложнее получить код выхода.

1
27.01.2020, 20:12

Я столкнулся с той же проблемой, и я хотел бы предложить другое решение, основанное на tee(, например решение @user4122451 ), но не создает временный файл, а также дает сбой, если sudo apt-get updateвозвращает ненулевой код выхода, отличный от -, без вывода некоторой строки W:, E:или Err::

exec {fd}>&2 # copy stderr to some unused fd
bash -o pipefail -c "sudo apt-get update -y -q 2>&1 | tee /dev/fd/$fd | ( ! grep -q -e '^Err:' -e '^[WE]:' )"
result=$?
exec {fd}>&- # close file descriptor

В частности, это решение основано на параметреset -o pipefailbash (, гарантирующем, что конвейер возвращает значение самой правой команды для выхода с ненулевым -статусом, в противном случае — нулевым )и использует дополнительный пронумерованный файл. дескриптор (см. также этот ответ SO).

Если вам не нужно делать параметр pipefailлокальным, вы можете просто написать:

set -o pipefail
exec {fd}>&2 # copy stderr to some unused fd
sudo apt-get update -y -q 2>&1 | tee /dev/fd/$fd | ( ! grep -q -e '^Err:' -e '^[WE]:' )
result=$?
exec {fd}>&- # close file descriptor
1
27.01.2020, 20:12

Вы можете использовать специальную переменную $? чтобы проверить статус выхода вашей последней команды. Вы также можете сначала перенаправить вывод ошибок на стандартный вывод.

OUTPUT=`apt-get update 2>&1`

if [[ $? != 0 ]]; then
  echo "$OUTPUT"
fi
0
15.11.2020, 13:28

Используйте этот параметр apt, чтобы превратить эти предупреждения в ошибки:

apt-get update -o APT::Update::Error-Mode=any

Вы также можете установить это в файлах конфигурации, если хотите.

2
08.06.2021, 12:29

Теги

Похожие вопросы