10

I'm writing a bash script to use inotifywait to monitor a directory and kick off actions when changes are detected. Something like:

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

Since inotifywait doesn't terminate by itself, this script will not halt.

So my plan was to get the PID of the inotifywait process, save it to a file and have a different process kill it later, say like:

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

But I don't know how to get the PID. Is there a simple way to achieve this? Another way is just to save the PID of the shell-script $$ to the file and kill the entire shell-script but I wanted to do some cleanup after the while loop.

I have tried using coproc and I think it will work but it seems like more complication than necessary.

  • You could use something like this ` ps -ef | grep processName | grep -v grep | awk '{print $2}' | xargs kill -9 ` – Kiwy Dec 3 '13 at 9:13
  • @Kiwy - instead of that mess just do a pgrep inotifywait. That will give you the PID,to kill, pkill inotifwait. – slm Dec 3 '13 at 12:42
  • @slm depending of your system you will not have pgrep and pkill while grep and ps while almost be present. You're welcome – Kiwy Dec 3 '13 at 12:48
  • @Kiwy - doubtful, those tools are pretty ubiquitous. Also you do not need to do a grep -v grep, instead ps -ef | grep [p]rocessname... would do the same. – slm Dec 3 '13 at 13:10
  • 1
    @DavidsonChua - yes you can use the -f switch if you need to match against more of the executables name. – slm Dec 4 '13 at 1:08
6

In a pipeline, all processes are started concurrently, there's not one that is earlier than the others.

You could do:

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

Or portably:

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

Also note that when the subshell that runs the while loop terminates, inotifywait would be killed automatically the next time it writes something to stdout.

3

If you need the process ID in the loop, print it first.

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

This SO answer seems applicable:

inotifywait -m file > >(while read f; do echo f; done) &

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.