Подтвердить что ты не робот

Почему ps o/p перечисляет процесс grep после трубы?

Когда я делаю

$ ps -ef | grep cron

Я получаю

root      1036     1  0 Jul28 ?        00:00:00 cron
abc    21025 14334  0 19:15 pts/2    00:00:00 grep --color=auto cron

Мой вопрос, почему я вижу вторую строку. По моему мнению, ps перечисляет процессы и переводит список в grep. grep даже не запускался, пока ps перечисляет процессы, тогда как процесс grep указан в файле o/p?

Второй вопрос:

Когда я делаю

$ ps -ef | grep [c]ron

Я получаю только

root      1036     1  0 Jul28 ?        00:00:00 cron

В чем разница между первой и второй grep исполнениями?

4b9b3361

Ответ 1

При выполнении команды:

ps -ef | grep cron

оболочку, которую вы используете

(... Я предполагаю, что bash в вашем случае из-за атрибута цвета grep. Я думаю, что вы используете систему gnu, такую ​​как дистрибутив linux, но это то же самое на других unix/shell... )

выполнит вызов pipe() для создания FIFO, тогда он будет fork() (создаст собственную копию). Это создаст новый дочерний процесс. Этот новый сгенерированный дочерний процесс будет close() его стандартным дескриптором выходного файла (fd 1) и привязать fd 1 к стороне записи канала, созданного процессом отцов (оболочка, в которой вы выполнили команду). Это возможно, потому что syscall fork() будет поддерживать для каждого действительный открытый файловый дескриптор (в этом случае fd). После этого будет exec() первая (в вашем случае) команда ps, найденная в вашей переменной среды PATH. При вызове exec() процесс станет выполняемой вами командой.

Итак, теперь у вас есть процесс оболочки с дочерним элементом, который в вашем случае является командой ps с атрибутами -ef.

В этот момент отец (оболочка) fork() снова. Этот вновь сгенерированный дочерний процесс close() представляет собой стандартный дескриптор входного файла (fd 0) и прикрепляет fd 0 к стороне чтения канала, созданного процессом отцов (оболочка, в которой вы выполнили команду).

После этого будет exec() первая (в вашем случае) grep команда, найденная в вашей переменной среды PATH.

Теперь у вас есть процесс оболочки с двумя дочерними элементами (которые являются братьями и сестрами), где первая - это команда ps с атрибутами -ef, а вторая - это команда grep с атрибутом cron. Сторона считывания трубы присоединена к команде STDIN команды grep, а сторона записи присоединена к STDOUT команды ps: стандартный вывод команды ps подключен к стандартный ввод команды grep.

Так как ps записывается для отправки стандартной информации вывода в каждом запущенном процессе, в то время как grep записывается, чтобы получить на своем стандартном входе то, что должно соответствовать заданному шаблону, вы получите ответ на свой первый вопрос

  • выполняется оболочка: ps -ef;
  • выполняется оболочка: grep cron;
  • ps отправляет данные (которые даже содержат строку "grep cron" ) на grep
  • grep соответствует шаблону поиска из STDIN и соответствует строке "grep cron" из-за атрибута "cron", который вы передали в grep: вы инструктируете grep для соответствия "cron", и это происходит потому, что "grep cron" является строкой, возвращаемой ps в то время, когда grep запустил ее выполнение.

При выполнении:

ps -ef | grep '[c]ron'

переданный атрибут указывает grep на соответствие тому, что содержит "c" , за которым следует "ron". Как и в первом примере, но в этом случае он сломает строку соответствия, возвращаемую ps, потому что:

  • выполняется оболочка: ps -ef;
  • оболочка работает: rep [c]ron;
  • ps отправляет данные (которые даже содержат строку grep [c]ron) в grep
  • grep не соответствует его шаблону поиска из stdin, потому что строка, содержащая "c" , за которой следует "ron", она не найдена, но она обнаружила строку, содержащую "c" , за которой следует "] ron"

GNU grep не имеет ограничений на соответствие строк, а на некоторых платформах (я думаю, Solaris, HPUX, aix) предел строки задается переменной "$ COLUMN" или шириной экрана терминала.

Надеюсь, этот длинный ответ немного пояснит процесс оболочки.

Совет:

ps -ef | grep cron | grep -v grep

Ответ 2

В вашей команде

ps -ef | grep 'cron'

Linux выполняет команду grep перед командой ps -ef. Затем Linux сопоставляет стандартный вывод (STDOUT) "ps -ef" со стандартным входом (STDIN) команды grep.

