Do recurring operation with cron and ruby
cron is very suitable to do recurring events on e.g. a server. But what if you want do an recurring event with a certain minimal interval in a desktop machine which isn't running all the time.
A backup script is a typical use case where you want to run the operation if a certain time has passed since the last the last time the operation executed.
The idea is to call a script regularly with cron (e.g. every 10 minutes). The script keeps track on when the operation was called last time and only execute the operation again if a minimal set interval has passed.
A simple implementation has been made in ruby below.
#!/usr/local/bin/ruby
require 'date'
require 'digest'
require 'tmpdir'
def command_tmp_file(command)
return "#{Dir.tmpdir}/last-call-#{Digest::MD5.hexdigest command.join("")}.date"
end
def set_last_time(command)
fname = command_tmp_file(command)
open(fname, 'w') { |f|
f.puts DateTime.now.rfc3339()
}
end
def seconds_since_last_time(command)
fname = command_tmp_file(command)
unless File.exists? fname then return -1 end
return Time.now.to_i - DateTime.rfc3339(File.read(fname)).to_time.to_i
end
def print_help
puts "Call \"wrapped\" command only if a minumum time (seconds) has passed since it was last executed"
puts "This utility may be called periodically (e.g. from cron) to achieve periodic execution"
puts "Usage: #{$0} INTERVAL COMMAND [ARGS]"
puts "Example: #{$0} 60 echo \"one minute since last call\""
end
if (ARGV.size < 2) || (not ARGV[0] =~ /^[0-9]+$/)
print_help
exit
end
command = Array.new(ARGV); command.shift
delay = seconds_since_last_time(command)
min_delay = ARGV[0].to_i
if delay == -1 || delay > min_delay
puts `#{command.join(" ")}`
set_last_time(command)
end
If this script is called multiple times the operation (echo "min 10 secs") is only executed if 10 seconds has passed since last time it (i.e. the wrapped operation) was executed.
$ ./interval.rb 10 echo "min 10 secs"
hello
$ ./interval.rb 10 echo "min 10 secs"
$ ./interval.rb 10 echo "min 10 secs"
hello
Is there an existing UNIX utility for this ...