script_executor 1.3.2 → 1.3.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 +15 -0
- data/.idea/codeStyleSettings.xml +14 -0
- data/.idea/misc.xml +1 -1
- data/.idea/script_executor.iml +195 -14
- data/.idea/workspace.xml +408 -345
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGES +9 -1
- data/Gemfile +6 -13
- data/Gemfile.lock +10 -1
- data/README.md +96 -20
- data/lib/executable.rb +0 -2
- data/lib/script_executor.rb +0 -2
- data/lib/script_executor/executable.rb +10 -121
- data/lib/script_executor/local_command.rb +78 -0
- data/lib/script_executor/remote_command.rb +91 -0
- data/lib/script_executor/version.rb +2 -2
- data/lib/script_locator.rb +0 -2
- data/spec/executable_spec.rb +1 -2
- data/spec/script_locator_spec.rb +5 -5
- metadata +10 -18
- data/.rbenv-gemsets +0 -1
- data/.rbenv-version +0 -1
- data/.rvmrc +0 -5
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
script_executor
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-1.9.3
|
data/CHANGES
CHANGED
data/Gemfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
3
|
group :default do
|
4
4
|
gem "highline"
|
@@ -15,16 +15,9 @@ group :test do
|
|
15
15
|
gem "mocha"
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# gem "linecache19", "0.5.13"
|
26
|
-
# gem "ruby-debug-base19x", "0.11.30.pre10"
|
27
|
-
# gem "ruby-debug-ide", "0.4.17.beta14"
|
28
|
-
# end
|
29
|
-
#end
|
18
|
+
group :debug do
|
19
|
+
gem "ruby-debug-base19x", "0.11.30.pre12"
|
20
|
+
gem "ruby-debug-ide", "0.4.17"
|
21
|
+
end
|
22
|
+
|
30
23
|
|
data/Gemfile.lock
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
GEM
|
2
|
-
remote:
|
2
|
+
remote: https://rubygems.org/
|
3
3
|
specs:
|
4
|
+
debugger-ruby_core_source (1.2.2)
|
4
5
|
diff-lcs (1.1.3)
|
5
6
|
file_utils (1.0.6)
|
6
7
|
gemcutter (0.7.1)
|
@@ -11,6 +12,7 @@ GEM
|
|
11
12
|
mocha (0.13.1)
|
12
13
|
metaclass (~> 0.0.1)
|
13
14
|
net-ssh (2.6.2)
|
15
|
+
rake (10.0.4)
|
14
16
|
rspec (2.12.0)
|
15
17
|
rspec-core (~> 2.12.0)
|
16
18
|
rspec-expectations (~> 2.12.0)
|
@@ -19,6 +21,11 @@ GEM
|
|
19
21
|
rspec-expectations (2.12.1)
|
20
22
|
diff-lcs (~> 1.1.3)
|
21
23
|
rspec-mocks (2.12.0)
|
24
|
+
ruby-debug-base19x (0.11.30.pre12)
|
25
|
+
debugger-ruby_core_source (>= 1.1.4)
|
26
|
+
rake (>= 0.8.1)
|
27
|
+
ruby-debug-ide (0.4.17)
|
28
|
+
rake (>= 0.8.1)
|
22
29
|
|
23
30
|
PLATFORMS
|
24
31
|
ruby
|
@@ -30,3 +37,5 @@ DEPENDENCIES
|
|
30
37
|
mocha
|
31
38
|
net-ssh
|
32
39
|
rspec
|
40
|
+
ruby-debug-base19x (= 0.11.30.pre12)
|
41
|
+
ruby-debug-ide (= 0.4.17)
|
data/README.md
CHANGED
@@ -4,39 +4,115 @@
|
|
4
4
|
|
5
5
|
Add this line to your application's Gemfile:
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
```bash
|
8
|
+
gem 'script_executor'
|
9
|
+
```
|
9
10
|
And then execute:
|
10
11
|
|
11
|
-
|
12
|
+
```bash
|
13
|
+
bundle
|
14
|
+
```
|
12
15
|
|
13
16
|
Or install it yourself as:
|
14
17
|
|
15
|
-
|
18
|
+
```bash
|
19
|
+
gem install script_executor
|
20
|
+
```
|
16
21
|
|
17
22
|
## Usage
|
18
|
-
|
19
|
-
executor = ScriptExecutor.new
|
20
23
|
|
21
|
-
|
24
|
+
```ruby
|
25
|
+
# Create executor
|
26
|
+
executor = ScriptExecutor.new
|
27
|
+
```
|
28
|
+
|
29
|
+
* Execute local command:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
executor.execute "ls"
|
33
|
+
```
|
34
|
+
|
35
|
+
* Execute remote command:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
server_info = {
|
39
|
+
:remote => true,
|
40
|
+
:domain => "some.host",
|
41
|
+
:user => "some.user",
|
42
|
+
}
|
43
|
+
|
44
|
+
executor.execute server_info.merge(:script => "ls -al")
|
45
|
+
```
|
46
|
+
|
47
|
+
* Execute remote command as 'sudo':
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
executor.execute server_info.merge({:sudo => true, :script => "/etc/init.d/tomcat stop"})
|
51
|
+
```
|
52
|
+
|
53
|
+
* Execute remote command with code block:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
executor.execute server_info.merge(:sudo => true) do
|
57
|
+
%Q(
|
58
|
+
/etc/init.d/tomcat stop
|
59
|
+
/etc/init.d/tomcat start
|
60
|
+
)
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
* Execute remote command while capturing and suppressing output (default is 'false'):
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
server_info.merge(:capture_output => true, :suppress_output => true)
|
68
|
+
|
69
|
+
result = executor.execute server_info.merge(:script => "whoami")
|
70
|
+
|
71
|
+
puts result # ENV['USER']
|
72
|
+
```
|
73
|
+
|
74
|
+
* Simulate remote execution:
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
server_info.merge(:simulate => true)
|
78
|
+
|
79
|
+
executor.execute server_info.merge(:script => "whoami") # generate commands without actual execution
|
80
|
+
```
|
81
|
+
|
82
|
+
## Using ScriptLocator
|
83
|
+
|
84
|
+
You can keep scripts that needs to be executed embedded into your code (as in examples above),
|
85
|
+
move them into separate file or keep them in same file behind "__END__" Ruby directive.
|
86
|
+
The latter gives you the ability to keep command and code together thus simplifying
|
87
|
+
access to code.
|
88
|
+
|
89
|
+
For example, if you want to create script with 2 commands (command1, command2), you can use
|
90
|
+
"scripts" and "evaluate_script_body" methods:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
require 'script_locator'
|
94
|
+
|
95
|
+
include ScriptLocator
|
96
|
+
|
97
|
+
puts scripts(__FILE__) # [command1, command2]
|
98
|
+
|
99
|
+
name = "john"
|
100
|
+
|
101
|
+
result = evaluate_script_body(result['command1'], binding)
|
102
|
+
|
103
|
+
puts result # john
|
104
|
+
__END__
|
105
|
+
|
106
|
+
[command1]
|
22
107
|
|
23
|
-
|
108
|
+
echo "<%= name %>"
|
24
109
|
|
25
|
-
|
110
|
+
[command2]
|
26
111
|
|
27
|
-
|
112
|
+
echo "test2"
|
113
|
+
```
|
28
114
|
|
29
|
-
server_info = {
|
30
|
-
:domain => "some.host",
|
31
|
-
:user => "some.user",
|
32
|
-
}
|
33
115
|
|
34
|
-
executor.remote_execute :sudo => true, server_info do # execute remote with sudo
|
35
|
-
%Q(
|
36
|
-
/etc/init.d/tomcat stop
|
37
|
-
/etc/init.d/tomcat start
|
38
|
-
)
|
39
|
-
end
|
40
116
|
|
41
117
|
## Contributing
|
42
118
|
|
data/lib/executable.rb
CHANGED
data/lib/script_executor.rb
CHANGED
@@ -1,14 +1,8 @@
|
|
1
|
-
require '
|
2
|
-
require
|
3
|
-
|
4
|
-
require 'script_executor/output_buffer'
|
1
|
+
require 'script_executor/local_command'
|
2
|
+
require 'script_executor/remote_command'
|
5
3
|
|
6
4
|
module Executable
|
7
5
|
|
8
|
-
def output
|
9
|
-
@output ||= $stdout
|
10
|
-
end
|
11
|
-
|
12
6
|
def execute params={}, &code
|
13
7
|
if params.class != Hash
|
14
8
|
simple_commands = commands_from_object(params)
|
@@ -21,120 +15,25 @@ module Executable
|
|
21
15
|
commands = locate_commands script, &code
|
22
16
|
|
23
17
|
if commands.nil?
|
24
|
-
output.puts "No
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
commands = sudo(commands) if params[:sudo]
|
29
|
-
|
30
|
-
remote = params[:remote]
|
31
|
-
domain = params[:domain]
|
32
|
-
user = params[:user]
|
33
|
-
password = params[:password]
|
34
|
-
capture_output = params[:capture_output]
|
35
|
-
suppress_output = params[:suppress_output]
|
36
|
-
simulate = params[:simulate]
|
37
|
-
line_action = params[:line_action]
|
38
|
-
|
39
|
-
print_execution commands, remote, domain, user, nil, simulate
|
18
|
+
output.puts "No command was provided!"
|
19
|
+
else
|
20
|
+
commands = sudo(commands) if params[:sudo]
|
40
21
|
|
41
|
-
|
42
|
-
|
43
|
-
suppress_output = suppress_output.nil? ? capture_output : suppress_output
|
22
|
+
remote = params.delete(:remote)
|
23
|
+
line_action = params.delete(:line_action)
|
44
24
|
|
45
25
|
if remote
|
46
|
-
|
26
|
+
command = RemoteCommand.new params
|
47
27
|
else
|
48
|
-
|
28
|
+
command = LocalCommand.new params
|
49
29
|
end
|
50
30
|
|
51
|
-
|
31
|
+
command.execute commands, line_action
|
52
32
|
end
|
53
33
|
end
|
54
34
|
|
55
35
|
private
|
56
36
|
|
57
|
-
def print_execution commands, remote, domain, user, identity_file, simulate
|
58
|
-
if remote
|
59
|
-
ssh_command = ssh_command(domain, user, identity_file)
|
60
|
-
|
61
|
-
if simulate
|
62
|
-
output.puts "Remote script: '#{ssh_command}'"
|
63
|
-
output.puts "-------"
|
64
|
-
print_commands commands
|
65
|
-
output.puts "-------"
|
66
|
-
else
|
67
|
-
output.puts "Remote execution on: '#{ssh_command}'"
|
68
|
-
output.puts "-------"
|
69
|
-
print_commands commands
|
70
|
-
output.puts "-------"
|
71
|
-
end
|
72
|
-
else
|
73
|
-
if simulate
|
74
|
-
output.puts "Script:"
|
75
|
-
output.puts "-------"
|
76
|
-
print_commands commands
|
77
|
-
output.puts "-------"
|
78
|
-
else
|
79
|
-
output.puts "Local execution:"
|
80
|
-
output.puts "-------"
|
81
|
-
print_commands(commands)
|
82
|
-
output.puts "-------"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def print_commands commands
|
88
|
-
lines = StringIO.new commands
|
89
|
-
|
90
|
-
lines.each_line do |line|
|
91
|
-
output.puts line
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def execute_command commands, password, line_action, suppress_output, storage
|
96
|
-
commands = commands + inline_password(password) if password
|
97
|
-
|
98
|
-
IO.popen(commands) do |pipe|
|
99
|
-
pipe.each("\r") do |line|
|
100
|
-
output.print(line) unless suppress_output
|
101
|
-
|
102
|
-
storage.save(line.chomp) if storage
|
103
|
-
|
104
|
-
line_action.call(line) if line_action
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def inline_password password
|
110
|
-
password ? "<<EOF\n#{password}\nEOF" : ""
|
111
|
-
end
|
112
|
-
|
113
|
-
def execute_ssh commands, domain, user, password, line_action, suppress_output, storage
|
114
|
-
if password.nil?
|
115
|
-
password = ask("Enter password for #{user}: ") { |q| q.echo = '*' }
|
116
|
-
end
|
117
|
-
|
118
|
-
Net::SSH.start(domain, user, :password => password) do |session|
|
119
|
-
session.exec "#{commands}" do |channel, _, line|
|
120
|
-
if line =~ /^\[sudo\] password for user:/ || line =~ /sudo password:/
|
121
|
-
#puts "Password request"
|
122
|
-
channel.request_pty # <- problem must be here.
|
123
|
-
channel.send_data password + "\n"
|
124
|
-
else
|
125
|
-
output.print(line) unless suppress_output
|
126
|
-
|
127
|
-
storage.save(line.chomp) if storage
|
128
|
-
|
129
|
-
line_action.call(line) if line_action
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# run the aggregated event loop
|
134
|
-
session.loop
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
37
|
def locate_commands script, &code
|
139
38
|
if block_given?
|
140
39
|
commands_from_block &code
|
@@ -163,16 +62,6 @@ module Executable
|
|
163
62
|
end
|
164
63
|
end
|
165
64
|
|
166
|
-
def ssh_command domain, user, identity_file
|
167
|
-
cmd = user.nil? ? domain : "#{user}@#{domain}"
|
168
|
-
|
169
|
-
cmd << " -i #{identity_file}" if identity_file
|
170
|
-
|
171
|
-
#cmd << " -t -t"
|
172
|
-
|
173
|
-
"ssh #{cmd}"
|
174
|
-
end
|
175
|
-
|
176
65
|
def sudo commands
|
177
66
|
"sudo -S -p 'sudo password: ' -s -- '#{commands}'"
|
178
67
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#require "open3"
|
2
|
+
#@stdout, @stderr, @status = Open3.capture3(stdin)
|
3
|
+
|
4
|
+
class LocalCommand
|
5
|
+
attr_accessor :simulate
|
6
|
+
|
7
|
+
attr_reader :password, :suppress_output, :capture_output, :simulate
|
8
|
+
|
9
|
+
def initialize params
|
10
|
+
@password = params[:password]
|
11
|
+
@suppress_output = params[:suppress_output]
|
12
|
+
@capture_output = params[:capture_output]
|
13
|
+
@simulate = params[:simulate]
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute commands, line_action
|
17
|
+
print_commands commands, $stdout
|
18
|
+
|
19
|
+
unless simulate
|
20
|
+
storage = capture_output ? OutputBuffer.new : nil
|
21
|
+
output = suppress_output ? nil : $stdout
|
22
|
+
|
23
|
+
commands = commands + inline_password(password) if password
|
24
|
+
|
25
|
+
IO.popen(commands) do |pipe|
|
26
|
+
pipe.each("\r") do |line|
|
27
|
+
output.print(line) if output
|
28
|
+
storage.save(line.chomp) if storage
|
29
|
+
|
30
|
+
line_action.call(line) if line_action
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
storage.buffer.join("\n") if storage
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def print_commands commands, output
|
41
|
+
if simulate
|
42
|
+
output.puts "Script:"
|
43
|
+
output.puts "-------"
|
44
|
+
|
45
|
+
lines = StringIO.new commands
|
46
|
+
|
47
|
+
lines.each_line do |line|
|
48
|
+
output.puts line
|
49
|
+
end
|
50
|
+
|
51
|
+
output.puts "-------"
|
52
|
+
else
|
53
|
+
output.puts "Local execution:"
|
54
|
+
output.puts "-------"
|
55
|
+
|
56
|
+
lines = StringIO.new commands
|
57
|
+
|
58
|
+
lines.each_line do |line|
|
59
|
+
output.puts line
|
60
|
+
end
|
61
|
+
|
62
|
+
output.puts "-------"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def inline_password password
|
67
|
+
password ? "<<EOF\n#{password}\nEOF" : ""
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
#require 'shellwords'
|
72
|
+
#
|
73
|
+
#def bash(command)
|
74
|
+
# escaped_command = Shellwords.escape(command)
|
75
|
+
# system "bash -c #{escaped_command}"
|
76
|
+
#end
|
77
|
+
|
78
|
+
|