sshkit 0.0.7 → 0.0.8
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.
- 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
|