Несколько команд и выполнение подоболочки после конвейера

Да, он содержит информацию о выходе из системы.

Когда сеанс интерактивного входа в TUI завершается, в эту таблицу вводится запись DEAD_PROCESS, заменяющая предыдущую USER_PROCESS. Эта запись не живет долго (в некоторых системах, по крайней мере ), так как управление службой входа в систему терминала вскоре повторно использует службу входа в систему, перезаписывая запись DEAD_PROCESSновой GETTY_PROCESSили LOGIN_PROCESS. Но там его можно найти.

В других системах, где нет таких вещей, как запись GETTY_PROCESSили LOGIN_PROCESS, она живет несколько дольше, и с ней легче столкнуться. Тем не менее, это трудно увидеть без программного доступа к таблице, так как утилиты обычно отфильтровывают DEAD_PROCESSзаписи при печати содержимого таблицы.

Кроме того, :из-за ошибок в этой таблице будут DEAD_PROCESSзаписи для сеансов входа в систему с графическим интерфейсом из некоторых современных сред рабочего стола без ограничений.

Дополнительная литература

1
11.03.2020, 13:47
3 ответа

Во-первых, чтобы согласовать несколько имен, вот как оболочка интерпретирует ваш ввод:

$ a=1; a=2; a=10 | echo $a
  ^^^  ^^^  ^^^^^^^^^^^^^^
    \    \         \_ Pipeline
     \    \_ Simple command
      \_ Simple command

Конвейер состоит из двух простых команд:

$ a=10 | echo $a
  ^^^^   ^^^^^^^
     \       \_ Simple command
      \_ Simple command

(Обратите внимание, что, хотя это может быть неясно указано в руководстве Bash, грамматика оболочки POSIX позволяет состоять из простой команды простого присвоения переменной ).

a=1;и a=2;не являются частью какого-либо конвейера. ;завершает конвейер, за исключением случаев, когда он появляется как часть составной команды . Как, например,:

{ a=1; a=2; a=10; } | echo $a

В вашем примере a=10и echo $aвыполняются в двух разных , независимых средах подоболочки 1 , обе созданы как копии основной среды. Вложенные оболочки не должны изменять свою родительскую среду выполнения 2 . Цитирование соответствующего раздела POSIX:

A subshell environment shall be created as a duplicate of the shell environment [...] Changes made to the subshell environment shall not affect the shell environment.

и

Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment. All other commands shall be executed in the current shell environment.

Таким образом, в то время как все команды в ваших примерах фактически выполняются, присваивания в левой части ваших конвейеров не имеют видимого эффекта :они только изменяют копии aв соответствующих средах подоболочек, которые теряется, как только подоболочки заканчиваются.

Единственный способ, которым подоболочки на двух концах канала могут напрямую взаимодействовать друг с другом, — это посредством самого канала — стандартного выхода левой стороны, соединенного со стандартным входом правой стороны. Поскольку a=10ничего не отправляет по каналу, он никак не может повлиять на echo $a.


1Если установлена ​​опция lastpipe, (она отключена по умолчанию и может быть включена с помощью встроенной команды shopt), Bash может выполнять последнюю команду конвейера в текущей оболочке.. См. Конвейеры в руководстве Bash. Однако это не имеет отношения к контексту вашего вопроса.

2Вы можете найти более подробную информацию с практической/исторической точки зрения о U&L, например. в этот ответ на Почему последняя функция, выполняемая в конвейере сценария оболочки POSIX, не сохраняет значения переменных?

2
28.04.2021, 23:20

Прошу прощения за мой английский, я его еще учу. Я также новичок в Bash, поэтому, пожалуйста, исправьте все ошибки, которые я сделал в своем ответе, спасибо.

