Получение PID команды ранее в Pipeline

11

Я пишу сценарий bash, чтобы использовать его inotifywaitдля мониторинга каталога и запуска действий при обнаружении изменений. Что-то типа:

inotifywait -m ... | while read f; do something; done

Так inotifywaitкак сам по себе не завершается, этот скрипт не остановится.

Поэтому я планировал получить PID процесса inotifywait, сохранить его в файл, а потом уничтожить другим процессом, например:

inotifywait -m ... | { echo ??PID?? > pid-file; while ... }

Но я не знаю, как получить PID. Есть ли простой способ добиться этого? Другой способ - просто сохранить PID shell-скрипта $$в файл и убить весь shell-скрипт, но я хотел сделать некоторую очистку после цикла while.

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

Адриан Пронк
источник
Вы можете использовать что-то вроде этого `ps -ef | grep processName | grep -v grep | awk '{print $ 2}' | xargs kill -9 `
Киви
@Kiwy - вместо этого бардака просто сделай pgrep inotifywait. Это даст вам PID, чтобы убить pkill inotifwait.
SLM
@slm, в зависимости от вашей системы, у вас не будет pgrep и pkill, а grep и ps будут присутствовать. Добро пожаловать
Kiwy
@Kiwy - сомнительно, эти инструменты довольно распространены. Также вам не нужно делать grep -v grep, вместо этого ps -ef | grep [p]rocessname...будет делать то же самое.
SLM
1
@DavidsonChua - да, вы можете использовать -fпереключатель, если вам нужно сопоставить больше имени исполняемого файла.
SLM

Ответы:

6

В конвейере все процессы запускаются одновременно , нет ни одного, который раньше, чем другие.

Вы могли бы сделать:

(echo "$BASHPID" > pid-file; exec inotifywait -m ...) | while IFS= read -r...

Или переносимо:

sh -c 'echo "$$" > pid-file; exec inotifywait -m ...' | while IFS= read -r...

Также обратите внимание, что когда подоболочка, выполняющая whileцикл, завершается, inotifywaitона будет автоматически уничтожена при следующей записи чего-либо в стандартный вывод.

Стефан Шазелас
источник
3

Если вам нужен идентификатор процесса в цикле, сначала напечатайте его.

sh -c 'echo "$$"; exec inotifywait -m ...' | {
  read inotifywait_pid
  while IFS= read -r f; do
    
    if …; then kill "$inotifywait_pid"; break;
  done
}
Жиль "ТАК - перестань быть злым"
источник