unix_commander 0.0.2 → 0.1.1
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/README.md +25 -0
- data/lib/unix_commander/version.rb +1 -1
- data/lib/unix_commander.rb +138 -16
- data/spec/command_spec.rb +83 -0
- data/spec/runner_spec.rb +73 -0
- metadata +7 -4
- data/spec/single_commands_spec.rb +0 -46
data/README.md
CHANGED
@@ -34,6 +34,17 @@ comm = UnixCommander::Command.new
|
|
34
34
|
comm.cat("file").tail("-n10").grep("'something'").run
|
35
35
|
```
|
36
36
|
|
37
|
+
<<<<<<< HEAD
|
38
|
+
=======
|
39
|
+
You can use redirection too
|
40
|
+
```
|
41
|
+
require 'unix_commander'
|
42
|
+
|
43
|
+
comm = UnixCommander::Command.new
|
44
|
+
comm.cat("file").tail("-n10").grep("'something'").out_to("my_file").err_to("/dev/null")
|
45
|
+
```
|
46
|
+
|
47
|
+
>>>>>>> development
|
37
48
|
You don't have to run the commands right away, we can create a command and run it whe we see fit:
|
38
49
|
|
39
50
|
```
|
@@ -56,7 +67,21 @@ require 'unix_commander'
|
|
56
67
|
comm = UnixCommander::Command.new
|
57
68
|
comm.cat("file").tail("-n10").grep("'something'").run_ssh("Batou99","secret","remote_server")
|
58
69
|
```
|
70
|
+
<<<<<<< HEAD
|
71
|
+
=======
|
59
72
|
|
73
|
+
After running a command you can access it output using **out**, **err** or **both**
|
74
|
+
```
|
75
|
+
require 'unix_commander'
|
76
|
+
>>>>>>> development
|
77
|
+
|
78
|
+
comm = UnixCommander::Command.new
|
79
|
+
comm.cat("file").tail("-n10").grep("'something'").run_ssh("Batou99","secret","remote_server").out
|
80
|
+
# Or
|
81
|
+
comm.cat("file").tail("-n10").grep("'something'").run_ssh("Batou99","secret","remote_server").err
|
82
|
+
# Or
|
83
|
+
comm.cat("file").tail("-n10").grep("'something'").run_ssh("Batou99","secret","remote_server").both
|
84
|
+
```
|
60
85
|
## Contributing
|
61
86
|
|
62
87
|
1. Fork it
|
data/lib/unix_commander.rb
CHANGED
@@ -5,32 +5,69 @@ require 'net/ssh'
|
|
5
5
|
|
6
6
|
module UnixCommander
|
7
7
|
|
8
|
-
class
|
8
|
+
# This class encapsulates the output of a command. It also has the logic to run a command locally or remotely
|
9
|
+
class Runner
|
9
10
|
|
10
|
-
|
11
|
+
# @return [Command]
|
12
|
+
attr :command
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
|
15
|
+
# Creates a new Runner
|
16
|
+
# @param _command The command to be run by the runner
|
17
|
+
def initialize(_command)
|
18
|
+
@command = _command
|
14
19
|
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
21
|
+
# Return a string with the output of the command
|
22
|
+
# If the command has not been run yet it returns an empty string
|
23
|
+
# @return [String] *stdout* and *stderr* of the command (*stdout* \\n *stderr*)
|
24
|
+
def to_s
|
25
|
+
both.join("\n")
|
22
26
|
end
|
23
27
|
|
24
|
-
|
25
|
-
|
28
|
+
# Returns the output (stdout) of the command
|
29
|
+
# If the command has not been run yet it returns an empty string
|
30
|
+
# @return [String] *stdout* of the command
|
31
|
+
def out
|
32
|
+
return "" if @out==nil
|
33
|
+
return @out if @out.class==String
|
26
34
|
@out.read
|
27
35
|
end
|
28
36
|
|
37
|
+
# Returns the output (stderr) of the command
|
38
|
+
# If the command has not been run yet it returns an empty string
|
39
|
+
# @return [String] *stderr* of the command
|
40
|
+
def err
|
41
|
+
return "" if @err==nil
|
42
|
+
return @err if @err.class==String
|
43
|
+
@err.read
|
44
|
+
end
|
45
|
+
|
46
|
+
# Return a string with the output of the command
|
47
|
+
# If the command has not been run yet it returns ["",""]
|
48
|
+
# @return [Array] *stdout* and *stderr* of the command
|
49
|
+
def both
|
50
|
+
[out, err]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Runs the stored command locally
|
54
|
+
# @return [Runner] Returns itself
|
55
|
+
def run
|
56
|
+
@in, @out, @err = Open3.popen3("#{@command.cmd}")
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
# Runs the stored command remotely
|
61
|
+
# @param _username The ssh username to access the remote server
|
62
|
+
# @param _password The ssh password to access the remote server
|
63
|
+
# @param _address The ssh server address to access the remote server. It defaults to localhost.
|
64
|
+
# @return [Runner] Returns itself
|
29
65
|
def run_ssh(_username, _password = "", _address = "127.0.0.1")
|
30
66
|
stdout_data = ""
|
67
|
+
stderr_data = ""
|
31
68
|
Net::SSH.start(_address,_username,:password => _password) do |ssh|
|
32
69
|
channel = ssh.open_channel do |ch|
|
33
|
-
ch.exec(@cmd) do |ch,success|
|
70
|
+
ch.exec(@command.cmd) do |ch,success|
|
34
71
|
# "on_data" is called when the process writes something to stdout
|
35
72
|
ch.on_data do |c, data|
|
36
73
|
stdout_data += data
|
@@ -38,13 +75,98 @@ module UnixCommander
|
|
38
75
|
|
39
76
|
# "on_extended_data" is called when the process writes something to stderr
|
40
77
|
ch.on_extended_data do |c, type, data|
|
41
|
-
|
78
|
+
stderr_data += data
|
42
79
|
end
|
43
80
|
end
|
44
81
|
end
|
45
82
|
end
|
46
|
-
|
47
|
-
|
83
|
+
@out = stdout_data
|
84
|
+
@err = stderr_data
|
85
|
+
self
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# This class encapsulates a command that will run in a unix machine locally or remotely
|
90
|
+
class Command
|
91
|
+
|
92
|
+
# @return [String]
|
93
|
+
attr :cmd
|
94
|
+
|
95
|
+
# Creates a new command
|
96
|
+
# @param [String] create a command with some unix code inside (defaults to "")
|
97
|
+
def initialize(_cmd = "")
|
98
|
+
@cmd = _cmd
|
99
|
+
end
|
100
|
+
# Shows the string representation of the command being run in unix
|
101
|
+
# @return [String]
|
102
|
+
def to_s
|
103
|
+
cmd
|
104
|
+
end
|
105
|
+
|
106
|
+
# This is the main method of the library. Every unknown method you call on a Command object
|
107
|
+
# is interpreted as a unix command and its args are used as the args of the unix command.
|
108
|
+
# When the command already has some unix command inside, it pipes them together (|)
|
109
|
+
# @param [String] m name of the unix command you want to execute
|
110
|
+
# @param [Array] *args args for the aforementioned command
|
111
|
+
# @return [Command] new command with internal unix commands piped together
|
112
|
+
def method_missing(m, *args, &block)
|
113
|
+
if cmd == ""
|
114
|
+
Command.new("#{m} #{args.join(' ')}".strip)
|
115
|
+
else
|
116
|
+
Command.new("#{cmd} | #{m} #{args.join(' ')}".strip)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Redirects *stdout* to someplace (Using >). By default it uses destructive redirection.
|
121
|
+
# @param [String] place to redirect the output (e.g. /dev/null)
|
122
|
+
# @param [true,false] append if true uses append redirection (>>) it defaults to false.
|
123
|
+
# @return [Command] New command with *stdout* redirected to _str
|
124
|
+
def out_to(_str,_append=false)
|
125
|
+
if cmd == ""
|
126
|
+
raise ArgumentError, "Cannot redirect with an empty command"
|
127
|
+
else
|
128
|
+
_append ? Command.new("#{cmd} >> #{_str}") : Command.new("#{cmd} > #{_str}")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Redirects *stderr* to someplace (Using >). By default it uses destructive redirection.
|
133
|
+
# @param [String] place to redirect the output (e.g. /dev/null)
|
134
|
+
# @param [true,false] append if true uses append redirection (>>) it defaults to false.
|
135
|
+
# @return [Command] New command with *stderr* redirected to _str
|
136
|
+
def err_to(_str,_append=false)
|
137
|
+
if cmd == ""
|
138
|
+
raise ArgumentError, "Cannot redirect with an empty command"
|
139
|
+
else
|
140
|
+
_append ? Command.new("#{cmd} 2>> #{_str}") : Command.new("#{cmd} 2> #{_str}")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Redirects *stdout* and *stderr* to someplace (Using >). By default it uses destructive redirection.
|
145
|
+
# @param [String] place to redirect the output (e.g. /dev/null)
|
146
|
+
# @param [true,false] append if true uses append redirection (>>) it defaults to false.
|
147
|
+
# @return [Command] New command with *stdout and stderr* redirected to _str
|
148
|
+
def both_to(_str,_append=false)
|
149
|
+
if cmd == ""
|
150
|
+
raise ArgumentError, "Cannot redirect with an empty command"
|
151
|
+
else
|
152
|
+
_append ? Command.new("#{cmd} >> #{_str} 2>&1") : Command.new("#{cmd} > #{_str} 2>&1")
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Run the Command locally. The output is encapsulated in a Runner object
|
157
|
+
# @return [Runner] runner object with the output inside
|
158
|
+
def run
|
159
|
+
Runner.new(self).run
|
160
|
+
end
|
161
|
+
|
162
|
+
# Run the Command remotely via ssh. The output is encapsulated in a Runner object
|
163
|
+
# @param _username The ssh username to access the remote server
|
164
|
+
# @param _password The ssh password to access the remote server
|
165
|
+
# @param _address The ssh server address to access the remote server. It defaults to localhost.
|
166
|
+
# @return [Runner] runner object with the output inside
|
167
|
+
def run_ssh(_username, _password = "", _address = "127.0.0.1")
|
168
|
+
Runner.new(self).run_ssh(_username,_password,_address)
|
48
169
|
end
|
49
170
|
end
|
171
|
+
|
50
172
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require './lib/unix_commander'
|
3
|
+
|
4
|
+
describe "Commands without chaining" do
|
5
|
+
before do
|
6
|
+
@command = UnixCommander::Command.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should accept commands with no args" do
|
10
|
+
version = %x[uname]
|
11
|
+
@command.uname.to_s.should == "uname"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should accept commands with one arg" do
|
15
|
+
@command.uname("-a").to_s.should == "uname -a"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "Commands with chaining" do
|
21
|
+
before do
|
22
|
+
@command = UnixCommander::Command.new
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can chain 2 commands" do
|
26
|
+
@command.uname("-a").cut("-d'#' -f1").to_s.should == "uname -a | cut -d'#' -f1"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can chain 3 commands" do
|
30
|
+
@command.cat("/proc/cpuinfo").awk("'{ print $1 }'").head("-n1").to_s.should == "cat /proc/cpuinfo | awk '{ print $1 }' | head -n1"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "Running" do
|
35
|
+
before do
|
36
|
+
@command = UnixCommander::Command.new.uname
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should call a runner" do
|
40
|
+
UnixCommander::Runner.any_instance.should_receive(:run).and_return(%x[uname -a])
|
41
|
+
@command.run.should == %x[uname -a]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should call a runner over ssh" do
|
45
|
+
UnixCommander::Runner.any_instance.should_receive(:run_ssh).with('dev','devpass','localhost').and_return(%x[uname -a])
|
46
|
+
@command.run_ssh('dev','devpass','localhost').should == %x[uname -a]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "Redirection" do
|
51
|
+
before do
|
52
|
+
@command = UnixCommander::Command.new.uname("-a").cut("-d' ' -f1")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should translate to_s correctly" do
|
56
|
+
@command.to_s.should == "uname -a | cut -d' ' -f1"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should redirect stdout" do
|
60
|
+
@command.out_to('/dev/null').to_s.should == "uname -a | cut -d' ' -f1 > /dev/null"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should redirect stderr" do
|
64
|
+
@command.err_to('/dev/null').to_s.should == "uname -a | cut -d' ' -f1 2> /dev/null"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should redirect both" do
|
68
|
+
@command.both_to('/dev/null').to_s.should == "uname -a | cut -d' ' -f1 > /dev/null 2>&1"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should append stdout" do
|
72
|
+
@command.out_to('/dev/null',true).to_s.should == "uname -a | cut -d' ' -f1 >> /dev/null"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should append stderr" do
|
76
|
+
@command.err_to('/dev/null',true).to_s.should == "uname -a | cut -d' ' -f1 2>> /dev/null"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should append both" do
|
80
|
+
@command.both_to('/dev/null',true).to_s.should == "uname -a | cut -d' ' -f1 >> /dev/null 2>&1"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
data/spec/runner_spec.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require './lib/unix_commander'
|
3
|
+
|
4
|
+
describe "Runner local" do
|
5
|
+
before do
|
6
|
+
@command = UnixCommander::Command.new("uname")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "can access out after run command" do
|
10
|
+
UnixCommander::Runner.new(@command).run.out.should == %x[uname]
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can access err after run command with no errors" do
|
14
|
+
UnixCommander::Runner.new(@command).run.err.should == ""
|
15
|
+
end
|
16
|
+
|
17
|
+
it "can access err after run command with errors" do
|
18
|
+
@command = UnixCommander::Command.new("cat /etc/shadow")
|
19
|
+
UnixCommander::Runner.new(@command).run.err.should_not == ""
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can access out and err after run command with errors" do
|
23
|
+
@command = UnixCommander::Command.new("grep abc /etc/*")
|
24
|
+
UnixCommander::Runner.new(@command).run.err.should_not == ""
|
25
|
+
UnixCommander::Runner.new(@command).run.out.should == %x[grep abc /etc/* 2> /dev/null]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have empty data before run" do
|
29
|
+
UnixCommander::Runner.new(@command).out == ""
|
30
|
+
UnixCommander::Runner.new(@command).err == ""
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can access out and err with an array" do
|
34
|
+
@command = UnixCommander::Command.new("grep abc /etc/*")
|
35
|
+
out_err = UnixCommander::Runner.new(@command).run.both
|
36
|
+
out_err[0].should_not == ""
|
37
|
+
out_err[1].should_not == ""
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "Runner ssh" do
|
43
|
+
before do
|
44
|
+
@command = UnixCommander::Command.new("uname")
|
45
|
+
end
|
46
|
+
|
47
|
+
it "can access out after run command" do
|
48
|
+
UnixCommander::Runner.new(@command).run_ssh('dev','dev').out.should == %x[uname]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can access err after run command with no errors" do
|
52
|
+
UnixCommander::Runner.new(@command).run_ssh('dev','dev').err.should == ""
|
53
|
+
end
|
54
|
+
|
55
|
+
it "can access err after run command with errors" do
|
56
|
+
@command = UnixCommander::Command.new("cat /etc/shadow")
|
57
|
+
UnixCommander::Runner.new(@command).run_ssh('dev','dev').err.should_not == ""
|
58
|
+
end
|
59
|
+
|
60
|
+
it "can access out and err after run command with errors" do
|
61
|
+
@command = UnixCommander::Command.new("grep abc /etc/*")
|
62
|
+
UnixCommander::Runner.new(@command).run_ssh('dev','dev').err.should_not == ""
|
63
|
+
UnixCommander::Runner.new(@command).run_ssh('dev','dev').out.should == %x[grep abc /etc/* 2> /dev/null]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "can access out and err with an array" do
|
67
|
+
@command = UnixCommander::Command.new("grep abc /etc/*")
|
68
|
+
out_err = UnixCommander::Runner.new(@command).run_ssh('dev','dev').both
|
69
|
+
out_err[0].should_not == ""
|
70
|
+
out_err[1].should_not == ""
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unix_commander
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-ssh
|
@@ -139,8 +139,9 @@ files:
|
|
139
139
|
- Rakefile
|
140
140
|
- lib/unix_commander.rb
|
141
141
|
- lib/unix_commander/version.rb
|
142
|
+
- spec/command_spec.rb
|
142
143
|
- spec/fixtures/ps_list.txt
|
143
|
-
- spec/
|
144
|
+
- spec/runner_spec.rb
|
144
145
|
- unix_commander.gemspec
|
145
146
|
homepage: https://github.com/Batou99/unix_commander
|
146
147
|
licenses: []
|
@@ -167,5 +168,7 @@ signing_key:
|
|
167
168
|
specification_version: 3
|
168
169
|
summary: A gem to run unix commands on a more ruby-esque way
|
169
170
|
test_files:
|
171
|
+
- spec/command_spec.rb
|
170
172
|
- spec/fixtures/ps_list.txt
|
171
|
-
- spec/
|
173
|
+
- spec/runner_spec.rb
|
174
|
+
has_rdoc:
|
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'pry'
|
2
|
-
require './lib/unix_commander'
|
3
|
-
|
4
|
-
describe "Commands without chaining" do
|
5
|
-
before do
|
6
|
-
@command = UnixCommander::Command.new
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should run commands with no args" do
|
10
|
-
version = %x[uname]
|
11
|
-
@command.uname.run.should == version
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should run commands with one arg" do
|
15
|
-
long_version = %x[uname -a]
|
16
|
-
@command.uname("-a").run.should == long_version
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "Commands with chaining" do
|
22
|
-
before do
|
23
|
-
@command = UnixCommander::Command.new
|
24
|
-
end
|
25
|
-
|
26
|
-
it "can chain 2 commands" do
|
27
|
-
uname_cut = %x[uname -a | cut -d'#' -f1]
|
28
|
-
@command.uname("-a").cut("-d'#' -f1").run.should == uname_cut
|
29
|
-
end
|
30
|
-
|
31
|
-
it "can chain 3 commands" do
|
32
|
-
cpuinfo = %x[ cat /proc/cpuinfo | awk '{ print $1 }' | head -n1]
|
33
|
-
@command.cat("/proc/cpuinfo").awk("'{ print $1 }'").head("-n1").run.should == cpuinfo
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe "Run via ssh" do
|
38
|
-
before do
|
39
|
-
@command = UnixCommander::Command.new
|
40
|
-
end
|
41
|
-
|
42
|
-
it "can chain 2 commands" do
|
43
|
-
uname_cut = %x[uname -a | cut -d'#' -f1]
|
44
|
-
@command.uname("-a").cut("-d'#' -f1").run_ssh('dev','dev').should == uname_cut
|
45
|
-
end
|
46
|
-
end
|