Да, он содержит информацию о выходе из системы.
Когда сеанс интерактивного входа в TUI завершается, в эту таблицу вводится запись DEAD_PROCESS
, заменяющая предыдущую USER_PROCESS
. Эта запись не живет долго (в некоторых системах, по крайней мере ), так как управление службой входа в систему терминала вскоре повторно использует службу входа в систему, перезаписывая запись DEAD_PROCESS
новой GETTY_PROCESS
или LOGIN_PROCESS
. Но там его можно найти.
В других системах, где нет таких вещей, как запись GETTY_PROCESS
или LOGIN_PROCESS
, она живет несколько дольше, и с ней легче столкнуться. Тем не менее, это трудно увидеть без программного доступа к таблице, так как утилиты обычно отфильтровывают DEAD_PROCESS
записи при печати содержимого таблицы.
Кроме того, :из-за ошибок в этой таблице будут DEAD_PROCESS
записи для сеансов входа в систему с графическим интерфейсом из некоторых современных сред рабочего стола без ограничений.
pututxline
. Базовые характеристики . IEEE 1003.1 :2017. Открытая группа.Во-первых, чтобы согласовать несколько имен, вот как оболочка интерпретирует ваш ввод:
$ 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, не сохраняет значения переменных?
Прошу прощения за мой английский, я его еще учу. Я также новичок в 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
не работает напрямую в конвейере.
Вот,
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 в своей системе.)