Зачем выходить из кода 141 с помощью grep -q?

Может кто-нибудь объяснить, почему я получаю код выхода 141 из ниже?

#!/usr/bin/bash

set -o pipefail

zfs list | grep tank
echo a ${PIPESTATUS[@]}

zfs list | grep -q tank
echo b ${PIPESTATUS[@]}

cat /etc/passwd | grep -q root
echo c ${PIPESTATUS[@]}

Я получаю

...
a 0 0
b 141 0
c 0 0

Из моего понимания код выхода 141 - это сбой, но строка выше дает нуль, поэтому я должен сказать, что это должен быть успех.

Ответ 1

Это связано с тем, что grep -q сразу же выходит с нулевым статусом, как только будет найдено совпадение. Команда zfs все еще записывает в трубку, но нет читателя (потому что grep вышел), поэтому он отправляет сигнал SIGPIPE из ядра и выходит со статусом 141.

Другим распространенным местом, где вы видите это поведение, является head. например.

$ seq 1 10000 | head -1
1

$ echo ${PIPESTATUS[@]}
141 0

В этом случае head считывает первую строку и завершает генерирование сигнала SIGPIPE, а seq - с 141.

См. "Сигнал непонятного SIGPIPE" в Руководстве для программистов Linux.

Ответ 2

Я не знаком с zfs list, но я думаю, что он жалуется на то, что его стандартный вывод закрыт - grep -q выходит сразу после совпадения, в отличие от grep.