sshkit 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +23 -0
- data/EXAMPLES.md +19 -0
- data/README.md +7 -4
- data/lib/sshkit/backends/abstract.rb +4 -0
- data/lib/sshkit/backends/netssh.rb +5 -0
- data/lib/sshkit/command.rb +7 -1
- data/lib/sshkit/version.rb +1 -1
- data/test/{integration → functional}/backends/test_netssh.rb +22 -20
- data/test/unit/test_command.rb +15 -0
- metadata +3 -3
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,29 @@
|
|
3
3
|
This file is written in reverse chronological order, newer releases will
|
4
4
|
appear at the top.
|
5
5
|
|
6
|
+
## 0.0.8
|
7
|
+
|
8
|
+
* Added DSL method `background()` this sends a task to the background using
|
9
|
+
`nohup` and redirects it's output to `/dev/null` so as to avoid littering
|
10
|
+
the filesystem with `nohup.out` files.
|
11
|
+
|
12
|
+
**Note:** Backgrounding a task won't work as you expect if you give it a
|
13
|
+
string, that is you must do `background(:sleep, 5)` and not `background("sleep 5")`
|
14
|
+
according to the rules by which a command is not processed in any way **if it
|
15
|
+
contains a spaca character in it's first argument**.
|
16
|
+
|
17
|
+
Usage Example:
|
18
|
+
|
19
|
+
on hosts do
|
20
|
+
background :rake, "assets:precompile" # typically takes 5 minutes!
|
21
|
+
end
|
22
|
+
|
23
|
+
**Further:** Many programs are badly behaved and no not work well with `nohup`
|
24
|
+
it has to do with the way nohup works, reopening the processe's file
|
25
|
+
descriptors and redirecting them. Programs that re-open, or otherwise
|
26
|
+
manipulate their own file descriptors may lock up when the SSH session is
|
27
|
+
disconnected, often they block writing to, or reading from stdin/out.
|
28
|
+
|
6
29
|
## 0.0.7
|
7
30
|
|
8
31
|
* DSL method `execute()` will now raise `SSHKit::Command::Failed` when the
|
data/EXAMPLES.md
CHANGED
@@ -65,6 +65,25 @@ leading slashes. It may be misleading as the `File.join()` is performed on the
|
|
65
65
|
machine running the code, if that's a Windows box, the paths may be incorrectly
|
66
66
|
joined according to the expectations of the machine receiving the commands.
|
67
67
|
|
68
|
+
## Running a task in the background
|
69
|
+
|
70
|
+
on hosts do
|
71
|
+
in '/opt/sites/example.com' do
|
72
|
+
background :rails, :server
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
This will run something like `nohup /usr/bin/env rails server > /dev/null &`,
|
77
|
+
backgrounding the Rails process, and making sure we don't leave nohup log
|
78
|
+
files littering the filesystem.
|
79
|
+
|
80
|
+
**Note:** The `background()` method won't do what you expect if you pass a
|
81
|
+
string `sleep 5`, according to the rules of processing commands, you must call
|
82
|
+
`background(:sleep, "5")` (that is, command: sleep, args: 5).
|
83
|
+
|
84
|
+
**Further Note:** The background() task wraps the given command in `nohup .... &` under some
|
85
|
+
circumstances the program will hang anyway when the SSH session exits.
|
86
|
+
|
68
87
|
## Do not care about the host block
|
69
88
|
|
70
89
|
on hosts do
|
data/README.md
CHANGED
@@ -178,8 +178,8 @@ should be printed.
|
|
178
178
|
|
179
179
|
* No handling of slow / timed out connections
|
180
180
|
* No handling of slow / hung remote commands
|
181
|
-
* No built-in way to background() something (execute and background the
|
182
|
-
process)
|
181
|
+
* ~~No built-in way to background() something (execute and background the
|
182
|
+
process).~~
|
183
183
|
* No environment handling (sshkit might not need to care)
|
184
184
|
* ~~No arbitrary `Host` properties (example storing `roles` on servers, or other
|
185
185
|
metadata that might be useful in the `on()` block)~~
|
@@ -190,10 +190,10 @@ should be printed.
|
|
190
190
|
* No verbosity control, commands should have a `Logger::LEVEL` on them,
|
191
191
|
user-generated should be at a high level, the commands auto-generated from
|
192
192
|
the guards and checks from as() and within() should have a lower level.
|
193
|
-
* Decide if `execute()` (and friends) should raise on non-zero exit statuses or
|
193
|
+
* ~~Decide if `execute()` (and friends) should raise on non-zero exit statuses or
|
194
194
|
not, perhaps a family of similarly named bang methods should be the ones to
|
195
195
|
raise. (Perhaps `test()` should be a way to `execute()` without raising, and
|
196
|
-
`execute()` and friends should always raise)
|
196
|
+
`execute()` and friends should always raise)~~
|
197
197
|
* It would be nice to be able to say `SSHKit.config.formatter = :pretty` and
|
198
198
|
have that method setter do the legwork of updating `SSHKit.config.output` to
|
199
199
|
be an instance of the correct formatter class wrapping the existing output
|
@@ -204,3 +204,6 @@ should be printed.
|
|
204
204
|
easily be modified to look into some connection factory for it's objects,
|
205
205
|
saving half a second when running lots of `on()` blocks.
|
206
206
|
* Documentation! (YARD style)
|
207
|
+
* Wrap all commands in a known shell, that is that `execute('uptime')` should
|
208
|
+
be converted into `sh -c 'uptime'` to ensure that we have a consistent shell
|
209
|
+
experience.
|
@@ -20,6 +20,11 @@ module SSHKit
|
|
20
20
|
_execute(*args).success?
|
21
21
|
end
|
22
22
|
|
23
|
+
def background(*args)
|
24
|
+
options = args.extract_options!.merge(run_in_background: true)
|
25
|
+
_execute(*[*args, options]).success?
|
26
|
+
end
|
27
|
+
|
23
28
|
def capture(*args)
|
24
29
|
_execute(*args).stdout.strip
|
25
30
|
end
|
data/lib/sshkit/command.rb
CHANGED
@@ -128,11 +128,17 @@ module SSHKit
|
|
128
128
|
if options[:user]
|
129
129
|
cs << "sudo su #{options[:user]} -c "
|
130
130
|
end
|
131
|
+
if options[:run_in_background]
|
132
|
+
cs << 'nohup '
|
133
|
+
end
|
131
134
|
cs << SSHKit.config.command_map[command.to_sym]
|
132
135
|
if args.any?
|
133
136
|
cs << ' '
|
134
137
|
cs << args.join(' ')
|
135
138
|
end
|
139
|
+
if options[:run_in_background]
|
140
|
+
cs << ' > /dev/null &'
|
141
|
+
end
|
136
142
|
if options[:env]
|
137
143
|
cs << ' )'
|
138
144
|
end
|
@@ -142,7 +148,7 @@ module SSHKit
|
|
142
148
|
private
|
143
149
|
|
144
150
|
def default_options
|
145
|
-
{ raise_on_non_zero_exit: true }
|
151
|
+
{ raise_on_non_zero_exit: true, run_in_background: false }
|
146
152
|
end
|
147
153
|
|
148
154
|
def sanitize_command!
|
data/lib/sshkit/version.rb
CHANGED
@@ -1,22 +1,10 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'benchmark'
|
2
3
|
|
3
4
|
module SSHKit
|
4
5
|
|
5
6
|
module Backend
|
6
7
|
|
7
|
-
class ToSIoFormatter < StringIO
|
8
|
-
extend Forwardable
|
9
|
-
attr_reader :original_output
|
10
|
-
def_delegators :@original_output, :read, :rewind
|
11
|
-
def initialize(oio)
|
12
|
-
@original_output = oio
|
13
|
-
end
|
14
|
-
def write(obj)
|
15
|
-
warn "What: #{obj.to_hash}"
|
16
|
-
original_output.write "> Executing #{obj}\n"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
8
|
class TestNetssh < FunctionalTest
|
21
9
|
|
22
10
|
def setup
|
@@ -47,19 +35,18 @@ module SSHKit
|
|
47
35
|
end
|
48
36
|
|
49
37
|
def simple_netssh
|
50
|
-
sio = ToSIoFormatter.new(StringIO.new)
|
51
38
|
SSHKit.capture_output(sio) do
|
52
39
|
printer.run
|
53
40
|
end
|
54
41
|
sio.rewind
|
55
42
|
result = sio.read
|
56
43
|
assert_equal <<-EOEXPECTED.unindent, result
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
44
|
+
if test ! -d /opt/sites/example.com; then echo "Directory does not exist '/opt/sites/example.com'" 2>&1; false; fi
|
45
|
+
cd /opt/sites/example.com && /usr/bin/env date
|
46
|
+
cd /opt/sites/example.com && /usr/bin/env ls -l /some/directory
|
47
|
+
if test ! -d /opt/sites/example.com/tmp; then echo "Directory does not exist '/opt/sites/example.com/tmp'" 2>&1; false; fi
|
48
|
+
if ! sudo su -u root whoami > /dev/null; then echo "You cannot switch to user 'root' using sudo, please check the sudoers file" 2>&1; false; fi
|
49
|
+
cd /opt/sites/example.com/tmp && ( RAILS_ENV=production ( sudo su -u root /usr/bin/env touch restart.txt ) )
|
63
50
|
EOEXPECTED
|
64
51
|
end
|
65
52
|
|
@@ -90,6 +77,21 @@ module SSHKit
|
|
90
77
|
end.run
|
91
78
|
end
|
92
79
|
|
80
|
+
def test_backgrounding_a_process
|
81
|
+
#SSHKit.config.output = SSHKit::Formatter::Pretty.new($stdout)
|
82
|
+
process_list = ""
|
83
|
+
time = Benchmark.measure do
|
84
|
+
Netssh.new(a_host) do
|
85
|
+
background :sleep, 5
|
86
|
+
end.run
|
87
|
+
Netssh.new(a_host) do
|
88
|
+
process_list = capture :ps, "aux | grep sleep | grep -v grep; true"
|
89
|
+
end.run
|
90
|
+
end
|
91
|
+
assert_operator time.real, :<, 1
|
92
|
+
assert_match "sleep 5", process_list
|
93
|
+
end
|
94
|
+
|
93
95
|
end
|
94
96
|
|
95
97
|
end
|
data/test/unit/test_command.rb
CHANGED
@@ -51,6 +51,21 @@ module SSHKit
|
|
51
51
|
assert_equal "sudo su anotheruser -c /usr/bin/env whoami", String(c)
|
52
52
|
end
|
53
53
|
|
54
|
+
def test_backgrounding_a_task
|
55
|
+
c = Command.new(:sleep, 15, run_in_background: true)
|
56
|
+
assert_equal "nohup /usr/bin/env sleep 15 > /dev/null &", String(c)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_backgrounding_a_task_as_a_given_user
|
60
|
+
c = Command.new(:sleep, 15, run_in_background: true, user: :anotheruser)
|
61
|
+
assert_equal "sudo su anotheruser -c nohup /usr/bin/env sleep 15 > /dev/null &", String(c)
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_backgrounding_a_task_as_a_given_user_with_env
|
65
|
+
c = Command.new(:sleep, 15, run_in_background: true, user: :anotheruser, env: {a: :b})
|
66
|
+
assert_equal "( A=b sudo su anotheruser -c nohup /usr/bin/env sleep 15 > /dev/null & )", String(c)
|
67
|
+
end
|
68
|
+
|
54
69
|
def test_complete?
|
55
70
|
c = Command.new(:whoami, raise_on_non_zero_exit: false)
|
56
71
|
refute c.complete?
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sshkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -256,10 +256,10 @@ files:
|
|
256
256
|
- lib/sshkit/runners/sequential.rb
|
257
257
|
- lib/sshkit/version.rb
|
258
258
|
- sshkit.gemspec
|
259
|
+
- test/functional/backends/test_netssh.rb
|
259
260
|
- test/functional/test_coordinator.rb
|
260
261
|
- test/functional/test_ssh_server_comes_up_for_functional_tests.rb
|
261
262
|
- test/helper.rb
|
262
|
-
- test/integration/backends/test_netssh.rb
|
263
263
|
- test/unit/backends/test_netssh.rb
|
264
264
|
- test/unit/backends/test_printer.rb
|
265
265
|
- test/unit/core_ext/test_string.rb
|
@@ -292,10 +292,10 @@ signing_key:
|
|
292
292
|
specification_version: 3
|
293
293
|
summary: SSHKit makes it easy to write structured, testable SSH commands in Ruby
|
294
294
|
test_files:
|
295
|
+
- test/functional/backends/test_netssh.rb
|
295
296
|
- test/functional/test_coordinator.rb
|
296
297
|
- test/functional/test_ssh_server_comes_up_for_functional_tests.rb
|
297
298
|
- test/helper.rb
|
298
|
-
- test/integration/backends/test_netssh.rb
|
299
299
|
- test/unit/backends/test_netssh.rb
|
300
300
|
- test/unit/backends/test_printer.rb
|
301
301
|
- test/unit/core_ext/test_string.rb
|