PIPESTATUS: как узнать, какая команда в пайпе реально упала
В Bash есть неприятная особенность: после пайпа $? показывает статус только последней команды.
Например:
false | grep test
echo $?
Здесь grep успешно отработал и вернул 0, поэтому ошибка false потерялась.
▪️На помощь приходит PIPESTATUS
Сразу после выполнения пайпа:
false | grep test
echo "${PIPESTATUS[@]}"
Получим:
1 1
Каждое значение соответствует своей команде.
false → 1
grep test → 1
▪️Более наглядный пример
cat /missing/file | grep ERROR | sort
echo "${PIPESTATUS[@]}"
Можно получить:
1 1 0
То есть cat завершился с ошибкой, grep ничего не получил, а sort технически выполнился успешно.
▪️Важный нюанс
PIPESTATUS очень легко потерять:
false | true
echo "${PIPESTATUS[@]}"
работает.
Но если между пайпом и проверкой выполнить другую команду:
false | true
echo "check"
echo "${PIPESTATUS[@]}"
теперь PIPESTATUS относится уже к echo "check".
Поэтому сохраняйте его сразу:
false | true
status=("${PIPESTATUS[@]}")
echo "${status[@]}"
▪️А если нужен общий статус пайпа?
Есть:
set -o pipefail
Теперь:
false | true
echo $?
вернёт ненулевой код.
Но pipefail отвечает только на вопрос «пайп завершился успешно?», а PIPESTATUS позволяет понять «какая именно команда вернула ошибку?».
▪️Почему это важно
В сложных Bash-конвейерах последняя команда может успешно завершиться даже тогда, когда предыдущая уже упала. PIPESTATUS позволяет не терять эти ошибки и точно определить проблемный этап.
BashTex 📱 #bash #utils
В Bash есть неприятная особенность: после пайпа $? показывает статус только последней команды.
Например:
false | grep test
echo $?
Здесь grep успешно отработал и вернул 0, поэтому ошибка false потерялась.
▪️На помощь приходит PIPESTATUS
Сразу после выполнения пайпа:
false | grep test
echo "${PIPESTATUS[@]}"
Получим:
1 1
Каждое значение соответствует своей команде.
false → 1
grep test → 1
▪️Более наглядный пример
cat /missing/file | grep ERROR | sort
echo "${PIPESTATUS[@]}"
Можно получить:
1 1 0
То есть cat завершился с ошибкой, grep ничего не получил, а sort технически выполнился успешно.
▪️Важный нюанс
PIPESTATUS очень легко потерять:
false | true
echo "${PIPESTATUS[@]}"
работает.
Но если между пайпом и проверкой выполнить другую команду:
false | true
echo "check"
echo "${PIPESTATUS[@]}"
теперь PIPESTATUS относится уже к echo "check".
Поэтому сохраняйте его сразу:
false | true
status=("${PIPESTATUS[@]}")
echo "${status[@]}"
▪️А если нужен общий статус пайпа?
Есть:
set -o pipefail
Теперь:
false | true
echo $?
вернёт ненулевой код.
Но pipefail отвечает только на вопрос «пайп завершился успешно?», а PIPESTATUS позволяет понять «какая именно команда вернула ошибку?».
▪️Почему это важно
В сложных Bash-конвейерах последняя команда может успешно завершиться даже тогда, когда предыдущая уже упала. PIPESTATUS позволяет не терять эти ошибки и точно определить проблемный этап.
BashTex 📱 #bash #utils