1

I am learning to use inotifywait, specifically by using the script at: https://unix.stackexchange.com/questions/24952/script-to-monitor-folder-for-new-files. What I do not understand is why my scripts always appear two times when I use pid x.

36285 pts/1    S+     0:00 /bin/bash ./observe2.sh /home/user1/testfolder
36286 pts/1    S+     0:00 inotifywait -m /home/user1/testfolder -e create -e moved_to
36287 pts/1    S+     0:00 /bin/bash ./observe2.sh /home/user1/testfolder

For quicker testing, I changed the linked script so that you can pass any folder via $1 to be observed, and saved as observe2.sh:

#!/bin/bash
inotifywait -m $1 -e create -e moved_to |
    while read path action file; do
        echo "The file '$file' appeared in directory '$path' via '$action'"
        # do something with the file
    done

Why does the script process show up two times? Is there a fork somewhere in the process? Could somebody explain why exactly this behavior of two processes is happening?

Community
  • 1
  • 1
tkja
  • 1,950
  • 5
  • 22
  • 40

1 Answers1

5

Because it has a pipeline.

A pipeline forks a subshell -- a second process -- and connects them. In the case of foo | bar -- where those are both external, non-shell commands -- the subshells exec the actual commands, and thus lose their process tree entries. When an element of that pipeline is written in shell, a shell to execute it remains in the process tree.


That said, I'd suggest[1] writing it a bit differently:

while read -r path action file; do
    echo "The file '$file' appeared in directory '$path' via '$action'"
    # do something with the file
done < <(exec inotifywait -m "$1" -e create -e moved_to)

This will keep the while loop in the main process, and the exec makes the forked-off subshell replace itself with inotifywait. Thus, changes you make inside the while loop -- such as setting variables in your script -- will persist even after the script moves on from the loop, whereas if you put the loop in a pipeline, any variables set in it are scoped to the subshell. See BashFAQ #24 for details.


[1] - Actually, I'd suggest writing it even more differently than that, if you want to cover all the corner cases thoroughly. Since POSIX filenames can contain any character other than NUL or / (and / can, of course, exist in pathnames), space- or newline-separating names is a very bad idea; there are also bugs in the existing implementation around names that end in whitespace. Unfortunately, since inotifywait doesn't allow custom format strings to contain \0 to NUL-delimit them, getting completely unambiguous output from it is quite tricky; it's been covered in other answers on StackOverflow, and I'm not much inclined to reproduce their contents here.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441