script_executor 1.3.2 → 1.3.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|