Created
August 24, 2015 13:35
-
-
Save crantok/ca184772fbeebac99de4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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