7

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

Jatin Dhoot
  • 4,294
  • 9
  • 39
  • 59
  • I have taken a glance on strace result, both `close` from soffice.bin itself, first one is to copy temp pdf result file to the destination, second is just check its stats, have to dig deeper into java source. but why this bothers you? – georgexsh Oct 04 '17 at 20:08
  • Thanks @georgexsh for your response. Actually there is some COPY-TO-CLOUD functionality going on which is bind with this trigger. So files are gettign copied twice and some other house keeping jobs going on in parallel. – Jatin Dhoot Oct 06 '17 at 06:30
  • @JatinDhoot what kind of answer are you looking for? – Oleg Kuralenko Oct 06 '17 at 20:23
  • @ffeast - I want to inotifywait to trigger the notification only once instead of twice in case if PDF is generated from soffice. Thanks. – Jatin Dhoot Oct 07 '17 at 06:46
  • @JatinDhoot you can't do it without having a wrapping code as the file itself seems to be written twice as georgexsh straced – Oleg Kuralenko Oct 07 '17 at 13:16

2 Answers2

1

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

Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
1

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.

Oleg Kuralenko
  • 11,003
  • 1
  • 30
  • 40