#! /usr/bin/env ruby USAGE = " NAME RAILS_ROOT/script/sesswatch SYNOPSIS sesswatch (--verbose|v --noop|n --help|h) max=100_000 on=atime DESCRIPTION sesswatch keeps a rails sessions dir limited to a certain number of files. rather than deleting files older than a certain time, it simply deletes the oldest sessions first until no more that a given max amount occupies the directory. this is advantageous because it limits disk usage and directory size while allowing users to keep their sessions as long as possible. EXAMPLES . show what would be done by default, actually delete nothing ./script/sesswatch --noop --verbose . keep only 42 files in the sessions dir ./script/sesswatch 42 . delete files based on mtime rather than atime, keep only 50000 session lying around ./script/sesswatch 50000 mtime . a sample crontab line might be */30 * * * * /full/path/to/RAILS_ROOT/script/sesswatch INSTALL cd ./RAILS_ROOT/scripts/ curl --remote-name http://s3.amazonaws.com/drawohara.com.ruby/sesswatch " # ruby built-in # require 'fileutils' # bootstrap into the rails app # RAILS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) Dir.chdir RAILS_ROOT # naive argument parsing # verbose = ARGV.delete('--verbose') || ARGV.delete('-v') noop = ARGV.delete('--noop') || ARGV.delete('-n') help = ARGV.delete('--help') || ARGV.delete('-h') max = Integer(ARGV.shift || 42_000) on = String(ARGV.shift || 'atime') # spew usage if asked # abort USAGE if help # load all sessions and their stats sorted oldest first # sessions = [] Dir.glob('tmp/sessions/*') do |entry| begin next unless entry =~ %r/ruby_sess/ stat = File.stat entry next unless stat.file? sessions << [ File.expand_path(entry), stat ] rescue Exception next end end sessions.sort!{|a,b| a.last.send(on) <=> b.last.send(on)} # nuke sessions until we're below threshold, killing oldest first, don't # assume we can delete every file, just try every one until we've met our goal # - the move give a consistent view to rails if sessions are living on NFS # n = sessions.size rm_f = if noop lambda do |pathname| STDOUT.puts pathname if verbose n -= 1 end else lambda do |pathname| STDOUT.puts pathname if verbose tmp = pathname + ".sesswatch" begin FileUtils.mv pathname, tmp FileUtils.rm_f tmp n -= 1 rescue Object end end end n.times do |i| break if n <= max pathname, stat = sessions[i] rm_f[ pathname ] end # die if we can't clean up (for instance due to permissions issues) # abort "could not clean up session dir!" unless n <= max