Skip to content

Instantly share code, notes, and snippets.

@jarthod
Created April 17, 2019 08:31
Show Gist options
  • Save jarthod/5e541aad42b30d53806e3686dc7a81a4 to your computer and use it in GitHub Desktop.
Save jarthod/5e541aad42b30d53806e3686dc7a81a4 to your computer and use it in GitHub Desktop.
Provides a system wide file lock to ensure no more than X process is running at the same time.
#!/usr/bin/env ruby
# Provides a system wide file lock to ensure no more
# than X process is running at the same time.
# Example:
#
# process_semaphore!({
# prefix: "/tmp/my_process",
# limit: 2
# })
# Calling this at the beginning of your script will ensure
# no more than 2 process with the same prefix are currently
# running. Any exceding process will simply exit(0).
require 'pathname'
def process_semaphore! options
prefix = options.fetch(:prefix)
limit = options.fetch(:limit, 1)
# Lock file
lock_file = Pathname.new("#{prefix}.#{$$}")
at_exit { lock_file.unlink if lock_file.exist? }
# Check running processes, remove stale pid files
running = Dir.glob("#{prefix}.*").sort.select do |path|
begin
# Try to lock the file to see if the process is still running
if File.open(path).flock(File::LOCK_EX | File::LOCK_NB)
puts "#{path} present but not locked, deleting"
File::unlink(path)
false
else
true
end
rescue Errno::ENOENT # The file is deleted
false
end
end.size
# Quit if above limit
exit if running >= limit
# Apply lock
file = lock_file.open(File::RDWR | File::CREAT)
file.flock(File::LOCK_EX | File::LOCK_NB)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment