Obtendo o PID do comando anteriormente no Pipeline

11

Estou escrevendo um script bash inotifywaitpara monitorar um diretório e iniciar ações quando alterações são detectadas. Algo como:

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

Como inotifywaitnão termina sozinho, esse script não será interrompido.

Portanto, meu plano era obter o PID do processo inotifywait, salvá-lo em um arquivo e fazer com que um processo diferente o matasse posteriormente, digamos:

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

Mas não sei como obter o PID. Existe uma maneira simples de conseguir isso? Outra maneira é salvar o PID do script de shell $$no arquivo e matar o script de shell inteiro, mas eu queria fazer uma limpeza após o loop while.

Eu tentei usar coproce acho que vai funcionar, mas parece mais complicação do que o necessário.

Adrian Pronk
fonte
Você pode usar algo parecido com isto `ps -ef | grep processName | grep -v grep | awk '{print $ 2}' | xargs kill -9 `
Kiwy
@ Kiwy - em vez dessa bagunça, basta fazer um pgrep inotifywait. Isso lhe dará o PID, para matar pkill inotifwait,.
slm
@ slm, dependendo do seu sistema, você não terá o pgrep e o pkill enquanto o grep e o ps estiverem quase presentes. Você é bem
Kiwy
@ Kiwy - duvidoso, essas ferramentas são bastante onipresentes. Além disso, você não precisa fazer a grep -v grep, mas ps -ef | grep [p]rocessname...faria o mesmo.
slm
1
@ DavididsonChua - sim, você pode usar a -fopção se precisar comparar com mais nomes dos executáveis.
slm

Respostas:

6

Em um pipeline, todos os processos são iniciados simultaneamente , não há um que seja anterior aos outros.

Você poderia fazer:

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

Ou portably:

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

Observe também que quando o subshell que executa o whileloop terminar, inotifywaitele será eliminado automaticamente na próxima vez em que gravar algo no stdout.

Stéphane Chazelas
fonte
3

Se você precisar do ID do processo no loop, imprima-o primeiro.

sh -c 'echo "$$"; exec inotifywait -m ...' | {
  read inotifywait_pid
  while IFS= read -r f; do
    
    if …; then kill "$inotifywait_pid"; break;
  done
}
Gilles 'SO- parar de ser mau'
fonte
1

Esta resposta SO parece aplicável:

inotifywait -m file > >(while read f; do echo f; done) &
Aryeh Leib Taurog
fonte