Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run inotifywait continuously and run it as a cron or deamon?

I've built a shell script that uses inotifywait to automatically detect file changes on a specific directory. When a new PDF file is dropped in the directory this script should go off and it should then trigger ocropus-parser to execute some commands on it. The code:

#!/bin/sh
inotifywait -m ~/Desktop/PdfFolder -e create -e moved_to |
while read path action file; do
    #echo "The file '$file' appeared in directory '$path' via '$action'"
    # Check if the file is a PDF or another file type.
    if [ $(head -c 4 "$file") = "%PDF" ]; then
        echo "PDF found - filename: " + $file
        python ocropus-parser.py $file
    else
        echo "NOT A PDF!"
fi
done

This works pretty well when I run this script through the terminal with ./filenotifier.sh but when I reboot my Linux (Ubuntu 14.04) my shell will no longer run and it will not restart after a reboot. I've decided to create an init script that starts at boot time (I think). I did this by copying the file filenotifier.sh to init.d:

sudo cp ~/Desktop/PdfFolder/filenotifier.sh /etc/init.d/

I've then gave the file the correct rights:

sudo chmod 775 /etc/init.d/filenotifier.sh

and finally I've added the file to update-rc.d:

sudo update-rc.d filenotifier.sh defaults

However when I reboot and drop a PDF in the folder ~/Desktop/PdfFolder nothing will happen and it seems that the script does not go off. I'm really not experienced with init.d, update-rc.d and deamon so I'm not sure what is wrong and if this is even a good approach or not.

Thanks, Yenthe

like image 963
Yenthe Avatar asked Dec 24 '22 09:12

Yenthe


2 Answers

  • Being an init-script, you should add the LSB header to your script, like this:

    #!/bin/sh
    ### BEGIN INIT INFO
    # Provides:          filenotifier
    # Required-Start:    $remote_fs $syslog
    # Required-Stop:     $remote_fs $syslog
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: Something
    # Description:       Something else
    ### END INIT INFO
    
    inotifywait -m ...
    

    This way, you can ensure that your script runs when all mount points are available (thanks to Required-Start: $remote_fs). This is essential if your home directory is not on the root partition.

  • Another problem is that in your init-script you're using ~:

    inotifywait -m ~/Desktop/PdfFolder ...
    

    The ~ expands to the current user home directory. Init-scripts are run as root, so it'll expand to /root/Desktop/PdfFolder. Use ~<username> instead:

    inotifywait -m ~yenthe/Desktop/PdfFolder ...
    

    (Assuming that your username is yenthe.)

    Or perhaps switch user before starting (using sudo).

  • $file is the basename without the path to the directory. Use "$path/$file" in your commands:

    "$(head -c 4 "$path/$file")"
    python ocropus-parser.py "$path/$file"
    

    Maybe consider using name instead of file, to avoid confusion.

  • If things are not working, or if in general you want to investigate something, remember to use ps, like this:

    ps -ef | grep inotifywait
    

    ps will tell you, for example, whether your script is running and if inotifywait was launched with the correct arguments.

  • Last but not least: use "$file", not $file; use "$(head -c 4 "$file")", not $(head -c 4 "$file"); use read -r, not read. These tips can save you a lot of headaches in the future!

like image 124
Andrea Corbellini Avatar answered Feb 14 '23 20:02

Andrea Corbellini


For that purpose the developers of inotify created incron. It is a cron like daemon which executes scripts based on changes in a watched file/directory rather than on time events.

like image 27
hek2mgl Avatar answered Feb 14 '23 18:02

hek2mgl