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

8

Я хочу порождать два дочерних процесса, но подождите, пока первый не достигнет определенной точки своего выполнения (которую можно определить, изучив stdout), прежде чем порождать второй. Я не уверен, какие Unix-команды будут задействованы для достижения этой цели, и им было трудно найти что-либо через Google из-за краткой, а иногда и загадочной природы имен Unix-команд.

Я не ищу решения конкретной проблемы, которую пытаюсь решить (хотя любые дополнительные указатели были бы оценены), я в первую очередь беспокоюсь о том, какие команды Unix я бы хотел найти и научиться использовать.

w.brian
источник
Вы открыты для использования Python?
xrisk
3
Не зная, как вы определяете «определенную точку в его исполнении», это очень расплывчато.
Муру
@muru отредактировано, чтобы уточнить
w.brian
Таким образом, вам на самом деле нужно 3 процесса. 1. работает, создает вывод; 2. контролирует вывод 1 и в определенный момент запускается 3. Этой информации достаточно, чтобы вы начали делать все, что вы делаете. Но это не очень хороший способ разработки программы.
djsmiley2kStaysInside

Ответы:

7

Вы можете использовать xargsутилиту для этого. Он может запускать команду для каждой строки в stdin, поэтому нам просто нужно убедиться, что xargsполучает в качестве входных данных одну строку в stdin во время запуска команды, что может быть выполнено с помощью grep:

proc1 | grep --max-count=1 "${targetString}" | xargs --max-lines=1 --no-run-if-empty --replace -- proc2

Аргументы --max-count=1, --max-lines=1и --no-run-if-emptyубедитесь, что proc2запускается ровно один раз, если и когда proc1выводит ${targetString}в первый раз, и никогда, если proc1никогда не выводит ${targetString}. В --replaceизбегает , что xargsдобавляет строку ввода в его командной строке.

Я использовал следующую командную строку, чтобы проверить это:

(echo Start >&2; sleep 3 ; echo Trigger; sleep 3; echo End >&2) | grep --max-count=1 Trigger | xargs --max-lines=1 --no-run-if-empty --replace -- echo "Triggered"
Филипп Вендлер
источник
1
+1 Это очень креативный ответ. Это будет значительно сложнее, если вам понадобится остальная часть вывода proc1. Вам нужно будет использовать такие вещи, как tee и дополнительные файловые дескрипторы или именованные каналы.
Джо
7

Я не уверен, что есть изящная команда / ответ на вопрос, который вы задали (т. Е. Достичь определенной точки в его выполнении), - но есть инструменты / методы, которые можно использовать, чтобы найти решение, возможно, включающее более 1 следующее, а может и другие вещи, о которых я пока не знаю:

  1. Фоновые процессы (&)
  2. Условное исполнение (&& и ||)
  3. спать
  4. подождите (я ожидаю, что это будет особенно полезно - если вы запустите более 1 задания в фоновом режиме, он будет ждать, пока все задания не будут завершены)
  5. Именованные каналы (которые могли бы обеспечить механизм общения между процессами).
  6. inodenotifywait

Написание и проверка файлов блокировки также является обычной практикой (совет: если у вас есть контроль над средой, пишите на виртуальный диск, а не в / tmp - во многих дистрибутивах это / dev / shm).

davidgo
источник
6

Это всего лишь идея, но первый процесс должен передать свой вывод в grep. Пусть grep направит свой вывод в цикл чтения строки и сравнит каждую строку с тем, что вы ищете. Найдя, выполните proc2.

#!/bin/bash
targetString="line you are looking for"
proc1 | grep "${targetString}" |
while read line
do
if [ "$line" = "${targetString}" ]; then
    proc2
fi
done

Если «определенная точка в его исполнении» может быть определена stdout, то как насчет следующего?

proc1 | grep "stdout trigger string" && proc2

&&должен срабатывать при grepвозврате 0, что он делает только тогда, когда находит совпадение.

Луи Ваверу
источник
1
grep будет продолжать работать до тех пор, пока stdin не закроется. До этого ничего не вернется (0 или иначе).
Боб
@ Боб О, спасибо ... Я постараюсь перефразировать эту идею.
Луи Ваверу
@bob Это было бы особенно беспорядочно и несвязно, и злоупотребление инструментом, но вы могли бы использовать fail2ban для мониторинга файла журнала (то есть stdout канала в файл), а затем запрограммировать правило для выполнения второго сценария, когда эта строка найдено (но я повторно изменяю файл триггера и использую inotify - более элегантное решение)
davidgo
1
Если targettring встречается в выходных данных proc1 более одного раза, proc2 будет запущен несколько раз. Если вы сделали proc2 &и то break, что бы не случилось, но что бы закрыть трубу и сделать proc1 прекращается досрочно. В качестве альтернативы, вы можете установить флаг после запуска proc2 и использовать его, чтобы убедиться, что proc2 больше не запускается. Как и в случае с другим ответом, остальные выходные данные proc1 отбрасываются, поэтому, если вам это нужно, требуется больше работы.
Джо
1
@Joe Хорошая мысль. Первоначальный вопрос на самом деле был просто вопрос о том, с какими командами было доступно работать, так что на самом деле это просто ответ, демонстрирующий потенциал некоторых из этих команд (в основном |и grepздесь).
Луи Ваверу