Skip to content

Instantly share code, notes, and snippets.

@crantok
Created August 24, 2015 13:35
Show Gist options
  • Save crantok/ca184772fbeebac99de4 to your computer and use it in GitHub Desktop.
Save crantok/ca184772fbeebac99de4 to your computer and use it in GitHub Desktop.
# A script to execute a system command in response to filesystem changes.
#
# After the latest filesystem change, a minimum interval is allowed to pass
# before calling the system command.
# Multiple filesystem changes in quick succession are treated as a single
# change.
#
# Pidify is used to ensure that this script can safely be called multiple
# times and only one instance will ever be running.
# The pidify ruby file is included using require_relative because I could not
# get the gem to install.
# Config
pid_directory = '/home/me/watcher/'
log_filename = '/home/me/watcher/watch-and-execute.log'
directory_to_watch = '/home/me/watcher/src/'
command_to_execute = 'cd /home/me/watcher && ls > dirlist.txt'
min_interval_in_seconds = 1.0
require_relative 'pidify.rb'
Pidify.pid_directory = pid_directory
if Pidify.running?
abort "Script already running"
else
begin
# First things first: Make sure this script cannot be executed again
# until the current execution concludes.
Pidify.start
# Don't risk examining a non-existent variable in the rescue block.
notifier = nil
require 'logger'
# Variables shared between threads.
dirty_event_time = nil
mutex = Mutex.new
logger = Logger.new( log_filename, 'weekly' );
logger.info( "Script started." )
# The thread that will execute the system command
t = Thread.new do
begin
loop do
if dirty_event_time && Time.now - dirty_event_time > min_interval_in_seconds
# First things first, unset the dirty event time.
# Doing it later would increase the chance of
# overwriting a new and undetected value.
mutex.synchronize do
dirty_event_time = nil
end
# Not using mutex as logger appears to be thread-safe:
# http://stackoverflow.com/a/4660331/664322
logger.info( "Executing command..." )
output = `#{command_to_execute}`
logger.info( output )
end
# Pause for the minimum interval. Note: This may mean a
# longer delay than the minimum interval between a
# filesystem change and execution of the system command.
sleep min_interval_in_seconds
end
rescue Exception => e
# Added a rescue clause because otherwise Ctrl-C can kill this
# thread without killing the script.
raise
end
end
t.abort_on_exception = true
# Add recursive directory watch.
require 'rb-inotify'
notifier = INotify::Notifier.new
notifier.watch( directory_to_watch, :attrib, :close_write, :move, :modify, :create, :delete, :recursive ) do
mutex.synchronize do
dirty_event_time = Time.now
end
logger.info "Filesystem change detected."
end
notifier.run
rescue Exception => e
Pidify.stop
if notifier
notifier.stop
notifier.close
end
logger.info "Script exiting..."
logger.info e.message
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment