crontest 0.1.0

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.
Files changed (5) hide show
  1. data/LICENSE +23 -0
  2. data/README.org +54 -0
  3. data/bin/crontest +16 -0
  4. data/lib/crontest.rb +115 -0
  5. metadata +98 -0
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2010, Ari Russo
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+ * Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ * The names of its contributors may not be used to endorse or promote products
12
+ derived from this software without specific prior written permission.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
18
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,54 @@
1
+ #+COMMENT: -*- org -*-
2
+ #+TITLE: crontest
3
+ #+AUTHOR: Ari Russo
4
+ #+DATE: 2010-10-28 Wed
5
+ #+TEXT: ruby command line tool/library for testing cron jobs
6
+ #+KEYWORDS: cron, crontest, cron-test, crontab, linux, unix, test, tasks, jobs
7
+ #+LANGUAGE: en
8
+ #+LINK_HOME: http://github.com/arirusso/crontest
9
+
10
+ * Summary
11
+
12
+ Ruby libary and command line tool for testing cron jobs.
13
+
14
+ * Description
15
+
16
+ Execute an (almost) immediate and transient cron job using the same environment that is used to run your user's crontab.
17
+
18
+ * Requires
19
+
20
+ - [[http://github.com/soveran/clap][clap]]
21
+
22
+ * Usage
23
+
24
+ : gem install crontest
25
+
26
+ to run crontest from the command line:
27
+
28
+ : crontest 'echo hello! > MY_CRON_TEST.txt' &
29
+
30
+ or, to call from another ruby program
31
+
32
+ : require 'crontest'
33
+ : Crontest.run("echo hello! > MY_CRON_TEST.txt")
34
+
35
+ these will both run =echo hello! > MY_CRON_TEST.txt= as a cron job. it can take up to a minute to run as cron's timing resolution is one minute.
36
+
37
+ crontest will create a backup file of your current crontab (cron-backup-[timestamp]) in the directory where directory you run it, and then restore it.
38
+
39
+ Options:
40
+
41
+ pass in options from the command line or Crontest.run(command, options)
42
+
43
+ : --no-backup
44
+ : -n
45
+ : :backup => false
46
+ no backup file
47
+
48
+ : -v
49
+ : :verbose => true
50
+ verbose output
51
+
52
+ * Caution
53
+
54
+ I highly encourage you to keep a separate backup of your crontab before trying this tool as it is brand new and relatively untested.
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+ require 'rubygems'
4
+ require 'clap'
5
+ require 'crontest'
6
+
7
+ opts = {}
8
+
9
+ args = Clap.run ARGV,
10
+ "--no-backup" => lambda { || opts[:backup] = false },
11
+ "-n" => lambda { || opts[:backup] = false },
12
+ "-v" => lambda { || opts[:verbose] = true }
13
+
14
+ command = args.first or raise "no command specified"
15
+
16
+ Crontest.run(command, opts)
@@ -0,0 +1,115 @@
1
+ module Crontest
2
+
3
+ VERSION = "0.1.0"
4
+
5
+ def self.run(command, opts = {})
6
+ Process.new(command, opts).run
7
+ end
8
+
9
+ class CrontabFile
10
+
11
+ attr_reader :path, :contents
12
+
13
+ # create temp file with current cron + new cron task in it using current time + @offset second offset
14
+ def initialize(path)
15
+ @contents = Crontest::CrontabHelper.current_crontab
16
+ @path = path
17
+ File.open(@path, 'w') {|f| f.write(@contents) }
18
+ end
19
+
20
+ # deletes the file
21
+ def delete
22
+ File.delete(@path)
23
+ end
24
+
25
+ end
26
+
27
+ class CrontabHelper
28
+
29
+ def self.cronify(command)
30
+ "* * * * * #{command}"
31
+ end
32
+
33
+ def self.activate(text, time)
34
+ if text.chomp.eql?('')
35
+ %x[crontab -r]
36
+ else
37
+ tmpfile = "/tmp/cron-#{time}"
38
+ %x[echo \"#{text}\" >> #{tmpfile}]
39
+ %x[crontab #{tmpfile}]
40
+ result = system("crontab #{tmpfile}") # to get the result type - is there a better way to do this?
41
+ %x[rm #{tmpfile}]
42
+ result
43
+ end
44
+ end
45
+
46
+ # get current crontab
47
+ def self.current_crontab
48
+ %x[crontab -l]
49
+ end
50
+
51
+ end
52
+
53
+ class Process
54
+
55
+ def initialize(command, opts = {})
56
+ @do_backup = opts[:backup] || true
57
+ @verbose = opts[:verbose] || false
58
+ @command = command
59
+ end
60
+
61
+ def run
62
+ raise "current directory must be writable" unless pwd_writable?
63
+
64
+ crontab_on_enter = CrontabHelper.current_crontab
65
+ time = Time.now.strftime('%Y%m%d%H%M%S')
66
+ @backup = CrontabFile.new("crontab-backup-#{time}")
67
+
68
+ new_crontab = @backup.contents + CrontabHelper.cronify(@command)
69
+ out("testing command #{new_crontab}")
70
+ CrontabHelper.activate(new_crontab, time) || crontab_on_enter.eql?(CrontabHelper.current_crontab) or
71
+ quit_with_error("command not accepted by cron")
72
+
73
+ wait_time = calc_wait_time
74
+ out("test will run in #{wait_time} seconds", true)
75
+ sleep(wait_time)
76
+
77
+ CrontabHelper.activate(@backup.contents, time) # restore to original crontab
78
+
79
+ unless crontab_on_enter.eql?(CrontabHelper.current_crontab)
80
+ quit_with_error("restored crontab doesn't match original")
81
+ end
82
+
83
+ cleanup(@do_backup)
84
+
85
+ out('finished', true)
86
+ end
87
+
88
+ private
89
+
90
+ def cleanup(keep_backup)
91
+ keep_backup ?
92
+ out("saved backup file #{Dir.pwd}/#{@backup.path}") :
93
+ @backup.delete
94
+ end
95
+
96
+ def calc_wait_time
97
+ 2 + (60 - Time.now.strftime('%S').to_i)
98
+ end
99
+
100
+ def out(text, always_show = false)
101
+ STDOUT.puts("crontest: #{text}") if (@verbose || always_show)
102
+ end
103
+
104
+ def quit_with_error(error)
105
+ cleanup(true)
106
+ raise error
107
+ end
108
+
109
+ def pwd_writable?
110
+ File.writable?('.')
111
+ end
112
+
113
+ end
114
+
115
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: crontest
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Ari Russo
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-02 00:00:00 -04:00
19
+ default_executable: crontest
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: clap
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: clap
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ description: ruby command line tool/library for testing cron jobs
50
+ email:
51
+ - ari.russo@gmail.com
52
+ executables:
53
+ - crontest
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - bin/crontest
60
+ - lib/crontest.rb
61
+ - LICENSE
62
+ - README.org
63
+ has_rdoc: true
64
+ homepage: http://github.com/arirusso/crontest
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options: []
69
+
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ requirements: []
91
+
92
+ rubyforge_project:
93
+ rubygems_version: 1.3.7
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Execute an (almost) immediate and transient cron job
97
+ test_files: []
98
+