Является ли статус выхода команды, выполняемой командой или процессом оболочки, который выполняет команду?

Из руководства по bash

Статус выхода исполняемой команды – это значение, возвращаемое системным вызовом waitpid или эквивалентной функцией. Статусы выхода находятся между 0 и 255, однако, как объясняется ниже, оболочка может использовать значения выше 125 специально. Выходные статусы из встроенных команд оболочки и составных команд также ограничены этим диапазоном. При определенных обстоятельствах оболочка будет использовать специальные значения для указания конкретных режимов отказа.

  1. Что определяет статус выхода выполненной команды,

    • сама команда, т. е. реализация команды определяет статус выхода, т. е. определение статуса выхода исполняемой команды, присущего ей свойства, подобно тому как разбор аргументов командной строки на выполнение команды присущ команды или
    • процесс оболочки, который выполнил команду?
      Системный вызов waitpid упомянутый выше, мне кажется, что статус выхода исполняемой команды реализуется процессом оболочки, а сама команда не имеет никакого отношения к статусу выхода самого выполнения.
  2. В процессе bash, когда мы можем получить статус выхода выполненной команды,

    • только когда процесс bash является интерактивным, или
    • независимо от того, является ли процесс bash интерактивным или неинтерактивным? Когда процесс bash не является интерактивным, как мы можем получить статус выхода команды, выполняемой в процессе bash?

Сама команда может предоставить статус выхода через аргумент системному вызову exit() . Оболочка (или другая программа, как насчет system() в Perl или PHP?) Может подобрать дочерний процесс «exit status» через wait() или waitpid() системные вызовы. Ядра Unix / Linux / * BSD организуют доставку SIGCHLD в родительский процесс, когда дочерний процесс изменяет статус.

Но есть и другие обстоятельства. Процесс, завершенный через SIGKILL, не имеет возможности выйти. Процесс, который разыскивает неверный адрес, не будет иметь возможности вызвать exit() если у него не установлен обработчик сигнала SIGSEGV. В этих случаях ядро ​​вычисляет статус выхода, который включает бит, который означает «убитый сигналом», и какой сигнал заставлял процесс быть убитым. Этот статус вычисленного ядра выдается в родительский процесс убитого процесса.

Код устанавливает статус выхода

 $ perl -e 'END { $? = 42 }'; echo $? 42 $ 

за исключением случаев, когда

 $ perl -e 'sleep 999; END { $? = 42 }' ^C $ echo $? 130 $ echo $((130-128)) 2 $ kill -l | head -2 1 HUP Hangup 17 STOP Stopped (signal) 2 INT Interrupt 18 TSTP Stopped $ 

или делает

 $ perl -e '$SIG{INT}=sub{exit 7};sleep 999' ^C$ echo $? 7 $ 

или не нужно, чтобы кто-то общался с SIGKILL и т. д.

В противном случае документация bash вводит в заблуждение в том, что waitpid устанавливает 16-битное слово состояния, но bash передает только подмножество этого в переменной оболочки $? , Это может привести к незнанию и путанице, если пользователь оболочки попытается waitpid результаты waitpid как если бы это было 8-битное значение (это не так).

 $ false; echo $? 1 $ perl -E 'system("false"); say $?' 256 $ perl -E 'system("false"); say $? >> 8' 1 $ 

Процесс определяет собственный код выхода. Когда он завершается, он предоставляет код выхода или, если ни один не указан, считается, что он равен нулю (без ошибок).

Как с интерактивными, так и с неинтерактивными оболочками код выхода предыдущей команды можно получить через значение $? ,