Сначала укажу на ошибку.

  • В a=10 | echo $aвы передаете (конвейер с помощью оператора конвейера;|)a=10для повторения команды. Конвейер соединит stdoutкоманду с stdinкоманды2, то есть command | command2.

  • a=10— это присваивание переменной, я предполагаю, что для него нет stdout, так как это не команда. Если вы выполняете подстановку команды в значении присваивания переменной, это не работает. Если я попробую следующее:

    user@host$ a=$(b=10); echo $a
    

    echo $aне возвращает значение 10. Когда я изменил его на

    user@host$ a=$(b=10; echo $b)
    

    вызов

    $ echo $a
    

    возвращено 10. Итак, я, вероятно, прав, предполагая, что назначение переменной не является командой (даже при ручном определении bash это не команда ).

Во-вторых, команда echoне получает ввод от stdin, она выводит свои аргументы.

user@host$ echo "I love linux" | echo

ничего не вернет. Вы можете использовать команду xargs, чтобы преодолеть это :

.
user@host$ echo "I love linux" | xargs echo

вернет I love linux. Таким образом, конвейер не работает напрямую с командой echo, поскольку он печатает свои аргументы, а не stdin.

Теперь к вашим испытаниям

  • В вашем распоряжении

    user@host$ a=1; a=2; a=10 | echo $a
    

    переменной aсначала присваивается значение 1, затем значение переменной изменяется на 2, как в текущей среде оболочки. Команды обычно запускаются в оболочке sub -. a=10 | echo $a— это список, т. е. эквивалент (a=10 | echo $a), который запускается в оболочке sub -, но он не работает, так как echoне принимает stdin, а только выводит свой аргумент. Здесь аргументом является $a, значение переменной aв оболочке sub -, которая равна 2.

  • Кроме того, a=10не производит никакого вывода, так как это присваивание переменной. Так,в действительности echo $aпечатает значение своего аргумента, которое равно 2и ничего не берет из a=10 | <... >. Таким образом, оператор трубы здесь не должен использоваться; вместо этого вы можете разделить имя команды и назначение переменной разделителем (, точкой с запятой -двоеточием ), и все будет работать нормально, как в (a=10; echo $a).

Чтобы лучше понять это, вы можете попробовать следующие примеры с включенной опцией отладки bash:

user@host$ a=1; a=2; a=10; echo $a;
  • В приведенной выше командной строке echo $aдает 10.

  • Если я изменю его на

    user@host$ a=1; a=2; (a=10; echo $a)
    

    первое и второе назначение переменных задаются в текущей оболочке, третье назначение переменной и команда echoвыполняются в подчиненной -оболочке. Следовательно, значение aравно 10в оболочке sub -, в которой также выполняется команда echo, поэтому возвращается 10. После того, как вы получите свое приглашение, если вы введете команду echo $a, она вернет 2, так как назначения переменных из вспомогательной оболочки -не переносятся обратно в родительскую оболочку.

  • Еще одно замечание: разделитель команд ;выполняет команды последовательно.

В тестовых примерах «A» и «B» последнее присвоение переменной(a=10в тесте A и a=20в тесте B )фактически выполняется, но оно выполняется после команды echo $a, поэтому вы получаете результат предыдущего значения переменной a, которая находится в среде оболочки sub -, после чего выполняются последние назначения переменных. В конвейере stdinи stdoutдвух команд соединяются до того, как команда будет выполнена, также назначения переменных ничего не производят на стандартный вывод.

tl;dr:Присваивание переменной не должно использоваться в конвейере. echoне работает напрямую в конвейере.

1
28.04.2021, 23:20

Вот,

a=20 | echo $a

Трубка только добавляет путаницы. Присваивание слева ничего не выводит на стандартный вывод, а echoничего не читает из стандартного ввода, поэтому данные не перемещаются по каналу. Аргумент echoпросто расширен по сравнению с тем, что было установлено ранее.

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

Вместо этого, если вы сделаете это:

{ a=999; echo a=$a; } | cat

конвейер имел бы больше смысла, и строка a=999проходила бы через него.

touch fileA.txtв последнем примере работает, потому что влияет на систему вне оболочки. Точно так же вы можете писать в stderr из команд в канале и видеть, как результат появляется на терминале:

$ echo a >&2 | echo b >&2 | echo c >&2
b
c
a

(Именно такой порядок вывода я получил с помощью Bash в своей системе.)

1
28.04.2021, 23:20

Теги

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