Intereting Posts
Замените python, созданный с помощью UCS4 с UCS2 анонимный или гостевой вход в vsftpd? Пользовательские настройки для monit? Должна ли она выполняться как root или ее собственный пользователь? добавление фильтра regexp для блокировки субдомена и TLD в sendmail Запретить запуск tmux на SSH DLNA-сервер в Linux Сбой соединения SSH из-за проблем с разрешениями Как я могу найти объем памяти, потребляемый процессом? Почему в этой команде не будет работать grep? Помогите мне понять, почему эта функция bash не работает рекурсивно Как заставить dhcpcd забыть старый статический адрес после редактирования dhcpcd.conf? Изменить раздел дисковой части ZFS Raid Как получить `pdftotext` для вывода текста в читаемом кодировании? Какую команду следует использовать для перемещения этих конкретных элементов? Почему другой пользователь не может получить доступ к моему файлу, когда это полный путь?

Как фиксировать статус выхода команды без конечного результата в конвейере?

Я хочу захватить статус выхода команды, которая происходит где-то в конвейере до последней позиции. Например, если конвейер похож на

command_1 ... | command_2 ... | command_3 ... | ... | command_n 

… Я хотел бы знать, как захватить статус выхода command_1 , или command_2 , или command_3 , и т. Д. ( command_3 , захват статуса command_n является тривиальным).

Кроме того, в случае, если это имеет значение, этот конвейер встречается внутри функции оболочки zsh.


Я попытался захватить статус выхода command_1 с чем-то вроде

 function_with_pipeline () { local command_1_status=-999999 # sentinel value { command_1 ...; command_1_status=$? } | command_2 ... | ... | command_n ... } 

… но после запуска конвейера значение переменной command_1_status прежнему было дозорным значением.


FWIW, вот рабочий пример, где в конвейере есть только две команды:

 foo ... | grep ... 

foo – функция, определенная для этого примера, например:

 foo () { (( $1 & 1 )) && echo "a non-neglible message" (( $1 & 2 )) && echo "a negligible message" (( $1 & 4 )) && echo "error message" >&2 return $(( ( $1 & 4 ) >> 2 )) } 

Цель состоит в том, чтобы зафиксировать статус выхода вызова для foo в конвейере.

Функция function_with_pipeline реализует (в конечном счете, неэффективную) стратегию, описанную выше, для этого:

 function_with_pipeline () { local foo_status=-999999 # sentinel value { foo $1; foo_status=$? } | grep -v "a negligible message" printf '%d\ndesired: %d; actual: %d\n\n' $1 $(( ( $1 & 4 ) >> 2 )) $foo_status } 

Цикл ниже выполняет function_with_pipeline function_with_pipeline. Результат показывает, что значение локальной переменной foo_status ничем не отличается от того, как она была запущена.

 for i in $(seq 0 7) do function_with_pipeline $i done # 0 # desired: 0; actual: -999999 # # a non-neglible message # 1 # desired: 0; actual: -999999 # # 2 # desired: 0; actual: -999999 # # a non-neglible message # 3 # desired: 0; actual: -999999 # # error message # 4 # desired: 1; actual: -999999 # # error message # a non-neglible message # 5 # desired: 1; actual: -999999 # # error message # 6 # desired: 1; actual: -999999 # # error message # a non-neglible message # 7 # desired: 1; actual: -999999 # 

Я получаю те же результаты, если я опускаю local декларацию в определении foo_status .

Для zsh существует специальный массив pipestatus , поэтому попробуйте

 command_1 ... | command_2 ... | command_3 

а также

 echo $pipestatus[1] $pipestatus[2] $pipestatus[3] 

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


Для справки, это PIPESTATUS (с заглавными буквами) в bash .

mispipe работает в любой оболочке. Синтаксис (по сравнению с регулярным каналом) работает следующим образом:

 mispipe true false ; echo $? # returns exit code of 1st command `true` true | false ; echo $? # returns exit code of 2nd command `false` 

Вывод:

 0 1 

Что делать, если есть более двух программ:

 # this still returns exit code of 1st command `true` mispipe true 'false | false | false' ; echo $? 

Вывод:

 0 

Несмотря на отсутствие видимого | , он по-прежнему ведет себя как труба:

 yes | mispipe head 'wc -c' 

Вывод:

  20