script_executor 1.0.0
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/.gitignore +18 -0
- data/.rbenv-gemsets +1 -0
- data/.rbenv-version +1 -0
- data/.rvmrc +5 -0
- data/CHANGES +5 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +31 -0
- data/LICENSE +22 -0
- data/README.md +47 -0
- data/Rakefile +32 -0
- data/lib/script_executor/script_executor.rb +163 -0
- data/lib/script_executor/version.rb +3 -0
- data/lib/script_executor.rb +3 -0
- data/script_executor.gemspec +23 -0
- data/script_executor.gemspec.erb +20 -0
- data/spec/script_executor_spec.rb +57 -0
- data/spec/spec_helper.rb +1 -0
- metadata +111 -0
data/.gitignore
ADDED
data/.rbenv-gemsets
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
script_executor
|
data/.rbenv-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p327
|
data/.rvmrc
ADDED
data/CHANGES
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.3)
|
5
|
+
file_utils (1.0.5)
|
6
|
+
gemcutter (0.7.1)
|
7
|
+
gemspec_deps_gen (1.0.3)
|
8
|
+
file_utils
|
9
|
+
highline (1.6.15)
|
10
|
+
metaclass (0.0.1)
|
11
|
+
mocha (0.13.0)
|
12
|
+
metaclass (~> 0.0.1)
|
13
|
+
rspec (2.11.0)
|
14
|
+
rspec-core (~> 2.11.0)
|
15
|
+
rspec-expectations (~> 2.11.0)
|
16
|
+
rspec-mocks (~> 2.11.0)
|
17
|
+
rspec-core (2.11.1)
|
18
|
+
rspec-expectations (2.11.3)
|
19
|
+
diff-lcs (~> 1.1.3)
|
20
|
+
rspec-mocks (2.11.3)
|
21
|
+
|
22
|
+
PLATFORMS
|
23
|
+
java
|
24
|
+
ruby
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
gemcutter
|
28
|
+
gemspec_deps_gen
|
29
|
+
highline
|
30
|
+
mocha
|
31
|
+
rspec
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Alexander Shvets
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# ScriptExecutor - This library helps to execute code, locally or remote over ssh
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Add this line to your application's Gemfile:
|
6
|
+
|
7
|
+
gem 'script_executor'
|
8
|
+
|
9
|
+
And then execute:
|
10
|
+
|
11
|
+
$ bundle
|
12
|
+
|
13
|
+
Or install it yourself as:
|
14
|
+
|
15
|
+
$ gem install script_executor
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
executor = ScriptExecutor.new
|
20
|
+
|
21
|
+
executor.execute "ls" # execute locally
|
22
|
+
|
23
|
+
executor.execute :remote => true, :script => "ls -al", :domain => "localhost", :user => "user" # execute remote
|
24
|
+
|
25
|
+
executor.remote_execute :script => "ls -al", :domain => "localhost", :user => "user" # execute remote
|
26
|
+
|
27
|
+
executor.remote_execute :sudo => true, :script => "/etc/init.d/tomcat stop", :domain => "somehost", :user => "user" # execute remote
|
28
|
+
|
29
|
+
server_info = {
|
30
|
+
:domain => "some.host",
|
31
|
+
:user => "some.user",
|
32
|
+
}
|
33
|
+
|
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
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
1. Fork it
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
45
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
47
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path("lib", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
require "script_executor/version"
|
7
|
+
require "gemspec_deps_gen/gemspec_deps_gen"
|
8
|
+
|
9
|
+
def version
|
10
|
+
ScriptExecutor::VERSION
|
11
|
+
end
|
12
|
+
|
13
|
+
def project_name
|
14
|
+
File.basename(Dir.pwd)
|
15
|
+
end
|
16
|
+
|
17
|
+
task :build do
|
18
|
+
generator = GemspecDepsGen.new
|
19
|
+
|
20
|
+
generator.generate_dependencies "#{project_name}.gemspec.erb", "#{project_name}.gemspec"
|
21
|
+
|
22
|
+
system "gem build #{project_name}.gemspec"
|
23
|
+
end
|
24
|
+
|
25
|
+
task :release => :build do
|
26
|
+
system "gem push #{project_name}-#{version}.gem"
|
27
|
+
end
|
28
|
+
|
29
|
+
RSpec::Core::RakeTask.new do |task|
|
30
|
+
task.pattern = 'spec/**/*_spec.rb'
|
31
|
+
task.verbose = false
|
32
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
require 'net/ssh'
|
3
|
+
require "highline/import"
|
4
|
+
|
5
|
+
class ScriptExecutor
|
6
|
+
|
7
|
+
def execute params={}, &code
|
8
|
+
if params.class != Hash
|
9
|
+
simple_commands = commands_from_object(params)
|
10
|
+
params = {}
|
11
|
+
params[:script] = simple_commands
|
12
|
+
end
|
13
|
+
|
14
|
+
remote = params.delete(:remote)
|
15
|
+
|
16
|
+
remote ? remote_execute(params, &code) : local_execute(params, &code)
|
17
|
+
end
|
18
|
+
|
19
|
+
def local_execute params={}, &code
|
20
|
+
simulate = params.delete(:simulate)
|
21
|
+
sudo = params.delete(:sudo)
|
22
|
+
|
23
|
+
commands = locate_commands params[:script], &code
|
24
|
+
|
25
|
+
if commands.nil?
|
26
|
+
puts "No commands were provided!"
|
27
|
+
return
|
28
|
+
end
|
29
|
+
|
30
|
+
commands = sudo(commands) if sudo
|
31
|
+
|
32
|
+
if simulate
|
33
|
+
puts "Script:"
|
34
|
+
puts "-------"
|
35
|
+
print_commands commands
|
36
|
+
puts "-------"
|
37
|
+
else
|
38
|
+
puts "Local execution:"
|
39
|
+
puts "-------"
|
40
|
+
print_commands(commands)
|
41
|
+
puts "-------"
|
42
|
+
execute_command commands, params[:capture_output]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def remote_execute params={}, &code
|
47
|
+
simulate = params.delete(:simulate)
|
48
|
+
sudo = params.delete(:sudo)
|
49
|
+
|
50
|
+
commands = locate_commands params[:script], &code
|
51
|
+
|
52
|
+
if commands.nil?
|
53
|
+
puts "No commands were provided!"
|
54
|
+
return
|
55
|
+
end
|
56
|
+
|
57
|
+
commands = sudo(commands) if sudo
|
58
|
+
|
59
|
+
ssh_command = ssh_command(params[:domain], params[:user], params[:identity_file])
|
60
|
+
|
61
|
+
if simulate
|
62
|
+
puts "Remote script: '#{ssh_command}'"
|
63
|
+
puts "-------"
|
64
|
+
print_commands commands
|
65
|
+
puts "-------"
|
66
|
+
else
|
67
|
+
puts "Remote execution on: '#{ssh_command}'"
|
68
|
+
puts "-------"
|
69
|
+
print_commands commands
|
70
|
+
puts "-------"
|
71
|
+
|
72
|
+
execute_ssh(params[:domain], params[:user], commands)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def print_commands commands
|
79
|
+
lines = StringIO.new commands
|
80
|
+
|
81
|
+
lines.each_line do |line|
|
82
|
+
puts line
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def execute_command commands, capture_output=false
|
87
|
+
if capture_output
|
88
|
+
buffer = []
|
89
|
+
|
90
|
+
IO.popen(commands).each_line do |line|
|
91
|
+
buffer << line.chomp
|
92
|
+
end
|
93
|
+
|
94
|
+
buffer.join("\n")
|
95
|
+
else
|
96
|
+
IO.popen(commands).each_line do |line|
|
97
|
+
print line
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def execute_ssh domain, user, commands
|
103
|
+
password = ask("Enter password for #{user}: ") { |q| q.echo = '*' }
|
104
|
+
|
105
|
+
Net::SSH.start(domain, user, :password => password) do |session|
|
106
|
+
session.exec "#{commands}" do |channel, _, data|
|
107
|
+
if data =~ /^\[sudo\] password for user:/ || data =~ /sudo password:/
|
108
|
+
#puts "Password request"
|
109
|
+
channel.request_pty # <- problem must be here.
|
110
|
+
channel.send_data password + "\n"
|
111
|
+
else
|
112
|
+
print data
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# run the aggregated event loop
|
117
|
+
session.loop
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def locate_commands script, &code
|
122
|
+
if block_given?
|
123
|
+
commands_from_block &code
|
124
|
+
elsif script
|
125
|
+
commands_from_object script
|
126
|
+
else
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def commands_from_block &code
|
132
|
+
s1 = code.call.split(/\n/)
|
133
|
+
s2 = s1.reject {|el| el.strip.size == 0 || el.empty?}
|
134
|
+
s3 = s2.collect {|el| el.strip}
|
135
|
+
|
136
|
+
s3.join("\n")
|
137
|
+
end
|
138
|
+
|
139
|
+
def commands_from_object object
|
140
|
+
if object.class == String
|
141
|
+
object
|
142
|
+
elsif object.class == Array
|
143
|
+
object.join("\n")
|
144
|
+
else
|
145
|
+
object
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def ssh_command domain, user, identity_file
|
150
|
+
cmd = user.nil? ? domain : "#{user}@#{domain}"
|
151
|
+
|
152
|
+
cmd << " -i #{identity_file}" if identity_file
|
153
|
+
|
154
|
+
#cmd << " -t -t"
|
155
|
+
|
156
|
+
"ssh #{cmd}"
|
157
|
+
end
|
158
|
+
|
159
|
+
def sudo commands
|
160
|
+
"sudo -S -p 'sudo password: ' #{commands}"
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/lib/script_executor/version')
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "script_executor"
|
7
|
+
spec.summary = %q{This library helps to execute code, locally or remote over ssh}
|
8
|
+
spec.description = %q{This library helps to execute code, locally or remote over ssh}
|
9
|
+
spec.email = "alexander.shvets@gmail.com"
|
10
|
+
spec.authors = ["Alexander Shvets"]
|
11
|
+
spec.homepage = "http://github.com/shvets/script_executor"
|
12
|
+
|
13
|
+
spec.files = `git ls-files`.split($\)
|
14
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
15
|
+
spec.require_paths = ["lib"]
|
16
|
+
spec.version = ScriptExecutor::VERSION
|
17
|
+
|
18
|
+
spec.add_runtime_dependency "highline", [">= 0"]
|
19
|
+
spec.add_development_dependency "gemspec_deps_gen", [">= 0"]
|
20
|
+
spec.add_development_dependency "gemcutter", [">= 0"]
|
21
|
+
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/lib/script_executor/version')
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "script_executor"
|
7
|
+
spec.summary = %q{This library helps to execute code, locally or remote over ssh}
|
8
|
+
spec.description = %q{This library helps to execute code, locally or remote over ssh}
|
9
|
+
spec.email = "alexander.shvets@gmail.com"
|
10
|
+
spec.authors = ["Alexander Shvets"]
|
11
|
+
spec.homepage = "http://github.com/shvets/script_executor"
|
12
|
+
|
13
|
+
spec.files = `git ls-files`.split($\)
|
14
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
15
|
+
spec.require_paths = ["lib"]
|
16
|
+
spec.version = ScriptExecutor::VERSION
|
17
|
+
|
18
|
+
<%= include_dependencies %>
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'script_executor'
|
4
|
+
|
5
|
+
describe ScriptExecutor do
|
6
|
+
server_info = {
|
7
|
+
:simulate => false,
|
8
|
+
:domain => "localhost",
|
9
|
+
:user => "user",
|
10
|
+
:remote => truez
|
11
|
+
}
|
12
|
+
|
13
|
+
subject { ScriptExecutor.new }
|
14
|
+
|
15
|
+
it "should execute commands from :script parameter" do
|
16
|
+
subject.execute server_info.merge(:script => "ls -al")
|
17
|
+
|
18
|
+
#result.should include "file_utils/version.rb"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should execute commands from the block of code" do
|
22
|
+
subject.execute server_info do
|
23
|
+
%Q(
|
24
|
+
ls -al
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should execute commands locally from :script parameter" do
|
30
|
+
subject.execute :script => "ls -al", :simulate => false
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should execute commands locally from the block of code" do
|
34
|
+
subject.execute do
|
35
|
+
%Q(
|
36
|
+
ls -al
|
37
|
+
ls
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should execute sudo command locally" do
|
43
|
+
subject.execute :sudo => true, :simulate => false, :remote => false do
|
44
|
+
%Q(
|
45
|
+
~/apache-tomcat-7.0.27/bin/shutdown.sh
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should execute sudo command on remote side" do
|
51
|
+
subject.execute server_info.merge(:sudo => true, :simulate => false, :remote => true) do
|
52
|
+
%Q(
|
53
|
+
/etc/init.d/tomcat5 restart
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
$: << File.expand_path('../lib', File.dirname(__FILE__))
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: script_executor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alexander Shvets
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: highline
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: gemspec_deps_gen
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: gemcutter
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: This library helps to execute code, locally or remote over ssh
|
63
|
+
email: alexander.shvets@gmail.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- .gitignore
|
69
|
+
- .rbenv-gemsets
|
70
|
+
- .rbenv-version
|
71
|
+
- .rvmrc
|
72
|
+
- CHANGES
|
73
|
+
- Gemfile
|
74
|
+
- Gemfile.lock
|
75
|
+
- LICENSE
|
76
|
+
- README.md
|
77
|
+
- Rakefile
|
78
|
+
- lib/script_executor.rb
|
79
|
+
- lib/script_executor/script_executor.rb
|
80
|
+
- lib/script_executor/version.rb
|
81
|
+
- script_executor.gemspec
|
82
|
+
- script_executor.gemspec.erb
|
83
|
+
- spec/script_executor_spec.rb
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
homepage: http://github.com/shvets/script_executor
|
86
|
+
licenses: []
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.8.24
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: This library helps to execute code, locally or remote over ssh
|
109
|
+
test_files:
|
110
|
+
- spec/script_executor_spec.rb
|
111
|
+
- spec/spec_helper.rb
|