LoginSignup
2
2

More than 5 years have passed since last update.

コマンド二重起動防止の setlock を ruby に移植してみた

Last updated at Posted at 2016-10-31

crontab 経由でコマンドを実行するときなど、コマンドの二重起動を抑止したいことがしばしばあります。
二重起動を抑止するコマンドとしては、 Linux で util-linux パッケージが使えれば flock コマンド、それ以外 (macOS とか) では自力でスクリプトを組むか、こちらで紹介されている setlock を使うことになると思います。

setlock は美しいツールだなーと思うのですが、daemontools をソースからビルドする必要があり、一手間かかります。なんというかコンパイルとかせずにどうにかならないものか...。

と思いまして setlock.c のソース を見たところ、超短いソースだったので、 Ruby に移植してみました。Amazon AMI には ruby-2.0 が最初から入ってるから、これならパスの通ったところにコピペで置くだけっ...。

setlock.rb
#!/usr/bin/env ruby
require 'optparse'

Version = '1.0.0'
flagx = false
flagndelay = false

parser = OptionParser.new
parser.banner = "Usage: setlock.rb [ -nNxX ] file program [ arg ... ]"
parser.on('-n','No delay. If fn is locked by another process, setlock gives up.'){|v|flagndelay=v}
parser.on('-N','(Default.) Delay. If fn is locked by another process, setlock waits until it can obtain a new lock.'){|v|flagndelay=!v}
parser.on('-x','If fn cannot be opened (or created) or locked, setlock exits zero.'){|v|flagx=v}
parser.on('-X','(Default.) If fn cannot be opened (or created) or locked, setlock prints an error message and exits nonzero.'){|v|flagx=!v}
parser.summary_width=3

begin
    parser.parse!(ARGV)
rescue => e
    abort "#{e.message}"
end

lockfile = ARGV.shift

abort "missing argument.\n#{parser.help}" if ARGV.size == 0

f = nil
begin
  f = File.open(lockfile, 'w')
rescue => e
  exit 0 if flagx
  abort "unable to open #{lockfile}"
end

if not f.flock(flagndelay ? (File::LOCK_EX|File::LOCK_NB) : File::LOCK_EX)
  exit 0 if flagx
  abort "unable to lock #{lockfile}"
end

system ARGV[0], *ARGV[1..-1]
exit $?.exitstatus

とはいえ、システム系プログラムはそんなに得意でないのと、Ruby あまり詳しくないので、変だったらぜひコメントで教えて下さい。それ以前に実は このパッケージ入れたら setlock 含まれてるよとか、あったらショックですが...。

2
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2