rubycron 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gem "mail"
data/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # RubyCron
2
+
3
+ Define your cronjobs in your favorite language, and get reporting for free!
4
+
5
+ By letting RubyCron deal with warnings, errors, and sending reports, you can focus on writing clean and effective cronjobs in Ruby.
6
+
7
+ ## Author
8
+
9
+ * Bart Kamphorst
10
+
11
+ ## Installation
12
+ #> gem install rubycron
13
+
14
+ ### Dependencies
15
+
16
+ This gem depends on [Mikel's wonderful mail gem](https://github.com/mikel/mail).
17
+
18
+ In order to send mail, it assumes you have a local smtp server running on port 25.
19
+
20
+ ## Usage
21
+
22
+ ### Configure the basics
23
+
24
+ Open a new file, require and include RubyCron, and then initialize a new RubyCronJob as follows:
25
+
26
+ rcj = RubyCronJob.new do |script|
27
+ script.author = 'John Doe'
28
+ script.name = 'test'
29
+ script.mailto = 'john@doe.com'
30
+ end
31
+
32
+ ### Write your cronjob
33
+
34
+ Call RubyCronJob's execute method, and define your cronjob within the do-end block.
35
+
36
+ rcj.execute do
37
+ unless File.directory?('/tmp')
38
+ warning "Something awry is going on with /tmp."
39
+ end
40
+ begin
41
+ File.open('/tmp/rubycrontest', 'w') do |f|
42
+ f.write("Test completed successfully.")
43
+ end
44
+ rescue => e
45
+ error "Something went wrong trying to write to file: #{e.message}"
46
+ end
47
+ end
48
+
49
+ That's it! Now when you run this cronjob, you will receive a report by email.
50
+
51
+ ## Set up Cron
52
+
53
+ To activate the cronjob, add it to your crontab like any other cronjob. There are, however, two ways to do this: run the RubyCronJob as a stand-alone script, or have the RubyCronJob be executed by rcjrunner.rb.
54
+
55
+ ### Stand-alone
56
+
57
+ For the stand-alone option, add a crontab entry like so:
58
+
59
+ min hour mday month wday command
60
+ * * * * * test.rcj
61
+
62
+ For this to work properly, make sure your rubycronjob (test.rcj in this example) starts with a shebang and is executable.
63
+
64
+ ### Using rcjrunner.rb
65
+
66
+ Simply feed your rubycronjob to rcjrunner.rb as a command-line argument in your crontab entry:
67
+
68
+ min hour mday month wday command
69
+ * * * * * rcjrunner.rb test.rcj
70
+
71
+ ## Other configuration options
72
+
73
+ ### I now get all these reports, but I really only care if the job fails!
74
+
75
+ Sorting through hundreds of cron mails per day that report successful runs may be gratifying at times, but most sane people only care to be notified when their cronjobs fail. Not to worry, just add to following line to the RubyCronJob's initialization.
76
+
77
+ script.mailon = :error
78
+
79
+ RubyCron will now only report when errors occurred during the run. Other options are :none, :warning and :all (default).
80
+
81
+ ### All emails originate from root@localhost. Can I change that?
82
+
83
+ Of course. Use
84
+
85
+ script.mailfrom = 'root@doe.com'
86
+
87
+ to change the From:-header.
88
+
89
+ ### I want my cronjob to stop running when there are errors.
90
+
91
+ No problem. You can configure this behavior with
92
+
93
+ script.exiton = :all
94
+
95
+ Valid values are :none, :warning, :error, :all.
96
+
97
+ ### May I please see some output while I'm developing my cronjob?
98
+
99
+ Output to stdout and stderr can be very useful when debugging your cronjob. Just set the verbose flag to true:
100
+
101
+ script.verbose = true
102
+
103
+ ### As a sysadmin, I like grepping through files. Can I have a log file please?
104
+
105
+ Yes. Set a file path in RubyCronJob's logfile variable, and all output will be redirected to file:
106
+
107
+ script.logfile = '/tmp/rcjlogfile'
108
+
109
+ Note that you will still receive email reports when you enable file logging.
110
+
111
+ ## License
112
+
113
+ Copyright (c) 2011, Bart Kamphorst
114
+
115
+ (Modified BSD License)
116
+
117
+ All rights reserved.
118
+
119
+ Redistribution and use in source and binary forms, with or without
120
+ modification, are permitted provided that the following conditions are met:
121
+
122
+ * Redistributions of source code must retain the above copyright
123
+ notice, this list of conditions and the following disclaimer.
124
+ * Redistributions in binary form must reproduce the above copyright
125
+ notice, this list of conditions and the following disclaimer in the
126
+ documentation and/or other materials provided with the distribution.
127
+ * Neither the name of the organization nor the
128
+ names of its contributors may be used to endorse or promote products
129
+ derived from this software without specific prior written permission.
130
+
131
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
132
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
133
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
134
+ DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
135
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
136
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
137
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
138
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
139
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
140
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/bin/rcjrunner.rb ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'RubyCron'
5
+ include RubyCron
6
+
7
+ if ARGV.empty? || ARGV.size > 1
8
+ $stderr.puts "## Usage: rcjrunner.rb <rubycronjob>"
9
+ else
10
+ instance_eval File.read(ARGV[0])
11
+ end
data/lib/report.erb ADDED
@@ -0,0 +1,25 @@
1
+ This is your RubyCron mailer reporting on <%= self.name %>.
2
+
3
+ There were <%= @warnings.size %> warnings and <%= @errors.size %> errors during the last run, which started at
4
+ <%= @starttime %> and ended at <%= @endtime %>.
5
+ <% unless @warnings.empty? %>
6
+ <%= "These were the warnings:" %>
7
+ <% @warnings.each_with_index do |warning, index| %>
8
+ <%= index + 1 %>: <%= warning %>
9
+ <%= "============================================================" %>
10
+ <% end %> <% end %>
11
+ <% unless @errors.empty? %>
12
+ <%= "These were the errors:" %>
13
+ <% @errors.each_with_index do |error, index| %>
14
+ <%= index + 1 %>: <%= error %>
15
+ <%= "============================================================" %>
16
+ <% end %> <% end %>
17
+ <% if @warnings.empty? && @errors.empty? %>
18
+ <%= "There were no problems to report. Have a nice day!" %>
19
+ <% else %>
20
+ <%= "Please look into these matters asap." %>
21
+ <% end %>
22
+
23
+
24
+
25
+ ## Powered by RubyCron.
data/lib/rubycron.rb ADDED
@@ -0,0 +1,106 @@
1
+ # Copyright (c) Bart Kamphorst <rubycron@kamphorst.com>, 2011
2
+ # Licensed under the modified BSD License. All rights reserved.
3
+
4
+ module RubyCron
5
+
6
+ class RubyCronJob
7
+
8
+ require 'net/smtp'
9
+ require 'rubygems'
10
+ require 'mail'
11
+ require 'erb'
12
+
13
+ attr_accessor :name, :author, :mailto, :mailfrom, :mailsubject, :mailon, :exiton, :logfile, :verbose
14
+
15
+ def initialize(&block)
16
+ @warnings, @errors = [], []
17
+
18
+ instance_eval(&block)
19
+ terminate("Cannot connect to local smtp server.") unless smtp_connection?
20
+ terminate("This job has no name.") unless self.name
21
+ terminate("This job has no author.") unless self.author
22
+ terminate("No To: header was set. ") unless self.mailto
23
+
24
+ self.mailfrom ||= 'root@localhost'
25
+ self.verbose ||= false
26
+ self.mailon = :all unless self.mailon && [:none, :warning, :error, :all].include?(self.mailon)
27
+ self.exiton = :all unless self.exiton && [:none, :warning, :error, :all].include?(self.exiton)
28
+
29
+ if self.logfile
30
+ $stdout.reopen(self.logfile, "a")
31
+ $stdout.sync = true
32
+ $stderr.reopen($stdout)
33
+ end
34
+ rescue => e
35
+ $stdout = STDOUT
36
+ terminate(e.message)
37
+ end
38
+
39
+ def terminate(message)
40
+ $stderr.puts "## Cannot complete job. Reason: #{message}"
41
+ exit 1
42
+ end
43
+
44
+ # Execute a given block of code (the cronjob), rescue encountered errors,
45
+ # and send a report about it if necessary.
46
+ def execute(&block)
47
+ @starttime = Time.now
48
+ puts "\nStarting run of #{self.name} at #{@starttime}.\n----" if self.verbose || self.logfile
49
+ instance_eval(&block)
50
+ rescue Exception => e
51
+ @errors << e.message
52
+ terminate(e.message) if exiton == (:error || :all)
53
+ ensure
54
+ @endtime = Time.now
55
+ if self.verbose || self.logfile
56
+ puts "Run ended at #{@endtime}.\n----"
57
+ puts "Number of warnings: #{@warnings.size}"
58
+ puts "Number of errors : #{@errors.size}"
59
+ end
60
+ unless self.mailon == :none || (@warnings.empty? && @errors.empty? && self.mailon != :all)
61
+ report
62
+ end
63
+ end
64
+
65
+ def warning(message)
66
+ $stderr.puts message if self.verbose || self.logfile
67
+ raise "Configured to exit on warning." if exiton == (:warning || :all)
68
+ @warnings << message
69
+ end
70
+
71
+ def error(message)
72
+ $stderr.puts message if self.verbose || self.logfile
73
+ raise "Configured to exit on error." if exiton == (:error || :all)
74
+ @errors << message
75
+ end
76
+
77
+ private
78
+ def smtp_connection?
79
+ return true if Net::SMTP.start('localhost', 25)
80
+ rescue
81
+ return false
82
+ end
83
+
84
+ # Report on the status of the cronjob through the use of
85
+ # an erb template file, and mikel's excellent mail gem.
86
+ private
87
+ def report
88
+ self.mailsubject = "Cron report for #{name}: #{@warnings.size} warnings & #{@errors.size} errors" unless self.mailsubject
89
+ mailfrom = self.mailfrom
90
+ mailto = self.mailto
91
+ mailsubject = self.mailsubject
92
+ mailbody = ERB.new(File.read(File.join(File.dirname(__FILE__), '/report.erb'))).result(binding)
93
+
94
+ mail = Mail.new do
95
+ from mailfrom
96
+ to mailto
97
+ subject mailsubject
98
+ body mailbody
99
+ end
100
+
101
+ mail.deliver!
102
+ rescue => e
103
+ terminate(e.message)
104
+ end
105
+ end
106
+ end
data/sample/test.rcj ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'RubyCron'
5
+ include RubyCron
6
+
7
+ rcj = RubyCronJob.new do |script|
8
+ script.author = 'John Doe'
9
+ script.name = 'test'
10
+ script.mailto = 'john@doe.com'
11
+ script.mailfrom = 'root@doe.com'
12
+ script.mailon = :all
13
+ script.exiton = :none
14
+ script.verbose = false
15
+ end
16
+
17
+ rcj.execute do
18
+ unless File.directory?('/tmp')
19
+ warning "Something awry is going on with /tmp."
20
+ end
21
+ begin
22
+ File.open('/tmp/rubycrontest', 'w') do |f|
23
+ f.write("Test completed successfully.")
24
+ end
25
+ rescue => e
26
+ error "Something went wrong trying to write to file: #{e.message}"
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubycron
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bart Kamphorst
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-19 00:00:00.000000000 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mail
17
+ requirement: &2160625260 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2160625260
26
+ description: Write clean cronjobs in Ruby, and get reporting for free!
27
+ email: rubycron@kamphorst.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files:
31
+ - README.md
32
+ files:
33
+ - README.md
34
+ - Gemfile
35
+ - lib/rubycron.rb
36
+ - lib/report.erb
37
+ - sample/test.rcj
38
+ - bin/rcjrunner.rb
39
+ has_rdoc: true
40
+ homepage: https://github.com/bartkamphorst/rubycron
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 1.6.2
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: Simplifies your Ruby cronjobs by automating the reporting process.
64
+ test_files: []