diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b266090 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +FROM phusion/baseimage:0.9.11 + +MAINTAINER David Coppit + +ENV DEBIAN_FRONTEND noninteractive + +# Speed up APT +RUN echo "force-unsafe-io" > /etc/dpkg/dpkg.cfg.d/02apt-speedup \ + && echo "Acquire::http {No-Cache=True;};" > /etc/apt/apt.conf.d/no-cache + +RUN set -x \ + && apt-get update \ + && apt-get install -y inotify-tools wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +VOLUME ["/media", "/config"] + +# Add default config file +ADD sagetv-rescan.conf /root/sagetv-rescan.conf + +# Add scripts +ADD start.sh /root/start.sh +RUN chmod +x /root/start.sh + +CMD /root/start.sh diff --git a/README.md b/README.md index 1fa4897..aaed7f4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,33 @@ # docker-sagetv-rescan + +docker-sagetv-rescan +==================== + Trigger a SageTV media library rescan whenever a folder changes + +This is a Docker container for triggering a library rescan for [SageTV](http://www.sage.tv/). Whenever the media library +changes, the container will notify SageTV. + +Usage +----- + +This docker image is available as a [trusted build on the docker index](https://index.docker.io/u/coppit/sagetv-rescan/). + +Run: + +`sudo docker run --name=SageTV-Rescan -d -v /etc/localtime:/etc/localtime -v /config/dir/path:/config:rw -v /media/dir/path:/media coppit/sagetv-rescan` + +To check the status, run: + +`docker logs SageTV-Rescan` + +When the container detects a change to the media directory, it will wait for a configurable "max wait time" for changes +to stop for a configurable "stabilization time". It will then notify SageTV to do a rescan, and wait for that rescan to +complete before resuming monitoring of the media directory. + +Configuration +------------- + +When run for the first time, a file named `sagetv-rescan.conf` will be created in the config dir, and the container will exit. +Edit this file, customizing how you want it to run. For example, you might want to increase the stabilization time to +avoid rescanning too frequently. Then restart the container and it will begin monitoring. diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..839c318 --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/bash + +docker build --rm=true -t coppit/sagetv-rescan . diff --git a/sagetv-rescan.conf b/sagetv-rescan.conf new file mode 100644 index 0000000..1104999 --- /dev/null +++ b/sagetv-rescan.conf @@ -0,0 +1,16 @@ +# After seeing the first event, we don't notify SageTV until we've processed any other events that might be happening. +# Otherwise we'll end up notifying SageTV 100 times for the case where someone moves 100 files into the media directory. + +# If we don't see any events for $SETTLE_DURATION time, assume that it's safe to notify SageTV. Format is HH:MM:SS, +# with HH and MM optional. +SETTLE_DURATION=5 + +# However, if we see continuous changes for longer than $MAX_WAIT_TIME with no break of $SETTLE_DURATION or more, then +# go ahead and notify SageTV. Otherwise we might be waiting forever for the directory to stop changing. Format is HH:MM:SS, +# with HH and MM optional. +MAX_WAIT_TIME=05:00 + +# This is the command to run to notify SageTV. Replace YOUR_SERVER with a proper IP address. This command assumes that +# you've installed the plugin called "sagex-services - SageTV Remote API Services". +NOTIFY_COMMAND="wget -nv -O /dev/null --auth-no-challenge \ + http://sage:frey@YOUR_SERVER:8080/sagex/api?c=RunLibraryImportScan&1=" diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..666e771 --- /dev/null +++ b/start.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +function ts { + echo [`date '+%b %d %X'`] +} + +echo "$(ts) Starting SageTV-Rescan container" + +# Search for custom config file, if it doesn't exist, copy the default one +if [ ! -f /config/sagetv-rescan.conf ]; then + echo "$(ts) Creating config file and exiting. Check the settings, then rerun the container." + cp /root/sagetv-rescan.conf /config/sagetv-rescan.conf + chmod a+w /config/sagetv-rescan.conf + exit 1 +fi + +tr -d '\r' < /config/sagetv-rescan.conf > /tmp/sagetv-rescan.conf + +. /tmp/sagetv-rescan.conf + +if [[ ! "$SETTLE_DURATION" =~ ^([0-9]{1,2}:){0,2}[0-9]{1,2}$ ]]; then + echo "$(ts) SETTLE_DURATION must be defined in sagetv-rescan.conf as HH:MM:SS or MM:SS or SS." + exit 1 +fi + +if [[ ! "$MAX_WAIT_TIME" =~ ^([0-9]{1,2}:){0,2}[0-9]{1,2}$ ]]; then + echo "$(ts) MAX_WAIT_TIME must be defined in sagetv-rescan.conf as HH:MM:SS or MM:SS or SS." + exit 1 +fi + +if [ -z "$NOTIFY_COMMAND" ]; then + echo "$(ts) NOTIFY_COMMAND must be defined in sagetv-rescan.conf" + exit 1 +elif [ "$NOTIFY_COMMAND" = "YOUR_SERVER" ]; then + echo "$(ts) Please replace \"YOUR_SERVER\" in sagetv-rescan.conf" + exit 1 +fi + +to_seconds () { + readarray elements < <(echo $1 | sed 's/:/\n/g' | tac) + + SECONDS=0 + POWER=1 + + for (( i=0 ; i<${#elements[@]}; i++ )) ; do + SECONDS=$(( 10#$SECONDS + 10#${elements[i]} * 10#$POWER )) + POWER=$(( 10#$POWER * 60 )) + done + + echo "$SECONDS" +} + +SETTLE_DURATION=$(to_seconds $SETTLE_DURATION) +MAX_WAIT_TIME=$(to_seconds $MAX_WAIT_TIME) + +pipe=$(mktemp -u) +mkfifo $pipe + +echo "$(ts) Waiting for changes..." +inotifywait -m -q --format '%e %f' /media >$pipe & + +while true +do + if read RECORD + then + EVENT=$(echo "$RECORD" | cut -d' ' -f 1) + FILE=$(echo "$RECORD" | cut -d' ' -f 2-) + +# echo "$RECORD" +# echo " EVENT=$EVENT" +# echo " FILE=$FILE" + + if [ "$EVENT" == "CREATE,ISDIR" ] + then + echo "$(ts) Detected new directory: $FILE" + elif [ "$EVENT" == "CLOSE_WRITE,CLOSE" ] + then + echo "$(ts) Detected new file: $FILE" + elif [ "$EVENT" == "MOVED_TO" ] + then + echo "$(ts) Detected moved file: $FILE" + else + continue + fi + + # Monster up as many events as possible, until we hit the either the settle duration, or the max wait threshold. + start_time=$(date +"%s") + + while true + do + if read -t $SETTLE_DURATION RECORD + then + end_time=$(date +"%s") + + if [ $(($end_time-$start_time)) -gt $MAX_WAIT_TIME ] + then + echo "$(ts) Input directory didn't stabilize after $MAX_WAIT_TIME seconds. Notifying SageTV anyway." + break + fi + else + echo "$(ts) Input directory stabilized for $SETTLE_DURATION seconds. Notifying SageTV." + break + fi + done + + $NOTIFY_COMMAND + fi +done <$pipe