2007-01-24

cron ジョブに複雑な条件を与えやすくする

つーことで『cron, crontab, and more』でちまちま悩んでいましたが、思いついたのはまた Ruby ですが以下のものです。やってることは簡単で、要は

複雑な条件はお気に入りの言語で記述する

ってことです。そのために

  • 条件の名前と実行するプログラムを与えるだけのスクリプトを用意
  • 条件の名前はそのまま(この場合は Ruby の)実行するメソッド名に該当する
  • cron には(例えば)以下のように書く
complex-cron -c RULE 'program'

という方法にしてみました。以下のスクリプトでは RULE は省略可能で、その場合は `default' を指定したものとみなしています。

※ 比較的最近の Web アプリでよくあるプラグインと基本的には同じアイディア、だと思ってます。

呼び出すメソッド(つまり判定条件)に引き数を与えることはできません。一瞬悩みましたが必要ないだろうと思いますし、引き数を与えられるようにすると実行時のパラメータの与え方が複雑になります。

実行するスクリプト

(例えばcomplex-cron て名前にしておく)

#! /usr/bin/env ruby

require 'optparse'
Version = '0.1'

class ComplexCron
  def initialize
    @condfile     = '/etc/defaults/cronconds'
    @condname     = nil
    @cond_default = 'default'
    @debug        = false

    accept_options()
    @cmd = ARGV.shift
    exam_options()
    exec_indeed()
  end

  def exam_options
    if ( @cmd.nil? )
      raise 'Nothing to do.'
    end

    if ( !File.exist?( @condfile ) )
      raise "File #{@condfile} does not exist."
    else
      load( @condfile, false )
      if ( @condname.nil? )
        @condname = @cond_default
      elsif ( !ComplexCronConds.instance_methods().include?( @condname ) )
        raise "Rule #{@condname} is not defined."
      end
    end
  end

  def exec_indeed
    if ( ComplexCronConds.instance_method( @condname ) )
      if ( @debug )
        puts @cmd
      else
        exec @cmd
      end
    end
  end

  def accept_options
    opt = OptionParser.new()
    opt.on( '-f CONDFILE' ) { |file|
      @condfile = file
    }
    opt.on( '-c CONDNAME' ) { |method|
      @condname = method
    }
    opt.on( '-n', 'dry run' ) { |v|
      @debug = true
    }
    opt.parse!( ARGV )
  end
end # of class ComplexCron

ComplexCron.new()

設定ファイルとは名ばかりの Ruby スクリプト

例えば /etc/defaults/cronconds とかいう名前で置いておく。場所はシステムに応じて適当に決めて。

# -*- ruby -*-

module ComplexCronConds
  def default
    return false
  end
end

この中に上で RULE と書いた名前に該当するメソッドを定義していきます。内容はどうぞご自由に。ただしあくまで「条件」をメソッドとして書くので、必ず true か false を返してください。default はあった方がいいかなと思って定義してあるんですけど、実際どう使うのかはあんまりイメージできてません。

これでまぁ、第3水曜だのシステムの負荷の様子だの、Ruby で判別可能な条件はなんでも書けるようになったわけです。あとは必要に迫られたときに考えればいいんじゃないかと。

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm