minicron 0.3 → 0.4
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 +4 -4
- data/README.md +42 -33
- data/bin/minicron +3 -0
- data/lib/minicron.rb +12 -3
- data/lib/minicron/alert.rb +9 -6
- data/lib/minicron/cli.rb +15 -6
- data/lib/minicron/cli/commands.rb +35 -12
- data/lib/minicron/constants.rb +1 -1
- data/lib/minicron/cron.rb +71 -30
- data/lib/minicron/hub/app.rb +6 -0
- data/lib/minicron/hub/assets/app/components/schedules.js +1 -1
- data/lib/minicron/hub/assets/app/controllers/hosts.js +6 -2
- data/lib/minicron/hub/assets/app/controllers/jobs.js +5 -2
- data/lib/minicron/hub/assets/app/controllers/schedules.js +15 -13
- data/lib/minicron/hub/assets/app/models/host.js +1 -0
- data/lib/minicron/hub/assets/app/models/job.js +1 -0
- data/lib/minicron/hub/controllers/api/executions.rb +0 -1
- data/lib/minicron/hub/controllers/api/hosts.rb +12 -13
- data/lib/minicron/hub/controllers/api/job_execution_outputs.rb +0 -1
- data/lib/minicron/hub/controllers/api/jobs.rb +5 -3
- data/lib/minicron/hub/controllers/api/schedule.rb +3 -1
- data/lib/minicron/hub/db/schema.rb +8 -6
- data/lib/minicron/hub/db/schema.sql +4 -2
- data/lib/minicron/hub/views/handlebars/hosts.erb +18 -0
- data/lib/minicron/hub/views/handlebars/jobs.erb +18 -0
- data/lib/minicron/monitor.rb +14 -12
- data/lib/minicron/transport.rb +0 -1
- data/lib/minicron/transport/client.rb +19 -11
- data/lib/minicron/transport/faye/client.rb +16 -2
- data/lib/minicron/transport/faye/extensions/job_handler.rb +10 -4
- data/lib/minicron/transport/faye/server.rb +5 -4
- data/lib/minicron/transport/server.rb +9 -4
- data/lib/minicron/transport/ssh.rb +5 -4
- data/spec/minicron/alert/pagerduty_spec.rb +1 -0
- data/spec/minicron/alert/sms_spec.rb +1 -0
- data/spec/minicron/cli_spec.rb +1 -0
- data/spec/minicron/transport/client_spec.rb +1 -0
- data/spec/minicron/transport/faye/client_spec.rb +1 -0
- data/spec/minicron/transport/server_spec.rb +1 -0
- data/spec/minicron/transport_spec.rb +1 -0
- data/spec/minicron_spec.rb +6 -0
- metadata +88 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b6939554f2e620783856cad085a5caebb87d70c
|
4
|
+
data.tar.gz: 3384f8536105f764031a7035c9a3fea95b985bcf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9420b0503c77643198a875eda7a194630186dd9809f90574b1c234eff524ffc9a1f6b925dc5e766ad775f2d9f89e94e3450c3c810347157d55de6745f9b8287
|
7
|
+
data.tar.gz: d4ffe62daecf9ae0abab5b85baf68d40da45a6c1b89a68b20793c4256a7488c8b1e875e4827ab5bcf0856d455c2260d5ed5cf1359b5d41e60d4d9fdc70b487b7
|
data/README.md
CHANGED
@@ -14,23 +14,31 @@ server(s) and executes your cron command and reports the status back to the Hub.
|
|
14
14
|
where data from one or many instances of the CLI are is recieved and stored in a database. The Hub also provides
|
15
15
|
a web interface to the data and makes it easy to manage your cron jobs.
|
16
16
|
|
17
|
-
- [
|
18
|
-
- [
|
19
|
-
- [
|
20
|
-
- [
|
21
|
-
- [
|
22
|
-
- [
|
23
|
-
- [
|
24
|
-
- [
|
25
|
-
- [
|
26
|
-
- [
|
17
|
+
- [Screenshots](#screenshots)
|
18
|
+
- [Background](#background)
|
19
|
+
- [Features](#goals)
|
20
|
+
- [Requirements](#requirements)
|
21
|
+
- [Installation](#installation)
|
22
|
+
- [Usage](#usage)
|
23
|
+
- [Documentation](#documentation)
|
24
|
+
- [Versioning](#versioning)
|
25
|
+
- [Contributing](#contributing)
|
26
|
+
- [Support](#support)
|
27
|
+
- [License](#license)
|
28
|
+
|
29
|
+
Screenshots
|
30
|
+
------------
|
31
|
+
|
32
|
+
<img src="http://f.cl.ly/items/2o3q3x1N1X3n2t180H1u/Image%202014-04-12%20at%2010.54.39%20pm.png" height="100"/>
|
33
|
+
|
34
|
+
More coming..
|
27
35
|
|
28
36
|
Background
|
29
37
|
-----------
|
30
38
|
|
31
|
-
I'm developing minicron as part of my dissertation at university which
|
32
|
-
development after that.
|
33
|
-
[Miniclip](http://www.miniclip.com) where the management and monitoring of cron jobs at times proved to be tricky!
|
39
|
+
I'm developing minicron as part of my dissertation at university which has to be completed by May but I plan to continue
|
40
|
+
development after that. The inspiration for developing minicron comes from my own experience, in particular my time spent
|
41
|
+
working at [Miniclip](http://www.miniclip.com) where the management and monitoring of cron jobs at times proved to be tricky!
|
34
42
|
|
35
43
|
Features
|
36
44
|
---------
|
@@ -43,9 +51,9 @@ Features
|
|
43
51
|
- Alerts when jobs executions are missed or fail via:
|
44
52
|
- Email
|
45
53
|
- SMS ([using Twilio](https://www.twilio.com))
|
46
|
-
- [PagerDuty](www.pagerduty.com)
|
54
|
+
- [PagerDuty](http://www.pagerduty.com) (SMS, Phone, Mobile Push Notifications and Email)
|
47
55
|
|
48
|
-
Lots more is planned for the future, see issues
|
56
|
+
Lots more is planned for the future, see [open issues](issues?state=open) or if you don't see the feature you want there add it!
|
49
57
|
|
50
58
|
Requirements
|
51
59
|
-------------
|
@@ -53,7 +61,7 @@ Requirements
|
|
53
61
|
#### Ruby
|
54
62
|
- **MRI**: 1.9.3 and above (tested on 1.9.3, 2.0.0, 2.1.0)
|
55
63
|
- <del>**Rubinius**: Travis builds are run on the latest release</del> [*awaiting bug fix*](https://github.com/rubinius/rubinius/issues/2944)
|
56
|
-
- **JRuby:** currently untested but most likely needs some
|
64
|
+
- **JRuby:** currently untested but most likely needs some work
|
57
65
|
|
58
66
|
#### Database
|
59
67
|
|
@@ -63,7 +71,7 @@ Requirements
|
|
63
71
|
#### Web Server / Reverse Proxy
|
64
72
|
|
65
73
|
If you want to run minicron behind a web server or proxy it needs to support the web socket protocol.
|
66
|
-
nginx for example supports web sockets from version 1.3.13 and up. I've included an [example config](
|
74
|
+
nginx for example supports web sockets from version 1.3.13 and up. I've included an [example config](sample.nginx.conf) for nginx.
|
67
75
|
|
68
76
|
#### Browser
|
69
77
|
|
@@ -72,22 +80,22 @@ I'm currently unsure of how it functions in the various of Internet Explorer but
|
|
72
80
|
|
73
81
|
#### OS
|
74
82
|
|
75
|
-
Should run on any linux/bsd based OS that the above ruby versions run on.
|
83
|
+
Should run on osx and any linux/bsd based OS that the above ruby versions run on.
|
76
84
|
|
77
85
|
Installation
|
78
86
|
-------------
|
79
87
|
|
80
88
|
minicron is currently under heavy development and as such I would not recommend that you use this in production yet
|
81
|
-
but I encourage you to give it a try in a non critical environment and help me to improve it.
|
89
|
+
but I encourage you to give it a try in a non critical environment and help me to improve it and work towards the first stable release (1.0).
|
82
90
|
|
83
|
-
1. First check you meet the [requirements](
|
91
|
+
1. First check you meet the [requirements](#requirements)
|
84
92
|
|
85
93
|
2. On some distributions you may need to install the ````ruby-dev```` and ````build-essential```` packages
|
86
94
|
|
87
|
-
3. To install the latest release (currently 0.
|
95
|
+
3. To install the latest release (currently 0.4) you can ````gem install minicron````, depending on your ruby setup
|
88
96
|
you may need to run this with ````sudo````
|
89
97
|
|
90
|
-
4. Set your database configuration options in ````/etc/minicron.toml````, you can use the [default.config.toml](
|
98
|
+
4. Set your database configuration options in ````/etc/minicron.toml````, you can use the [default.config.toml](default.config.toml) as a guide on what options are configurable
|
91
99
|
|
92
100
|
5. Make sure you have created an empty database with the name you set in ````/etc/minicron.toml````
|
93
101
|
|
@@ -99,7 +107,7 @@ but I encourage you to give it a try in a non critical environment and help me t
|
|
99
107
|
> ````
|
100
108
|
|
101
109
|
6. You can then ````minicron db setup```` to create the database schema, alternatively you can use
|
102
|
-
the [schema dump provided](
|
110
|
+
the [schema dump provided](lib/minicron/hub/db/schema.sql)
|
103
111
|
|
104
112
|
7. Done! See the usage section below for more details on how to use minicron now you have it installed
|
105
113
|
|
@@ -149,7 +157,7 @@ you can also use the ````stop```` and ````status```` commands to control the ser
|
|
149
157
|
To run the server in debug mode, i.e not as a daemon so you can see its output you can pass the ````--debug````
|
150
158
|
option.
|
151
159
|
|
152
|
-
See [sample.nginx.conf](
|
160
|
+
See [sample.nginx.conf](sample.nginx.conf) for an example of
|
153
161
|
how to run minicron behind a reverse proxy.
|
154
162
|
|
155
163
|
#### Connecting to a host via SSH
|
@@ -163,7 +171,7 @@ most linux distributions or ````/var/root/.ssh/authorized_keys```` on OSX.
|
|
163
171
|
|
164
172
|
#### Version
|
165
173
|
|
166
|
-
Like many command line programs minicron will show
|
174
|
+
Like many command line programs minicron will show its version number when the global options ````-v````
|
167
175
|
or ````--version```` are passed to the CLI.
|
168
176
|
|
169
177
|
#### Configuration
|
@@ -171,14 +179,14 @@ or ````--version```` are passed to the CLI.
|
|
171
179
|
Some configuration options can be passed in manually but the recommend way to configure minicron is through the use
|
172
180
|
of a config file. You can specify the path to the file using the ````--config```` global option. The file is expected
|
173
181
|
to be in the [toml](https://github.com/mojombo/toml "toml") format. The default options are specified in the
|
174
|
-
[default.config.toml](
|
182
|
+
[default.config.toml](default.config.toml "default.config.toml")
|
175
183
|
file and minicron will parse a config located in ````/etc/minicron.toml```` if it exists. Options specified via
|
176
184
|
the command line will take precedence over those taken from a config file.
|
177
185
|
|
178
186
|
Documentation
|
179
187
|
-------------
|
180
188
|
|
181
|
-
minicron uses [Yard](http://yardoc.org/ "Yard") for
|
189
|
+
minicron uses [Yard](http://yardoc.org/ "Yard") for its code documentation (currently the only *usage* documentation is what you're reading right now), you can either generate it and view
|
182
190
|
it locally using the following commands:
|
183
191
|
|
184
192
|
````bash
|
@@ -191,7 +199,8 @@ or view the most up to date version online at [RubyDoc.info](http://rdoc.info/gi
|
|
191
199
|
Versioning
|
192
200
|
-----------
|
193
201
|
|
194
|
-
|
202
|
+
All stable releases will follow the [semantic versioning](http://semver.org/) guidelines. Until 1.0 hits I will try to document any
|
203
|
+
major breaking changes in the release descriptions.
|
195
204
|
|
196
205
|
Releases will be numbered with the following format:
|
197
206
|
|
@@ -206,17 +215,17 @@ Based on the following guidelines:
|
|
206
215
|
Contributing
|
207
216
|
------------
|
208
217
|
|
209
|
-
Feedback and pull requests are welcome, please see [CONTRIBUTING.md](
|
218
|
+
Feedback and pull requests are welcome, please see [CONTRIBUTING.md](CONTRIBUTING.md "CONTRIBUTING.md") for more info.
|
210
219
|
|
211
220
|
Areas that I would love some help with:
|
212
221
|
|
213
|
-
- Any of the unassigned [issues here](
|
222
|
+
- Any of the unassigned [issues here](issues?state=open).
|
214
223
|
- General testing of the system, let me know what you think and create issues for any bugs you find!
|
215
224
|
- Tests!!
|
216
225
|
- Validation and error handling improvements
|
217
|
-
- Documentation improvements.
|
226
|
+
- Documentation improvements. If you find something confusing or unexpected let me know and I'll add or improve
|
218
227
|
documentation for it!
|
219
|
-
- Look for '[TODO:](
|
228
|
+
- Look for '[TODO:](search?q=TODO%3A)' notices littered around the code,
|
220
229
|
I'm trying to convert them all to issues but there are a lot..
|
221
230
|
- Code refactoring, I had a reasonably tight deadline to have the main concept done by so some parts are a bit rushed
|
222
231
|
- UI improvements
|
@@ -234,4 +243,4 @@ Or feel free to open an issue and I'll do my best to help.
|
|
234
243
|
License
|
235
244
|
--------
|
236
245
|
|
237
|
-
minicron is licensed under the GPL v3, [see here for the full license](
|
246
|
+
minicron is licensed under the GPL v3, [see here for the full license](LICENSE "see here")
|
data/bin/minicron
CHANGED
@@ -4,6 +4,9 @@ require 'minicron'
|
|
4
4
|
require 'minicron/cli'
|
5
5
|
require 'minicron/transport/server'
|
6
6
|
|
7
|
+
# Set the process name to something more useful
|
8
|
+
$PROGRAM_NAME = "minicron #{ARGV.join(' ')}"
|
9
|
+
|
7
10
|
begin
|
8
11
|
# Capture any output from STDERR so we can handle it how we want to
|
9
12
|
Minicron.capture_output(:type => :stderr) do
|
data/lib/minicron.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
require 'stringio'
|
2
|
-
require 'toml'
|
3
|
-
require 'sshkey'
|
4
1
|
require 'minicron/constants'
|
5
2
|
|
6
3
|
# @author James White <dev.jameswhite+minicron@gmail.com>
|
7
4
|
module Minicron
|
5
|
+
# Define module autoloading
|
6
|
+
autoload :TOML, 'toml'
|
7
|
+
autoload :StringIO, 'stringio'
|
8
|
+
autoload :SSHKey, 'sshkey'
|
9
|
+
|
8
10
|
# Default configuration, this can be overriden
|
9
11
|
@config = {
|
10
12
|
'verbose' => false,
|
@@ -179,4 +181,11 @@ module Minicron
|
|
179
181
|
def self.get_hostname
|
180
182
|
`hostname -s`.strip
|
181
183
|
end
|
184
|
+
|
185
|
+
# Get the user minicron is being run as
|
186
|
+
#
|
187
|
+
# @return [String]
|
188
|
+
def self.get_user
|
189
|
+
`whoami`.strip
|
190
|
+
end
|
182
191
|
end
|
data/lib/minicron/alert.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
-
require 'minicron/alert/email'
|
2
|
-
require 'minicron/alert/sms'
|
3
|
-
require 'minicron/alert/pagerduty'
|
4
|
-
require 'minicron/hub/models/alert'
|
5
|
-
require 'minicron/hub/models/job'
|
6
|
-
|
7
1
|
module Minicron
|
2
|
+
autoload :Email, 'minicron/alert/email'
|
3
|
+
autoload :SMS, 'minicron/alert/sms'
|
4
|
+
autoload :PagerDuty, 'minicron/alert/pagerduty'
|
5
|
+
|
6
|
+
module Hub
|
7
|
+
autoload :Alert, 'minicron/hub/models/alert'
|
8
|
+
autoload :Job, 'minicron/hub/models/job'
|
9
|
+
end
|
10
|
+
|
8
11
|
# Allows the sending of alerts via multiple mediums
|
9
12
|
class Alert
|
10
13
|
# Send an alert using all enabled mediums
|
data/lib/minicron/cli.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
|
-
|
1
|
+
autoload :PTY, 'pty'
|
2
|
+
autoload :Minicron, 'minicron'
|
3
|
+
|
2
4
|
require 'English'
|
3
5
|
require 'rainbow/ext/string'
|
4
6
|
require 'commander'
|
5
7
|
require 'minicron/constants'
|
6
8
|
require 'minicron/cli/commands'
|
7
|
-
require 'minicron/transport'
|
8
|
-
require 'minicron/transport/client'
|
9
|
-
require 'minicron/transport/server'
|
10
|
-
require 'minicron/monitor'
|
11
9
|
|
12
10
|
include Commander::UI
|
13
11
|
|
14
12
|
module Minicron
|
13
|
+
autoload :Transport, 'minicron/transport'
|
14
|
+
autoload :Monitor, 'minicron/monitor'
|
15
|
+
|
16
|
+
module Transport
|
17
|
+
autoload :Client, 'minicron/transport/client'
|
18
|
+
autoload :Server, 'minicron/transport/server'
|
19
|
+
end
|
20
|
+
|
15
21
|
# Handles the main CLI interaction of minicron
|
16
22
|
# TODO: this class is probably too complicated and should be refactored a bit
|
17
23
|
module CLI
|
@@ -188,6 +194,9 @@ module Minicron
|
|
188
194
|
@cli.program :version, Minicron::VERSION
|
189
195
|
@cli.program :description, 'cli for minicron; a system a to manage and monitor cron jobs'
|
190
196
|
|
197
|
+
# Display the output in a compact format
|
198
|
+
@cli.program :help_formatter, Commander::HelpFormatter::TerminalCompact
|
199
|
+
|
191
200
|
# Set the default command to run
|
192
201
|
@cli.default_command :help
|
193
202
|
|
@@ -197,7 +206,7 @@ module Minicron
|
|
197
206
|
end
|
198
207
|
|
199
208
|
# Add a global option for verbose mode
|
200
|
-
@cli.global_option '--verbose', "Turn on verbose mode. Default: #{Minicron.config['
|
209
|
+
@cli.global_option '--verbose', "Turn on verbose mode. Default: #{Minicron.config['verbose'].to_s}" do
|
201
210
|
Minicron.config['verbose'] = true
|
202
211
|
end
|
203
212
|
|
@@ -1,8 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
autoload :Minicron, 'minicron'
|
2
|
+
autoload :Insidious, 'insidious'
|
3
|
+
autoload :Rake, 'rake'
|
4
|
+
|
5
|
+
module Sinatra
|
6
|
+
autoload :ActiveRecordTasks, 'sinatra/activerecord/rake'
|
7
|
+
end
|
4
8
|
|
5
9
|
module Minicron
|
10
|
+
autoload :Transport, 'minicron/transport'
|
11
|
+
|
12
|
+
module Transport
|
13
|
+
autoload :Client, 'minicron/transport/client'
|
14
|
+
autoload :Server, 'minicron/transport/server'
|
15
|
+
end
|
16
|
+
|
17
|
+
module Hub
|
18
|
+
autoload :App, 'minicron/hub/app'
|
19
|
+
end
|
20
|
+
|
6
21
|
module CLI
|
7
22
|
class Commands
|
8
23
|
# Add the `minicron db` command
|
@@ -20,11 +35,6 @@ module Minicron
|
|
20
35
|
# Parse the file and cli config options
|
21
36
|
Minicron::CLI.parse_config(opts)
|
22
37
|
|
23
|
-
# These are inlined as we only need them in this use case
|
24
|
-
require 'rake'
|
25
|
-
require 'minicron/hub/app'
|
26
|
-
require 'sinatra/activerecord/rake'
|
27
|
-
|
28
38
|
# Setup the db
|
29
39
|
Minicron::Hub::App.setup_db
|
30
40
|
|
@@ -125,7 +135,16 @@ module Minicron
|
|
125
135
|
# Set up the job and get the jexecution and job ids back from the server
|
126
136
|
ids = setup_job(args.first, faye)
|
127
137
|
end
|
138
|
+
rescue Exception => e
|
139
|
+
raise Exception, "Unable to setup job, reason: #{e.message}"
|
128
140
|
|
141
|
+
# Ensure that all messages are delivered and that we
|
142
|
+
unless Minicron.config['cli']['dry_run']
|
143
|
+
faye.tidy_up
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
begin
|
129
148
|
# Execute the command and yield the output
|
130
149
|
Minicron::CLI.run_command(args.first, :mode => Minicron.config['cli']['mode'], :verbose => Minicron.config['verbose']) do |output|
|
131
150
|
# We need to handle the yielded output differently based on it's type
|
@@ -143,6 +162,7 @@ module Minicron
|
|
143
162
|
yield output[:output] unless output[:type] == :status
|
144
163
|
end
|
145
164
|
rescue Exception => e
|
165
|
+
p e
|
146
166
|
# Send the exception message to the server and yield it
|
147
167
|
unless Minicron.config['cli']['dry_run']
|
148
168
|
faye.send(:job_id => ids[:job_id], :execution_id => ids[:execution_id], :type => :output, :message => e.message)
|
@@ -171,9 +191,6 @@ module Minicron
|
|
171
191
|
# Get the fully qualified domain name of the currnet host
|
172
192
|
fqdn = Minicron.get_fqdn
|
173
193
|
|
174
|
-
# Get the short hostname of the current host
|
175
|
-
hostname = Minicron.get_hostname
|
176
|
-
|
177
194
|
# Get the md5 hash for the job
|
178
195
|
job_hash = Minicron::Transport.get_job_hash(command, fqdn)
|
179
196
|
|
@@ -181,7 +198,13 @@ module Minicron
|
|
181
198
|
faye.ensure_em_running
|
182
199
|
|
183
200
|
# Setup the job on the server
|
184
|
-
ids = faye.setup(
|
201
|
+
ids = faye.setup(
|
202
|
+
:job_hash => job_hash,
|
203
|
+
:user => Minicron.get_user,
|
204
|
+
:command => command,
|
205
|
+
:fqdn => fqdn,
|
206
|
+
:hostname => Minicron.get_hostname
|
207
|
+
)
|
185
208
|
|
186
209
|
# Wait until we get the execution id
|
187
210
|
faye.ensure_delivery
|
data/lib/minicron/constants.rb
CHANGED
data/lib/minicron/cron.rb
CHANGED
@@ -3,9 +3,6 @@ require 'escape'
|
|
3
3
|
|
4
4
|
module Minicron
|
5
5
|
# Used to interact with the crontab on hosts over an ssh connection
|
6
|
-
# TODO: I've had a moment of clarity, I don't need to do all the CRUD
|
7
|
-
# using unix commands. I can cat the crontab, manipulate it in ruby
|
8
|
-
# and then echo it back!
|
9
6
|
class Cron
|
10
7
|
# Initialise the cron class
|
11
8
|
#
|
@@ -16,15 +13,49 @@ module Minicron
|
|
16
13
|
|
17
14
|
# Build the minicron command to be used in the crontab
|
18
15
|
#
|
19
|
-
# @param command [String]
|
20
16
|
# @param schedule [String]
|
17
|
+
# @param user [String]
|
18
|
+
# @param command [String]
|
21
19
|
# @return [String]
|
22
|
-
def build_minicron_command(
|
20
|
+
def build_minicron_command(schedule, user, command)
|
23
21
|
# Escape the command so it will work in bourne shells
|
24
22
|
command = Escape.shell_command(['minicron', 'run', command])
|
25
|
-
cron_command =Escape.shell_command(['/bin/bash', '-l', '-c', command])
|
23
|
+
cron_command = Escape.shell_command(['/bin/bash', '-l', '-c', command])
|
26
24
|
|
27
|
-
"#{schedule}
|
25
|
+
"#{schedule} #{user} #{cron_command}"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Test an SSH connection and the permissions for the crontab
|
29
|
+
#
|
30
|
+
# @param conn an instance of an open ssh connection
|
31
|
+
# @return [Hash]
|
32
|
+
def test_host_permissions(conn = nil)
|
33
|
+
# Open an SSH connection
|
34
|
+
conn ||= @ssh.open
|
35
|
+
|
36
|
+
# Check if /etc is writeable
|
37
|
+
etc_write = conn.exec!("/bin/sh -c 'test -w /etc && echo \"y\" || echo \"n\"'").strip
|
38
|
+
|
39
|
+
# Check if /etc is executable
|
40
|
+
etc_execute = conn.exec!("/bin/sh -c 'test -x /etc && echo \"y\" || echo \"n\"'").strip
|
41
|
+
|
42
|
+
# Check if the crontab is readable
|
43
|
+
crontab_read = conn.exec!("/bin/sh -c 'test -r /etc/crontab && echo \"y\" || echo \"n\"'").strip
|
44
|
+
|
45
|
+
# Check if the crontab is writeable
|
46
|
+
crontab_write = conn.exec!("/bin/sh -c 'test -w /etc/crontab && echo \"y\" || echo \"n\"'").strip
|
47
|
+
|
48
|
+
{
|
49
|
+
:connect => true,
|
50
|
+
:etc => {
|
51
|
+
:write => etc_write == 'y',
|
52
|
+
:execute => etc_execute == 'y'
|
53
|
+
},
|
54
|
+
:crontab => {
|
55
|
+
:read => crontab_read == 'y',
|
56
|
+
:write => crontab_write == 'y'
|
57
|
+
}
|
58
|
+
}
|
28
59
|
end
|
29
60
|
|
30
61
|
# Used to find a string and replace it with another in the crontab by
|
@@ -34,7 +65,27 @@ module Minicron
|
|
34
65
|
# @param find [String]
|
35
66
|
# @param replace [String]
|
36
67
|
def find_and_replace(conn, find, replace)
|
37
|
-
|
68
|
+
begin
|
69
|
+
# Test the SSH connection first
|
70
|
+
test = test_host_permissions(conn)
|
71
|
+
rescue Exception => e
|
72
|
+
raise Exception, "Error connecting to host, reason: #{e.message}"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Check the connection worked
|
76
|
+
raise Exception, "Unable to connect to host, reason: unknown" if !test[:connect]
|
77
|
+
|
78
|
+
# Check the crontab is readable
|
79
|
+
raise Exception, "Insufficient permissions to read from /etc/crontab" if !test[:crontab][:read]
|
80
|
+
|
81
|
+
# Check the crontab is writeable
|
82
|
+
raise Exception, "Insufficient permissions to write to /etc/crontab" if !test[:crontab][:write]
|
83
|
+
|
84
|
+
# Check /etc is writeable
|
85
|
+
raise Exception, "/etc is not writeable by the current user" if !test[:etc][:write]
|
86
|
+
|
87
|
+
# Check /etc is executable
|
88
|
+
raise Exception, "/etc is not executable by the current user" if !test[:etc][:execute]
|
38
89
|
|
39
90
|
# Get the full crontab
|
40
91
|
crontab = conn.exec!('cat /etc/crontab').to_s.strip
|
@@ -47,17 +98,12 @@ module Minicron
|
|
47
98
|
end
|
48
99
|
|
49
100
|
# Echo the crontab back to the tmp crontab
|
50
|
-
|
51
|
-
|
52
|
-
# Throw an exception if it failed
|
53
|
-
if update != 'y'
|
54
|
-
fail Exception, "Unable to replace '#{find}' with '#{replace}' in the crontab"
|
55
|
-
end
|
101
|
+
conn.exec!("echo #{crontab.shellescape} > /tmp/minicron_crontab").to_s.strip
|
56
102
|
|
57
103
|
# If it's a delete
|
58
104
|
if replace == ''
|
59
105
|
# Check the original line is no longer there
|
60
|
-
grep = conn.exec!("grep -F #{find.shellescape} /
|
106
|
+
grep = conn.exec!("grep -F #{find.shellescape} /tmp/minicron_crontab").to_s.strip
|
61
107
|
|
62
108
|
# Throw an exception if we can't see our new line at the end of the file
|
63
109
|
if grep != replace
|
@@ -65,7 +111,7 @@ module Minicron
|
|
65
111
|
end
|
66
112
|
else
|
67
113
|
# Check the updated line is there
|
68
|
-
grep = conn.exec!("grep -F #{replace.shellescape} /
|
114
|
+
grep = conn.exec!("grep -F #{replace.shellescape} /tmp/minicron_crontab").to_s.strip
|
69
115
|
|
70
116
|
# Throw an exception if we can't see our new line at the end of the file
|
71
117
|
if grep != replace
|
@@ -74,10 +120,10 @@ module Minicron
|
|
74
120
|
end
|
75
121
|
|
76
122
|
# And finally replace the crontab with the new one now we now the change worked
|
77
|
-
move = conn.exec!("mv /
|
123
|
+
move = conn.exec!("/bin/sh -c 'mv /tmp/minicron_crontab /etc/crontab && echo \"y\" || echo \"n\"'").to_s.strip
|
78
124
|
|
79
125
|
if move != 'y'
|
80
|
-
fail Exception, 'Unable to move tmp crontab
|
126
|
+
fail Exception, 'Unable to move /tmp/minicron_crontab to /etc/crontab, check the permissions?'
|
81
127
|
end
|
82
128
|
end
|
83
129
|
|
@@ -91,20 +137,15 @@ module Minicron
|
|
91
137
|
conn ||= @ssh.open
|
92
138
|
|
93
139
|
# Prepare the line we are going to write to the crontab
|
94
|
-
line = build_minicron_command(job.
|
140
|
+
line = build_minicron_command(schedule, job.user, job.command)
|
95
141
|
escaped_line = line.shellescape
|
96
|
-
echo_line = "echo #{escaped_line} >> /etc/crontab
|
142
|
+
echo_line = "echo #{escaped_line} >> /etc/crontab"
|
97
143
|
|
98
144
|
# Append it to the end of the crontab
|
99
|
-
|
100
|
-
|
101
|
-
# Throw an exception if it failed
|
102
|
-
if write != 'y'
|
103
|
-
fail Exception, "Unable to echo #{escaped_line} to the crontab"
|
104
|
-
end
|
145
|
+
conn.exec!(echo_line).to_s.strip
|
105
146
|
|
106
147
|
# Check the line is there
|
107
|
-
tail = conn.exec!('tail -n 1 /etc/crontab').strip
|
148
|
+
tail = conn.exec!('tail -n 1 /etc/crontab').to_s.strip
|
108
149
|
|
109
150
|
# Throw an exception if we can't see our new line at the end of the file
|
110
151
|
if tail != line
|
@@ -123,10 +164,10 @@ module Minicron
|
|
123
164
|
conn ||= @ssh.open
|
124
165
|
|
125
166
|
# We are looking for the current value of the schedule
|
126
|
-
find = build_minicron_command(job.
|
167
|
+
find = build_minicron_command(old_schedule, job.user, job.command)
|
127
168
|
|
128
169
|
# And replacing it with the updated value
|
129
|
-
replace = build_minicron_command(job.
|
170
|
+
replace = build_minicron_command(new_schedule, job.user, job.command)
|
130
171
|
|
131
172
|
# Replace the old schedule with the new schedule
|
132
173
|
find_and_replace(conn, find, replace)
|
@@ -142,7 +183,7 @@ module Minicron
|
|
142
183
|
conn ||= @ssh.open
|
143
184
|
|
144
185
|
# We are looking for the current value of the schedule
|
145
|
-
find = build_minicron_command(job.
|
186
|
+
find = build_minicron_command(schedule, job.user, job.command)
|
146
187
|
|
147
188
|
# Replace the old schedule with nothing i.e deleting it
|
148
189
|
find_and_replace(conn, find, '')
|