Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

inotifywait triggering event twice while converting docx to PDF

I have shell script with inotifwait set up as under:

inotifywait -r  -e close_write,moved_to  -m "<path>/upload" --format '%f##@@##%e##@@##%w'

There are some docx files residing in watched directory and some script converts docx to PDF via below command:

soffice --headless --convert-to pdf:writer_pdf_Export <path>/upload/somedoc.docx --outdir  <path>/upload/

Somehow event is triggered twice as soon as PDF is generated. Entries are as under:

somedoc.pdf##@@##CLOSE_WRITE,CLOSE##@@##<path>/upload/
somedoc.pdf##@@##CLOSE_WRITE,CLOSE##@@##<path>/upload/

What else is wrong here?

Regards

like image 830
Jatin Dhoot Avatar asked Sep 29 '17 05:09

Jatin Dhoot


2 Answers

It's triggered twice because this is how soffice appears to behave internally. One day it may start writing it 10 times and doing sleep 2 between such writes during a single run, our program can't and I believe shouldn't anticipate it and depend on it.

So I'd try solving the problem from a different angle - lets just put the converted file into a temporary directory and then move it to the target dir, like this:

soffice --headless --convert-to pdf:writer_pdf_Export <path>/upload/somedoc.docx --outdir <path>/tempdir/ && mv <path>/tempdir/somedoc.pdf <path>/upload/

and use inotifywait in the following way:

inotifywait -r -e moved_to  -m "<path>/upload" --format '%f##@@##%e##@@##%w'

The advantage is that you no longer depend on soffice's internal logic. If you can't adjust behavior of the script producing the pdf files then indeed you'll need to resort to a workaround like @Tarun suggested.

like image 93
ffeast Avatar answered Nov 01 '22 18:11

ffeast


I don't think you can control the external program as such. But I assume you are using this output for a pipe and then inputing it some place else. In that case you can avoid a event that happens continuously with a span of few seconds

So we add %T to --format and --timefmt "%s" to get the epoch time. Below is the updated command

$ inotifywait -r  -e close_write,moved_to --timefmt "%s"  -m "/home/vagrant" --format '%f##@@##%e##@@##%w##T%T' -q | ./process.sh
test.txt##@@##CLOSE_WRITE,CLOSE##@@##/home/vagrant/
Skipping this event as it happend within 2 seconds. TimeDiff=2
test.txt##@@##CLOSE_WRITE,CLOSE##@@##/home/vagrant/

This was done by using touch test.txt, multiple time every second. And as you can see second even was skipped. The process.sh is a simple bash script

#!/bin/bash

LAST_EVENT=
LAST_EVENT_TIME=0
while read line
do
  DEL="##T"
  EVENT_TIME=$(echo "$line" | awk -v delimeter="$DEL" '{split($0,a,delimeter)} END{print a[2]}')
  EVENT=$(echo "$line" | awk -v delimeter="$DEL" '{split($0,a,delimeter)} END{print a[1]}')
  TIME_DIFF=$(( $EVENT_TIME - $LAST_EVENT_TIME))
  if [[ "$EVENT" == "$LAST_EVENT" ]]; then
     if [[ $TIME_DIFF -gt 2 ]]; then
        echo "$EVENT"
     else
        echo "Skipping this event as it happend within 2 seconds. TimeDiff=$TIME_DIFF"
     fi
  else
    echo $EVENT
    LAST_EVENT_TIME=$EVENT_TIME
  fi
  LAST_EVENT=$EVENT
done < "${1:-/dev/stdin}"

In your actual script you will disable the echo in if, this one was just for demo purpose

like image 23
Tarun Lalwani Avatar answered Nov 01 '22 18:11

Tarun Lalwani