| 1 | #! /usr/bin/env ruby |
|---|
| 2 | # -*- mode: ruby; coding: mule-utf-8 -*- |
|---|
| 3 | |
|---|
| 4 | require 'pathname' |
|---|
| 5 | require 'optparse' |
|---|
| 6 | #require 'const_loader' |
|---|
| 7 | |
|---|
| 8 | # |
|---|
| 9 | # = periodic-forwarder |
|---|
| 10 | # |
|---|
| 11 | # スクリプトに置かれているディレクトリに応じて、該当する periodic なディ |
|---|
| 12 | # レクトリを指定パス内から探し出し、これを run-parts あるいは periodic |
|---|
| 13 | # で実行する |
|---|
| 14 | # |
|---|
| 15 | # ex) |
|---|
| 16 | # |
|---|
| 17 | # /etc/cron.daily/THIS_SCRIPT -> |
|---|
| 18 | # periodic #{BASE_DIR}/SITE/#{FILLING_PATH}/daily/ |
|---|
| 19 | # |
|---|
| 20 | # THIS_SCRIPT は link で構わない。APPEND を与えればリダイレクトやパイプに |
|---|
| 21 | # よって結果を処理することも可能。 |
|---|
| 22 | # |
|---|
| 23 | # == requirements |
|---|
| 24 | # `which` , and `periodic` or `run-parts` command |
|---|
| 25 | # |
|---|
| 26 | |
|---|
| 27 | Version = 0.1 |
|---|
| 28 | |
|---|
| 29 | class PeriodicForwarder |
|---|
| 30 | # include ConstLoader |
|---|
| 31 | |
|---|
| 32 | def initialize |
|---|
| 33 | @opt = {} |
|---|
| 34 | |
|---|
| 35 | @conf = { |
|---|
| 36 | 'append' => nil, |
|---|
| 37 | 'base_dir' => nil, |
|---|
| 38 | 'filling_path' => nil, |
|---|
| 39 | } |
|---|
| 40 | |
|---|
| 41 | @periodic = nil |
|---|
| 42 | @periodic_runner = periodic_runner |
|---|
| 43 | end |
|---|
| 44 | |
|---|
| 45 | def run() |
|---|
| 46 | begin |
|---|
| 47 | load_conf |
|---|
| 48 | rescue |
|---|
| 49 | end |
|---|
| 50 | |
|---|
| 51 | opts().parse!( ARGV ) |
|---|
| 52 | @period = period( parent_dir ) |
|---|
| 53 | exec( collect_periodic_dirs ) |
|---|
| 54 | end |
|---|
| 55 | |
|---|
| 56 | # |
|---|
| 57 | # periodic / run-parts の判別 |
|---|
| 58 | # |
|---|
| 59 | def periodic_runner |
|---|
| 60 | return system( 'which run-parts > /dev/null' ) ? 'run-parts' : 'periodic' |
|---|
| 61 | end |
|---|
| 62 | |
|---|
| 63 | # |
|---|
| 64 | # 指定ディレクトリの親ディレクトリ |
|---|
| 65 | # |
|---|
| 66 | # 無指定の場合はスクリプト自身の置かれているディレクトリ |
|---|
| 67 | # |
|---|
| 68 | def parent_dir( dir = nil ) |
|---|
| 69 | dir = ( dir.nil? ) ? File.expand_path( __FILE__ ) : dir |
|---|
| 70 | |
|---|
| 71 | return Pathname.new( dir ).parent.basename.to_s |
|---|
| 72 | end |
|---|
| 73 | |
|---|
| 74 | # |
|---|
| 75 | # 指定ディレクトリの意味する期間 |
|---|
| 76 | # |
|---|
| 77 | def period( dir ) |
|---|
| 78 | period = nil |
|---|
| 79 | |
|---|
| 80 | if ( /cron\.(.*)/ =~ dir ) |
|---|
| 81 | period = $1 |
|---|
| 82 | else |
|---|
| 83 | period = dir |
|---|
| 84 | end |
|---|
| 85 | |
|---|
| 86 | return period |
|---|
| 87 | end |
|---|
| 88 | |
|---|
| 89 | # |
|---|
| 90 | # base_dir 以下で @periodic と同じ名前を持つディレクトリを集める |
|---|
| 91 | # |
|---|
| 92 | def collect_periodic_dirs( base_dir = nil ) |
|---|
| 93 | dir = ( base_dir || @conf['base_dir'] ) |
|---|
| 94 | |
|---|
| 95 | if ( dir.nil? ) |
|---|
| 96 | abort( 'base_dir is not defined.' ) |
|---|
| 97 | end |
|---|
| 98 | |
|---|
| 99 | dirs = [] |
|---|
| 100 | Dir.foreach( dir ) { |e| |
|---|
| 101 | target = File.expand_path( File.join( dir, e.to_s, @conf['filling_path'].to_s, @period.to_s ) ) + '/' |
|---|
| 102 | if ( File.exist?( target ) and File.directory?( target ) ) |
|---|
| 103 | dirs.push( target ) |
|---|
| 104 | end |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | return dirs |
|---|
| 108 | end |
|---|
| 109 | |
|---|
| 110 | # |
|---|
| 111 | # 対象ディレクトリ群に対して片っ端から @periodic を実行 |
|---|
| 112 | # |
|---|
| 113 | # [Param] dirs |
|---|
| 114 | # |
|---|
| 115 | def exec( dirs ) |
|---|
| 116 | dirs.each { |dir| |
|---|
| 117 | cmd = "#{@periodic_runner} #{dir}" |
|---|
| 118 | if ( @conf['append'] ) |
|---|
| 119 | cmd += " #{@conf['append']}" |
|---|
| 120 | end |
|---|
| 121 | system( cmd ) |
|---|
| 122 | } |
|---|
| 123 | end |
|---|
| 124 | |
|---|
| 125 | # |
|---|
| 126 | # オプション定義 |
|---|
| 127 | # |
|---|
| 128 | def opts |
|---|
| 129 | opt = OptionParser.new() |
|---|
| 130 | # opt.on( '-c', 'CONFIG FILE' ) { |file| |
|---|
| 131 | # if ( File.exist?( file ) ) |
|---|
| 132 | # @opt['conf'] = file |
|---|
| 133 | # end |
|---|
| 134 | # } |
|---|
| 135 | opt.on( '-a', '--append=APPEND' ) { |append| |
|---|
| 136 | @conf['append'] = append |
|---|
| 137 | } |
|---|
| 138 | opt.on( '-b', '--base-dir=BASE_DIR' ) { |base_dir| |
|---|
| 139 | if ( File.exist?( base_dir ) ) |
|---|
| 140 | @conf['base_dir'] = base_dir |
|---|
| 141 | end |
|---|
| 142 | } |
|---|
| 143 | opt.on( '-f', '--filling-path=FILLING_PATH' ) { |filling_path| |
|---|
| 144 | if ( File.exist?( filling_path ) ) |
|---|
| 145 | @conf['filling_path'] = filling_path |
|---|
| 146 | end |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | return opt |
|---|
| 150 | end |
|---|
| 151 | |
|---|
| 152 | end # of class App |
|---|
| 153 | |
|---|
| 154 | if ( __FILE__ == $0 ) |
|---|
| 155 | begin |
|---|
| 156 | load( File.basename( __FILE__ ) + '.conf' ) |
|---|
| 157 | rescue LoadError |
|---|
| 158 | end |
|---|
| 159 | app = PeriodicForwarder.new |
|---|
| 160 | app.run() |
|---|
| 161 | end |
|---|