Передача 'false' не дает не -нулевой код результата

Вы можете попробовать дерево:

tree -d -h --du

-d только печатать каталоги, -du использование диска, -h удобный для человека вывод

7
21.04.2020, 15:31
3 ответа

Результат как true | echo "$?", так и false | echo "$?"вводит в заблуждение. Содержимое "$?"будет установлено до того, как передаст команду falseв команду echo.

Для выполнения этих строк bash устанавливает конвейер команд. Конвейер настроен, затем команды запущены параллельно. Итак, в вашем примере:

true;   echo "$?"      # 0
false;  echo "$?"      # 1
true  | echo "$?"      # 0

совпадает с:

true   
echo "$?"      # 0
false  
echo "$?"      # 1
echo "$?"      # 0

trueне выполняется до тех пор, пока echo $?не выполняется одновременно.

15
19.03.2021, 02:27

Это связано с тем, что обе части конвейера выполняются параллельно, поэтому команда falseеще не завершена (и установите $?), когда команда echoуже начинает печатать $?, что является все еще результат предыдущей команды ; в вашем случае, скорее всего, последний echoвыполнил (и, вероятно, успешно ).

3
19.03.2021, 02:27

В false | echo $?$?не является статусом выхода false, потому что$?расширяется до десятичного статуса выхода самого последнего конвейера [1], а не самой последней команды , подоболочки или дочернего процесса . В false | echo $?, falseне конвейер, а просто его часть. Простая полная команда, такая как false;, является конвейером, даже если не содержит никакого |.

Предполагая, что set -o pipefailвключен и состояние выхода false | echo $?будет таким же, как у false, $?также не может быть выходом из состояния текущего конвейера, поскольку текущий конвейер еще не вышел к тому времени, когда он повторяет это.

Не имеет значения порядок, в котором две стороны конвейера (, которые всегда выполняются параллельно ), запускаются или завершаются, а также то, выполняется ли echo $?фактически в дочернем процессе или подоболочке.

FWIW, когда в подоболочке переменные и другие параметры всегда расширяются в контексте текущей подоболочки :, если false | echo $?реализовано путем разветвления отдельных процессов для обеих сторон конвейера (, что имеет место в bash, но не во всех оболочках ), $?будут расширены в дочернем процессе, после fork()и, возможно, после левой стороны конвейера вышел [2].

And how could I force a failure in a pipe, and get 1 thereafter?

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


[1] 2.5.2 Специальные параметры в стандарте SUSv4. Будет ли подстановка команд считаться конвейером в этом контексте, зависит от оболочки; в большинстве старых и современных оболочек :; echo `exit 13` $?будет печатать 13, но в некоторых (, таких как dash, yash или pdksh -, производных ), он будет печатать 0.

[2] Простой пример bash, который может помочь понять, что это echo $BASHPID >&2 | echo $BASHPID >&2 | echo $BASHPID >&2; переменная BASHPIDявляется не расширенной до того, как будут настроены и запущены 3 дочерних процесса. Специальные параметры, такие как $?, в этом отношении не являются особыми; они расширяются, как и любые другие переменные.

7
19.03.2021, 02:27

Теги

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