Skip to content

Instantly share code, notes, and snippets.

@Yetangitu
Last active February 24, 2016 19:17
Show Gist options
  • Save Yetangitu/ae1ddc79c831d9e3472b to your computer and use it in GitHub Desktop.
Save Yetangitu/ae1ddc79c831d9e3472b to your computer and use it in GitHub Desktop.
inotifywait-based change generator for use with apps/files scan api
#!/bin/bash
# inotify-based file watcher, to be used in combination with a patched files app
# command which supports the scanSingle/scanBatch api
#
# run as any user; make sure user can modify the PID file
TIMEOUT=60
OC_ROOT=/var/www/owncloud
OC_ADMIN_USER="admin"
OC_ADMIN_PASS="zooperzeekret"
OC_ROOT_PATH="https://www.example.org/owncloud"
PID=/var/run/oc-watch.pid
echo $$ > $PID
LOGDIR=$(mktemp -qd /tmp/oc-watch.XXXXXX)
LOG=$LOGDIR/log
QUEUE=$LOGDIR/queue
ACT=$LOGDIR/act
mkfifo $LOGDIR/fifo
> $LOG
> $QUEUE
> $ACT
# mounts and mountpoints (see mount.json in OC data root)
# every mount has a mountpoint for every user. Only one user
# needs to be given for each storage_id, which does not matter.
mounts=(/export/books)
mountpoints=(/frank/files/Library)
delay=$TIMEOUT
check_sanity () {
if [ ${#mounts[*]} -ne ${#mountpoints[*]} ]; then
echo please specify exactly one mountpoint per mount!
echo " ${#mounts[*]} mounts: ${mounts[*]}"
echo " ${#mountpoints[*]} mountpoints: ${mountpoints[*]}"
exit
fi
}
make_sed_script () {
for j in $(seq 0 $((${#mounts[*]}-1)));do
echo -n "s@^${mounts[$j]}@${mountpoints[$j]}@;"
done
}
on_exit () {
[ -n "$COPROC_PID" ] && kill $COPROC_PID
rm $LOG
rm $QUEUE
rm $ACT
rm $LOGDIR/fifo
rmdir $LOGDIR
rm $PID
}
oc_scan () {
curl -s -d @${ACT} -u ${OC_ADMIN_USER}:"${OC_ADMIN_PASS}" -H "Content-Type:application/json" ${OC_ROOT_PATH}/index.php/apps/files/api/v1/scan
}
trap on_exit EXIT
check_sanity
sed_script=$(make_sed_script)
coproc inotifywait -sqmr -e CREATE,DELETE,MOVE --format '%w%f' ${mounts[*]} >> $LOG
# occ needs to be executed from the OC_ROOT directory
cd $OC_ROOT
# sleep for (TIMEOUT - runtime previous scan (0 if result is negative)),
# pause inotifywait, copy contents of log to queue, empty log,
# unpause inotifywait. Sort/uniq queue, translate mounts
# to mountpoints, wrap results in json and feed them to OC
# through curl
while :;do
sleep $delay
kill -STOP $COPROC_PID
cp $LOG $QUEUE
> $LOG
kill -CONT $COPROC_PID
start_time=$(date +%s)
declare -a paths
sort $QUEUE|uniq > $LOGDIR/fifo &
while IFS= read -r f; do
IFS= paths+=($(echo "$f"|sed -e "$sed_script"))
done < $LOGDIR/fifo
if [ ${#paths[*]} -gt 0 ]; then
printf -v expanded_paths "%s\n" "${paths[@]}"
jq -n --arg ARR "$expanded_paths" '{ path_list: $ARR | rtrimstr("\n") | split("\n") }' > $ACT
oc_scan $ACT 2>&1 > /dev/null
fi
stop_time=$(date +%s)
run_time=$(($stop_time-$start_time))
if [ "$run_time" -ge "$TIMEOUT" ]; then
delay=0
else
delay=$(($TIMEOUT-$run_time))
fi
unset paths
> $QUEUE
> $ACT
done
@Yetangitu
Copy link
Author

Edited script to make it space-in-filename-proof... (added IFS= before 'paths+=($(echo "$f"|sed -e "$sed_script"))')

@jcdirks
Copy link

jcdirks commented Feb 24, 2016

That's a great solution for reliable syncing of files which are modified outside the scope of ownCloud, e.g. via a Samba share. That you very much! I've found it useful to include modified files to the watch criteria, line 74:
coproc inotifywait -sqmr -e CREATE,DELETE,MOVE,MODIFY --format '%w%f' ${mounts[*]} >> $LOG

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment