Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to limit concurrent instances of same Ruby script?

In Ruby 1.9.x, what might be a simple way to either not allow my Ruby script to run again, or wait for the previous instance to finish?**

I'm hoping to avoid messy file-locking or process table checking.

Is there something like a global mutex or semaphore already in the core? I studied the native Mutex but that only seems to apply to threads within one Ruby process, not across different processes.

** Later on I might add timeout functionality, or limit to N instances, or look to be using more than one global lock (one per system-wide resource that should only have max one instance).

like image 464
Marcos Avatar asked Mar 12 '12 18:03

Marcos


2 Answers

This very short code will freeze in place until a lockfile in /tmp named after your script is locked exclusively:

File.open("/tmp/#{File.basename $0}.lock", File::RDWR|File::CREAT, 0644).flock(File::LOCK_EX)

Any other program locking it, Ruby or not, needs only to terminate or be killed, for the newer process instance to unblock and continue on. So for now this workaround does what I need. I can call my Ruby program with

timeout 1m ./myrubyscript.rb

from the wrapping bash script if I get impatient, for instance. (In that example, myrubyscript.rb will terminate after 1 minute whether or not and got its file lock to continue doing what it was written to do.)

like image 163
Marcos Avatar answered Sep 20 '22 16:09

Marcos


This is usually solved at the OS level, by checking for a flag-file and not trying to launch again, not in the script itself.

But, if you want to check in the script, look for a semaphore file in a known location. If it exists and it's not within a given time window that fits in your launch window, then delete the file and create a new one. If it's in your time window then exit.

You can use file-locking, or storing timestamps in the file, or many other checks if you don't launch using a cron-type mechanism. Each approach has its pluses and minuses.

You'll want to trap interrupts so that when you exit from a Control-C you erase that file too.

Read through the related questions on the right. Though they are covering various other languages, the suggested answers will help understand the problems and possible ways to work around them across all languages.

like image 44
the Tin Man Avatar answered Sep 22 '22 16:09

the Tin Man