Он не выполняет команду ps, сохраняет результат в памяти и передает ее в grep. Подумайте об этом, почему? Представьте себе, если бы вы собирали сотни гигабайт данных?

Изменить В отношении вашего второго вопроса:

В grep (и большинстве движков регулярных выражений) вы можете указать скобки, чтобы они знали, что вы примете ЛЮБОЙ символ в скобках. Поэтому запись [c] означает, что он примет любой charcter, но указывается только c. Точно так же вы можете сделать любую другую комбинацию символов.

ps aux | grep cron
root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron
root     23744  0.0  0.0  14564   900 pts/0    S+   21:13   0:00 grep --color=auto cron

^ Это соответствует самому себе, потому что ваша собственная команда содержит "cron"

ps aux | grep [c]ron
root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron

Это соответствует cron, потому что cron содержит c, а затем "ron". Это не соответствует вашему запросу, потому что ваш запрос [c] ron

Вы можете поместить все, что хотите, в скобки, если оно содержит c:

ps aux | grep [cbcdefadq]ron
root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron

Если вы удалите C, это не будет соответствовать, потому что "cron" начинается с c:

ps aux | grep [abedf]ron

^ Не имеет результатов

Изменить 2

Чтобы повторить этот момент, вы можете делать всевозможные сумасшедшие вещи с помощью grep. Нет никакого смысла в выборе первого символа, чтобы сделать это с.

ps aux | grep [c][ro][ro][n]
root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron

Ответ 3

Оболочка конструирует ваш конвейер с помощью цепочек вызовов fork(), pipe() и exec(). В зависимости от оболочки любая ее часть может быть построена первой. Так что grep может быть запущен до начала ps. Или, даже если сначала начинается ps, он будет записывать в буфер ядра ядра 4k и в конечном итоге будет блокировать (при печати строки вывода процесса) до тех пор, пока grep не запустится и не начнет потреблять данные в трубе. В последнем случае, если ps может начать и закончить до начала grep, вы можете не увидеть grep cron на выходе. Возможно, вы уже заметили, что этот детерминизм уже играет.

Ответ 4

На ваш вопрос был дан ответ другими, но я предлагаю совет: если вы хотите избежать просмотра процесса grep, вы можете сделать это следующим образом:

$ ps -ef | grep [c]ron

Ответ 5

Вы писали: "С моей точки зрения, ps перечисляет процессы и пересылает список в grep. grep даже не запускался, а ps перечисляет процессы".

Ваше понимание неверно.

Это не работает трубопровод. Оболочка не запускает первую команду для завершения, запоминает вывод первой команды, а затем запускает следующую команду, используя эти данные в качестве входных данных. Нет. Вместо этого оба процесса выполняются, и их входы/выходы подключены. Как писал Бен Джексон, нет ничего особого, чтобы гарантировать, что процессы будут работать в одно и то же время, если они оба очень недолговечны, и если ядро ​​может с комфортом управлять небольшим количеством данных, проходящих через соединение. В этом случае это действительно может произойти так, как вы ожидаете, только случайно. Но концептуальная модель должна иметь в виду, что они работают параллельно.

Если вы хотите использовать официальные источники, как насчет страницы bash man:

  A pipeline is a sequence of one or more commands separated by the character |.  The format for a pipeline is:

         [time [-p]] [ ! ] command [ | command2 ... ]

  The  standard  output  of command is connected via a pipe to the standard input of command2.  This connection is
  performed before any redirections specified by the command (see REDIRECTION below).

  ...

  Each command in a pipeline is executed as a separate process (i.e., in a subshell).

Что касается вашего второго вопроса (на самом деле это не совсем связано, я сожалею), вы просто описываете, как работают регулярные выражения. Регулярное выражение cron соответствует строке cron. Регулярное выражение [c]ron не соответствует строке [c]ron. Таким образом, первая команда grep окажется в списке процессов, а вторая не будет.

Ответ 6

$ ps -ef | grep cron

Linux Shell всегда выполняет команду справа налево. поэтому перед выполнением ps -ef grep cron уже выполнил то, почему o/p показывает команду.

$ ps -ef | grep [c]ron

Но в этом u указан grep ron, за которым следует только c. поэтому o/p не имеет командной строки, потому что в команде есть [c] ron.

Ответ 7

pgrep иногда лучше, чем ps -ef | grep word, потому что он исключает grep. Попробуйте

pgrep -f bash
pgrep -lf bash