Uzyskiwanie PID polecenia wcześniej w Pipeline

11

Piszę skrypt bash inotifywaitdo monitorowania katalogu i rozpoczynania akcji po wykryciu zmian. Coś jak:

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

Ponieważ inotifywaitskrypt nie zakończy się sam, skrypt nie zostanie zatrzymany.

Tak więc moim planem było uzyskanie PID procesu inotifywait, zapisanie go do pliku i inny proces zabił go później, powiedzmy:

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

Ale nie wiem, jak uzyskać PID. Czy istnieje prosty sposób na osiągnięcie tego? Innym sposobem jest po prostu zapisanie PID skryptu powłoki $$w pliku i zabicie całego skryptu powłoki, ale chciałem trochę wyczyścić po pętli while.

Próbowałem używać coproci myślę, że to zadziała, ale wydaje się, że jest to bardziej skomplikowane niż to konieczne.

Adrian Pronk
źródło
Możesz użyć czegoś takiego jak ten `ps -ef | grep nazwa_procesu | grep -v grep | awk '{print 2 USD}' | xargs kill -9 `
Kiwy
@Kiwy - zamiast tego bałaganu po prostu zrób pgrep inotifywait. Który daje PID, aby zabić pkill inotifwait.
slm
@slm w zależności od systemu nie będziesz mieć pgrep i pkill, podczas gdy grep i ps będą prawie obecne. Nie ma za co
Kiwy
@Kiwy - wątpliwe, że narzędzia te są dość wszechobecne. Nie musisz też robić grep -v grep, zamiast tego ps -ef | grep [p]rocessname...zrobiłbyś to samo.
slm
1
@DavidsonChua - tak, możesz użyć -fprzełącznika, jeśli chcesz dopasować do większej liczby nazw plików wykonywalnych.
slm

Odpowiedzi:

6

W potoku wszystkie procesy są uruchamiane jednocześnie , nie ma takiego, który jest wcześniejszy niż inne.

Mógłbyś:

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

Lub przenośnie:

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

Zauważ również, że kiedy podpowłoka, która uruchamia whilepętlę, inotifywaitzostanie automatycznie zabita, gdy następnym razem napisze coś na standardowe wyjście.

Stéphane Chazelas
źródło
3

Jeśli potrzebujesz identyfikatora procesu w pętli, najpierw go wydrukuj.

sh -c 'echo "$$"; exec inotifywait -m ...' | {
  read inotifywait_pid
  while IFS= read -r f; do
    
    if …; then kill "$inotifywait_pid"; break;
  done
}
Gilles „SO- przestań być zły”
źródło
1

Ta odpowiedź SO wydaje się mieć zastosowanie:

inotifywait -m file > >(while read f; do echo f; done) &
Aryeh Leib Taurog
źródło