fluent-plugin-exec_cron 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.document +3 -0
- data/.gitignore +9 -0
- data/.travis.yml +15 -0
- data/.yardopts +1 -0
- data/Gemfile +7 -0
- data/README.md +79 -0
- data/Rakefile +11 -0
- data/exsample/exsample.conf +18 -0
- data/fluent-plugin-exec_cron.gemspec +26 -0
- data/lib/fluent/plugin/in_exec_cron.rb +136 -0
- data/test/helper.rb +18 -0
- data/test/plugin/test_in_exec_cron.rb +75 -0
- metadata +170 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cbbcf3f7345626fd259b551bebfca72f62a994cd
|
4
|
+
data.tar.gz: 24ca495172005d6079578070c02ad81a371023ad
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f4f551d1ef67f94df3df94f9b1423c1157cd1c9e4e2c57c4b8d1f1ab1e4e2715442075e6158076426eca32688aab17b6132f4166d2d079eae166e10a46982a3b
|
7
|
+
data.tar.gz: 98b8abdcf12ef59e76b02b2b9c01b609eaeee4016cf55a89e6a10172d9d2c925fd2f96b1c069f54243c45f9227a044f72b0da2289c629f419114aa28a579a6ad
|
data/.document
ADDED
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown --title "fluent-plugin-exec_cron Documentation" --protected
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# fluent-plugin-exec_cron [](http://travis-ci.org/toyama0919/fluent-plugin-exec_cron)
|
2
|
+
|
3
|
+
executes external programs with cron syntax.
|
4
|
+
|
5
|
+
## Examples
|
6
|
+
|
7
|
+
### minutely
|
8
|
+
```
|
9
|
+
<source>
|
10
|
+
type exec_cron
|
11
|
+
tag exec_cron.example
|
12
|
+
command echo '{"a":"a"}'
|
13
|
+
format json
|
14
|
+
cron * * * * *
|
15
|
+
graceful_shutdown false
|
16
|
+
</source>
|
17
|
+
|
18
|
+
<match exec_cron.example>
|
19
|
+
type stdout
|
20
|
+
</match>
|
21
|
+
```
|
22
|
+
|
23
|
+
#### output
|
24
|
+
```
|
25
|
+
2015-05-27 13:07:00 +0900 exec_cron.example: {"a":"a"}
|
26
|
+
2015-05-27 13:08:00 +0900 exec_cron.example: {"a":"a"}
|
27
|
+
2015-05-27 13:09:00 +0900 exec_cron.example: {"a":"a"}
|
28
|
+
2015-05-27 13:10:00 +0900 exec_cron.example: {"a":"a"}
|
29
|
+
2015-05-27 13:11:00 +0900 exec_cron.example: {"a":"a"}
|
30
|
+
2015-05-27 13:12:00 +0900 exec_cron.example: {"a":"a"}
|
31
|
+
```
|
32
|
+
|
33
|
+
### hourly
|
34
|
+
```
|
35
|
+
<source>
|
36
|
+
type exec_cron
|
37
|
+
tag exec_cron.example
|
38
|
+
command echo '{"a":"a"}'
|
39
|
+
format json
|
40
|
+
cron 0 * * * *
|
41
|
+
graceful_shutdown true
|
42
|
+
</source>
|
43
|
+
|
44
|
+
<match exec_cron.example>
|
45
|
+
type stdout
|
46
|
+
</match>
|
47
|
+
```
|
48
|
+
|
49
|
+
#### output
|
50
|
+
```
|
51
|
+
2015-05-27 12:00:00 +0900 exec_cron.example: {"a":"a"}
|
52
|
+
2015-05-27 13:00:00 +0900 exec_cron.example: {"a":"a"}
|
53
|
+
```
|
54
|
+
|
55
|
+
|
56
|
+
## Installation
|
57
|
+
```
|
58
|
+
sudo td-agent-gem install fluent-plugin-exec_cron
|
59
|
+
```
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
1. Fork it
|
64
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
66
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
67
|
+
5. Create new [Pull Request](../../pull/new/master)
|
68
|
+
|
69
|
+
## Information
|
70
|
+
|
71
|
+
* [Homepage](https://github.com/toyama0919/fluent-plugin-exec_cron)
|
72
|
+
* [Issues](https://github.com/toyama0919/fluent-plugin-exec_cron/issues)
|
73
|
+
* [Documentation](http://rubydoc.info/gems/fluent-plugin-exec_cron/frames)
|
74
|
+
* [Email](mailto:toyama0919@gmail.com)
|
75
|
+
|
76
|
+
## Copyright
|
77
|
+
|
78
|
+
Copyright (c) 2015 Hiroshi Toyama
|
79
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
<source>
|
2
|
+
type forward
|
3
|
+
port 24224
|
4
|
+
</source>
|
5
|
+
|
6
|
+
<source>
|
7
|
+
type exec_cron
|
8
|
+
tag exec_cron.example
|
9
|
+
command echo '{"a":"a"}'
|
10
|
+
format json
|
11
|
+
cron * * * * *
|
12
|
+
graceful_shutdown false
|
13
|
+
</source>
|
14
|
+
|
15
|
+
<match exec_cron.exsample>
|
16
|
+
type stdout
|
17
|
+
</match>
|
18
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = "fluent-plugin-exec_cron"
|
5
|
+
gem.version = "0.0.2"
|
6
|
+
gem.summary = %q{executes external programs with cron syntax.}
|
7
|
+
gem.description = %q{executes external programs with cron syntax.}
|
8
|
+
gem.license = "MIT"
|
9
|
+
gem.authors = ["Hiroshi Toyama"]
|
10
|
+
gem.email = "toyama0919@gmail.com"
|
11
|
+
gem.homepage = "https://github.com/toyama0919/fluent-plugin-exec_cron"
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($/)
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.require_paths = ['lib']
|
17
|
+
|
18
|
+
gem.add_runtime_dependency "parse-cron"
|
19
|
+
gem.add_development_dependency 'bundler', '~> 1.7.2'
|
20
|
+
gem.add_development_dependency 'fluentd'
|
21
|
+
gem.add_development_dependency 'pry', '~> 0.10.1'
|
22
|
+
gem.add_development_dependency 'rake', '~> 10.3.2'
|
23
|
+
gem.add_development_dependency 'rubocop', '~> 0.24.1'
|
24
|
+
gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
|
25
|
+
gem.add_development_dependency 'yard', '~> 0.8'
|
26
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module Fluent
|
2
|
+
class ExecCronInput < Input
|
3
|
+
Plugin.register_input('exec_cron', self)
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
super
|
7
|
+
require 'fluent/plugin/exec_util'
|
8
|
+
require 'fluent/timezone'
|
9
|
+
require 'parse-cron'
|
10
|
+
require 'erb'
|
11
|
+
end
|
12
|
+
|
13
|
+
SUPPORTED_FORMAT = {
|
14
|
+
'tsv' => :tsv,
|
15
|
+
'json' => :json,
|
16
|
+
'msgpack' => :msgpack,
|
17
|
+
}
|
18
|
+
|
19
|
+
unless method_defined?(:router)
|
20
|
+
define_method("router") { Fluent::Engine }
|
21
|
+
end
|
22
|
+
|
23
|
+
config_param :command, :string
|
24
|
+
config_param :format, :default => :tsv do |val|
|
25
|
+
f = SUPPORTED_FORMAT[val]
|
26
|
+
raise ConfigError, "Unsupported format '#{val}'" unless f
|
27
|
+
f
|
28
|
+
end
|
29
|
+
config_param :keys, :default => [] do |val|
|
30
|
+
val.split(',')
|
31
|
+
end
|
32
|
+
config_param :tag, :string, :default => nil
|
33
|
+
config_param :tag_key, :string, :default => nil
|
34
|
+
config_param :time_key, :string, :default => nil
|
35
|
+
config_param :time_format, :string, :default => nil
|
36
|
+
config_param :run_interval, :time, :default => nil
|
37
|
+
config_param :graceful_shutdown, :bool, :default => false
|
38
|
+
config_param :cron, :string
|
39
|
+
|
40
|
+
def configure(conf)
|
41
|
+
super
|
42
|
+
|
43
|
+
if localtime = conf['localtime']
|
44
|
+
@localtime = true
|
45
|
+
elsif utc = conf['utc']
|
46
|
+
@localtime = false
|
47
|
+
end
|
48
|
+
|
49
|
+
if conf['timezone']
|
50
|
+
@timezone = conf['timezone']
|
51
|
+
Fluent::Timezone.validate!(@timezone)
|
52
|
+
end
|
53
|
+
|
54
|
+
if !@tag && !@tag_key
|
55
|
+
raise ConfigError, "'tag' or 'tag_key' option is required on exec input"
|
56
|
+
end
|
57
|
+
|
58
|
+
if @time_key
|
59
|
+
if @time_format
|
60
|
+
f = @time_format
|
61
|
+
@time_parse_proc = Proc.new {|str| Time.strptime(str, f).to_i }
|
62
|
+
else
|
63
|
+
@time_parse_proc = Proc.new {|str| str.to_i }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
case @format
|
68
|
+
when :tsv
|
69
|
+
if @keys.empty?
|
70
|
+
raise ConfigError, "keys option is required on exec input for tsv format"
|
71
|
+
end
|
72
|
+
@parser = ExecUtil::TSVParser.new(@keys, method(:on_message))
|
73
|
+
when :json
|
74
|
+
@parser = ExecUtil::JSONParser.new(method(:on_message))
|
75
|
+
when :msgpack
|
76
|
+
@parser = ExecUtil::MessagePackParser.new(method(:on_message))
|
77
|
+
end
|
78
|
+
|
79
|
+
begin
|
80
|
+
@cron_parser = CronParser.new(@cron)
|
81
|
+
rescue => e
|
82
|
+
raise ConfigError, "invalid cron expression. [#{@cron}]"
|
83
|
+
end
|
84
|
+
@command = ERB.new(@command.gsub(/\$\{([^}]+)\}/, '<%= \1 %>'))
|
85
|
+
end
|
86
|
+
|
87
|
+
def start
|
88
|
+
@finished = false
|
89
|
+
@thread = Thread.new(&method(:run_periodic))
|
90
|
+
end
|
91
|
+
|
92
|
+
def shutdown
|
93
|
+
@finished = true
|
94
|
+
if @graceful_shutdown
|
95
|
+
@thread.join
|
96
|
+
else
|
97
|
+
Thread.kill(@thread)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def run_periodic
|
102
|
+
until @finished
|
103
|
+
begin
|
104
|
+
secs = @cron_parser.next(Time.now) - Time.now
|
105
|
+
sleep secs
|
106
|
+
io = IO.popen(@command.result(binding), "r")
|
107
|
+
@parser.call(io)
|
108
|
+
Process.waitpid(io.pid)
|
109
|
+
rescue
|
110
|
+
log.error "exec failed to run or shutdown child process", :error => $!.to_s, :error_class => $!.class.to_s
|
111
|
+
log.warn_backtrace $!.backtrace
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def on_message(record)
|
119
|
+
if val = record.delete(@tag_key)
|
120
|
+
tag = val
|
121
|
+
else
|
122
|
+
tag = @tag
|
123
|
+
end
|
124
|
+
|
125
|
+
if val = record.delete(@time_key)
|
126
|
+
time = @time_parse_proc.call(val)
|
127
|
+
else
|
128
|
+
time = Engine.now
|
129
|
+
end
|
130
|
+
|
131
|
+
router.emit(tag, time, record)
|
132
|
+
rescue => e
|
133
|
+
log.error "exec failed to emit", :error => e.to_s, :error_class => e.class.to_s, :tag => tag, :record => Yajl.dump(record)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
14
|
+
require 'fluent/test'
|
15
|
+
require 'fluent/plugin/in_exec_cron'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class ExecCronInputTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
Fluent::Test.setup
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_driver(conf)
|
9
|
+
Fluent::Test::InputTestDriver.new(Fluent::ExecCronInput).configure(conf)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_configure_full
|
13
|
+
d = create_driver %q{
|
14
|
+
type exec_cron
|
15
|
+
tag exec_cron.example
|
16
|
+
command echo '{"a":"a"}'
|
17
|
+
format json
|
18
|
+
cron * * * * *
|
19
|
+
graceful_shutdown false
|
20
|
+
}
|
21
|
+
|
22
|
+
assert_equal 'exec_cron.example', d.instance.tag
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_configure_error_when_config_is_empty
|
26
|
+
assert_raise(Fluent::ConfigError) do
|
27
|
+
create_driver ''
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_configure_error_cron_syntax
|
32
|
+
assert_raise(Fluent::ConfigError) do
|
33
|
+
create_driver %q{
|
34
|
+
tag exec_cron.example
|
35
|
+
command echo '{"a":"a"}'
|
36
|
+
format json
|
37
|
+
cron hogehoge
|
38
|
+
graceful_shutdown false
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_configure_placeholder
|
44
|
+
d = create_driver %q{
|
45
|
+
type exec_cron
|
46
|
+
tag exec_cron.example
|
47
|
+
command echo '{"a":"${(Date.new(2015, 1, 1) - 1).strftime('%Y/%m/%d')}"}'
|
48
|
+
format json
|
49
|
+
cron * * * * *
|
50
|
+
graceful_shutdown false
|
51
|
+
}
|
52
|
+
assert_equal %Q{echo '{"a":"2014/12/31"}'}, d.instance.command.result(binding)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_emit
|
56
|
+
d = create_driver %q{
|
57
|
+
tag exec_cron.example
|
58
|
+
command echo '{"a":"a", "time":"2011-01-02 13:14:15"}'
|
59
|
+
format json
|
60
|
+
time_key time
|
61
|
+
time_format %Y-%m-%d %H:%M:%S
|
62
|
+
cron * * * * *
|
63
|
+
graceful_shutdown false
|
64
|
+
}
|
65
|
+
|
66
|
+
d.run do
|
67
|
+
sleep 60
|
68
|
+
end
|
69
|
+
|
70
|
+
emits = d.emits
|
71
|
+
assert_equal true, emits.length > 0
|
72
|
+
assert_equal ["exec_cron.example", Time.parse("2011-01-02 13:14:15").to_i, {"a"=>"a"}], emits[0]
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
metadata
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-exec_cron
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hiroshi Toyama
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: parse-cron
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.7.2
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.7.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: fluentd
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.10.1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.10.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 10.3.2
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 10.3.2
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.24.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.24.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubygems-tasks
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.2'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.2'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.8'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.8'
|
125
|
+
description: executes external programs with cron syntax.
|
126
|
+
email: toyama0919@gmail.com
|
127
|
+
executables: []
|
128
|
+
extensions: []
|
129
|
+
extra_rdoc_files: []
|
130
|
+
files:
|
131
|
+
- ".document"
|
132
|
+
- ".gitignore"
|
133
|
+
- ".travis.yml"
|
134
|
+
- ".yardopts"
|
135
|
+
- Gemfile
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- exsample/exsample.conf
|
139
|
+
- fluent-plugin-exec_cron.gemspec
|
140
|
+
- lib/fluent/plugin/in_exec_cron.rb
|
141
|
+
- test/helper.rb
|
142
|
+
- test/plugin/test_in_exec_cron.rb
|
143
|
+
homepage: https://github.com/toyama0919/fluent-plugin-exec_cron
|
144
|
+
licenses:
|
145
|
+
- MIT
|
146
|
+
metadata: {}
|
147
|
+
post_install_message:
|
148
|
+
rdoc_options: []
|
149
|
+
require_paths:
|
150
|
+
- lib
|
151
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
requirements: []
|
162
|
+
rubyforge_project:
|
163
|
+
rubygems_version: 2.4.2
|
164
|
+
signing_key:
|
165
|
+
specification_version: 4
|
166
|
+
summary: executes external programs with cron syntax.
|
167
|
+
test_files:
|
168
|
+
- test/helper.rb
|
169
|
+
- test/plugin/test_in_exec_cron.rb
|
170
|
+
has_rdoc:
|