При работе с конвейерами (пайпами, «трубами», pipe), часто возникает вопрос, как отловить ошибку, произошедшую внутри конвейера.
Для примера возьмем код, где ход загрузки файла отображается dialog’овым прогрессбаром (копия):
#!/bin/bash
FADDR="http://tolik-punkoff.com/static/test.mp3"
wget --progress=dot -O "./test.mp3" "$FADDR" 2>&1 |\
stdbuf -o0 awk '/[.] +[0-9][0-9]?[0-9]?%/ { print substr($0,63,3) }' | \
dialog --gauge "Download file from $FADDR" 10 100
Как видите, конвейер (т.е. передача вывода от одной команды другой через |), тут налицо.
Если после данной команды просто дописать echo $?, то будет видно, что результат будет 0.
И когда все в порядке:

И когда все не в порядке (в данном случае, сделан обрыв связи):

На самом деле, это происходит потому, что в переменной $? оказывается код завершения последней команды в pipe.
В современных версиях bash перед использованием контейнера, необходимо добавить команду:
set -o pipefail
В старых bash и некоторых других оболочках придется извращаться, может как-нибудь вернусь к вопросу (если для какого утюга что писать буду).
После добавления вышеуказанной команды в скрипт делаем тест с обрывом связи:

Или указываем в переменной $FADDR некорректный адрес:

Теперь echo $? отображает корректный код завершения.
С учетом вышеизложенного, а так же с учетом знания о кодах завершения wget (копия) и о том, что wget портит файлы в случае ошибки загрузки (копия) можно красиво модифицировать скрипт, чтоб он сообщал пользователю о результате после загрузки.
#!/bin/bash
FADDR="http://tolik-punkoff.com/static/test.mp3"
FPATH="./test.mp3"
messagebox() #1 - title $2 - message
{
dialog --title "$1" --msgbox "$2" 10 41
}
set -o pipefail
wget --progress=dot --tries=10 --timeout=30 -O "$FPATH" "$FADDR" 2>&1 |\
stdbuf -o0 awk '/[.] +[0-9][0-9]?[0-9]?%/ { print substr($0,63,3) }' | \
dialog --gauge "Download file from $FADDR" 10 100
RETVAL=$?
case "$RETVAL" in
0)
messagebox "Complete!" "File downloaded!"
;;
1)
messagebox "Error" "Generic error ($RETVAL)"
;;
2)
messagebox "Error" "Command line or config error ($RETVAL)"
;;
3)
messagebox "Error" "I/O error ($RETVAL)"
;;
4)
messagebox "Error" "Network failure ($RETVAL)"
;;
5)
messagebox "Error" "SSL verification failure ($RETVAL)"
;;
6)
messagebox "Error" "Username/password authentication failure ($RETVAL)"
;;
7)
messagebox "Error" "Protocol error ($RETVAL)"
;;
8)
messagebox "Error" "Server error ($RETVAL)"
;;
*)
messagebox "Error" "Unknow error ($RETVAL)"
;;
esac
#remove wrong file if exist
if [ "$RETVAL" -ne 0 ];then
if [ -e "$FPATH" ];then
rm "$FPATH"
fi
fi
Все ОК:

Обрыв связи:

Неверный адрес:
