rexec 1.1.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ module RExec
17
+ module VERSION #:nodoc:
18
+ MAJOR = 1
19
+ MINOR = 1
20
+ TINY = 10
21
+
22
+ STRING = [MAJOR, MINOR, TINY].join('.')
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ $connection.run do |object|
17
+ case(object[0])
18
+ when :bounce
19
+ $stderr.puts("Bouncing #{object[1].inspect}...")
20
+ $connection.send_object(object[1])
21
+ when :exception
22
+ $stderr.puts("Raising exception...")
23
+ raise Exception.new("I love exceptions!")
24
+ when :stop
25
+ $stderr.puts("Stopping connection manually...")
26
+ $connection.stop
27
+ when :stderr
28
+ $stderr.puts object[1]
29
+ $stderr.flush
30
+ end
31
+ end
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007, 2009 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+
20
+ require 'pathname'
21
+
22
+ require 'rexec'
23
+ require 'rexec/daemon'
24
+
25
+ require 'webrick'
26
+ require 'webrick/https'
27
+ require 'xmlrpc/server'
28
+
29
+ # Very simple XMLRPC daemon
30
+ class TestDaemon < RExec::Daemon::Base
31
+ @@var_directory = "/tmp/ruby-test/var"
32
+
33
+ def self.run
34
+ puts "Starting server..."
35
+
36
+ @@rpc_server = WEBrick::HTTPServer.new(
37
+ :Port => 11235,
38
+ :BindAddress => "0.0.0.0",
39
+ :SSLEnable => true,
40
+ :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
41
+ :SSLCertName => [["CN", WEBrick::Utils::getservername]])
42
+
43
+ @@listener = XMLRPC::WEBrickServlet.new
44
+
45
+ @@listener.add_handler("add") do |amount|
46
+ @@count ||= 0
47
+ @@count += amount
48
+ end
49
+
50
+ @@listener.add_handler("total") do
51
+ @@count
52
+ end
53
+
54
+ @@rpc_server.mount("/RPC2", @@listener)
55
+
56
+ $stdout.flush
57
+ $stderr.flush
58
+
59
+ @@rpc_server.start
60
+ end
61
+
62
+ def self.shutdown
63
+ puts "Shutting down server..."
64
+ @@rpc_server.shutdown
65
+ end
66
+ end
67
+
68
+ TestDaemon.daemonize
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007, 2009 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+ require 'pathname'
20
+ require 'xmlrpc/client'
21
+ require 'test/unit'
22
+
23
+ class DaemonTest < Test::Unit::TestCase
24
+ DAEMON = (Pathname.new(__FILE__).dirname + "./daemon.rb").realpath
25
+ def setup
26
+ system(DAEMON, "start")
27
+
28
+ # Daemon takes a moment to become fully operational
29
+ sleep(5)
30
+ end
31
+
32
+ def teardown
33
+ system(DAEMON, "stop")
34
+ end
35
+
36
+ def test_connection
37
+ rpc = XMLRPC::Client.new_from_uri("https://localhost:11235")
38
+ rpc.call("add", 10)
39
+
40
+ total = rpc.call("total")
41
+
42
+ assert_equal 10, total
43
+ end
44
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007, 2009 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+ require 'rexec'
20
+
21
+ CLIENT = <<EOF
22
+
23
+ $connection.run do |path|
24
+ listing = []
25
+
26
+ IO.popen("ls -la " + path.dump, "r+") do |ls|
27
+ listing = ls.readlines
28
+ end
29
+
30
+ $connection.send_object(listing)
31
+ end
32
+
33
+ EOF
34
+
35
+ command = ARGV[0] || "ruby"
36
+
37
+ puts "Starting server..."
38
+ RExec::start_server(CLIENT, command) do |conn, pid|
39
+ puts "Sending path..."
40
+ conn.send_object("/")
41
+
42
+ puts "Waiting for response..."
43
+ listing = conn.receive_object
44
+
45
+ puts "Received listing:"
46
+ listing.each do |entry|
47
+ puts "\t#{entry}"
48
+ end
49
+ end
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ # This script is used to test actual remote connections
19
+ # e.g. ./test_remote.rb "ssh haru.oriontransfer.org"
20
+
21
+ require 'rubygems'
22
+
23
+ require 'test/unit'
24
+ require 'fileutils'
25
+ require 'pathname'
26
+ require 'rexec'
27
+
28
+ if $0.match("remote_server_test.rb") and ARGV.size > 0
29
+ COMMAND = ARGV.join(" ")
30
+ else
31
+ COMMAND = "ruby"
32
+ end
33
+
34
+ BOUNCE = "Apples and Oranges"
35
+
36
+ class RemoteServerTest < Test::Unit::TestCase
37
+ def test_block_execution
38
+ code = Pathname.new(__FILE__).dirname + "./client.rb"
39
+
40
+ RExec::start_server(code.read, COMMAND, :passthrough => []) do |conn, pid|
41
+ conn.send_object([:bounce, BOUNCE])
42
+
43
+ assert_equal BOUNCE, conn.receive_object
44
+
45
+ conn.dump_errors
46
+
47
+ conn.stop
48
+ end
49
+ end
50
+
51
+ def test_result_execution
52
+ code = Pathname.new(__FILE__).dirname + "./client.rb"
53
+
54
+ conn, pid = RExec::start_server(code.read, COMMAND, :passthrough => [])
55
+
56
+ conn.send_object([:bounce, BOUNCE])
57
+ assert_equal BOUNCE, conn.receive_object
58
+
59
+ conn.dump_errors
60
+
61
+ conn.stop
62
+ end
63
+ end
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+
20
+ require 'test/unit'
21
+ require 'fileutils'
22
+ require 'pathname'
23
+ require 'rexec'
24
+
25
+ class ServerTest < Test::Unit::TestCase
26
+ def test_local_execution
27
+ code = Pathname.new(__FILE__).dirname + "./client.rb"
28
+ sobj = [1, 2, "three", 4]
29
+ stderr_text = "There was no error.. maybe?"
30
+ connection_started = false
31
+ object_received = false
32
+
33
+ RExec::start_server(code.read, "ruby", :passthrough => []) do |conn, pid|
34
+ connection_started = true
35
+ conn.send_object([:bounce, sobj])
36
+
37
+ assert_equal sobj, conn.receive_object
38
+
39
+ assert_raises(Exception) do
40
+ conn.send_object([:exception])
41
+ obj = conn.receive_object
42
+
43
+ puts "Received object which should have been exception: #{obj.inspect}"
44
+ end
45
+
46
+ conn.dump_errors
47
+ conn.send_object([:stderr, stderr_text])
48
+
49
+ puts "Attemping to read from #{conn.error.to_i}..."
50
+ assert_equal stderr_text, conn.error.readline.chomp
51
+
52
+ conn.stop
53
+ end
54
+
55
+ assert(connection_started, "Connection started")
56
+ end
57
+
58
+ def test_shell_execution
59
+ connection_started = false
60
+ code = Pathname.new(__FILE__).dirname + "client.rb"
61
+
62
+ test_obj = [1, 2, 3, 4, "five"]
63
+
64
+ RExec::start_server(code.read, "/bin/sh -c ruby", :passthrough => []) do |conn, pid|
65
+ connection_started = true
66
+ conn.send_object([:bounce, test_obj])
67
+
68
+ assert_equal test_obj, conn.receive_object
69
+
70
+ conn.stop
71
+ end
72
+
73
+ assert(connection_started, "Connection started")
74
+ end
75
+
76
+ def test_shell_execution_non_block
77
+ connection_started = false
78
+ code = Pathname.new(__FILE__).dirname + "client.rb"
79
+
80
+ test_obj = [1, 2, 3, 4, "five"]
81
+
82
+ conn, pid = RExec::start_server(code.read, "/bin/sh -c ruby", :passthrough => [])
83
+ conn.send_object([:bounce, test_obj])
84
+
85
+ assert_equal test_obj, conn.receive_object
86
+
87
+ conn.stop
88
+ end
89
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ input = $stdin.readline.chomp
19
+
20
+ $stdout.puts("STDOUT: " + input)
21
+ $stdout.flush
22
+
23
+ $stderr.puts("STDERR: " + input)
24
+ $stderr.flush
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2007 Samuel Williams. Released under the GNU GPLv3.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'rubygems'
19
+
20
+ require 'test/unit'
21
+ require 'fileutils'
22
+ require 'pathname'
23
+ require 'rexec'
24
+
25
+ require 'timeout'
26
+
27
+ class TaskTest < Test::Unit::TestCase
28
+ TASK_PATH = Pathname.new(__FILE__).dirname + "./task.rb"
29
+ TEXT = "The quick brown fox jumped over the lazy dog."
30
+ STDOUT_TEXT = "STDOUT: " + TEXT
31
+ STDERR_TEXT = "STDERR: " + TEXT
32
+
33
+ def test_script_execution
34
+ RExec::Task.open(TASK_PATH) do |task|
35
+ task.input.puts(TEXT)
36
+ task.input.close
37
+
38
+ assert_equal STDOUT_TEXT, task.output.readline.chomp
39
+ assert_equal STDERR_TEXT, task.error.readline.chomp
40
+ end
41
+ end
42
+
43
+ def test_ruby_execution
44
+ RExec::Task.open("ruby") do |task|
45
+ task.input.puts(TASK_PATH.read)
46
+ task.input.puts("\004")
47
+
48
+ task.input.puts(TEXT)
49
+ task.input.close
50
+
51
+ assert_equal STDOUT_TEXT, task.output.readline.chomp
52
+ assert_equal STDERR_TEXT, task.error.readline.chomp
53
+ end
54
+ end
55
+
56
+ def test_spawn_child
57
+ rd, wr = IO.pipe
58
+ pid = RExec::Task.spawn_child do
59
+ rd.close
60
+ wr.write(TEXT)
61
+ wr.close
62
+ exit(10)
63
+ end
64
+
65
+ wr.close
66
+
67
+ pid, status = Process.wait2(pid)
68
+
69
+ assert_equal rd.read, TEXT
70
+ assert_equal status, status
71
+ end
72
+
73
+ def test_spawn_daemon
74
+ rd, wr = IO.pipe
75
+
76
+ # We launch one daemon to start another. The first daemon will exit, but the second will keep on running.
77
+ ppid = RExec::Task.spawn_daemon do
78
+ RExec::Task.spawn_daemon do
79
+ rd.close
80
+ sleep 0.5
81
+ wr.puts(TEXT, Process.pid)
82
+ wr.close
83
+ sleep 0.5
84
+ end
85
+ end
86
+
87
+ wr.close
88
+
89
+ Timeout::timeout(5) do
90
+ until !RExec::Task.running?(ppid) do
91
+ sleep(0.1)
92
+ end
93
+
94
+ text = rd.readline.chomp
95
+ pid = rd.readline.chomp.to_i
96
+
97
+ assert_raises(EOFError) do
98
+ rd.readline
99
+ end
100
+
101
+ assert_equal text, TEXT
102
+ assert RExec::Task.running?(pid)
103
+
104
+ until !RExec::Task.running?(pid) do
105
+ sleep(0.1)
106
+ end
107
+ end
108
+ end
109
+
110
+ def test_task
111
+ test_results = Proc.new do |input, output, error|
112
+ input.puts TEXT
113
+ input.flush
114
+
115
+ assert_equal output.readline.chomp, STDOUT_TEXT
116
+ assert_equal error.readline.chomp, STDERR_TEXT
117
+ end
118
+
119
+ RExec::Task.open(TASK_PATH) do |task|
120
+ test_results.call(task.input, task.output, task.error)
121
+ end
122
+
123
+ rd, wr = IO.pipe
124
+
125
+ RExec::Task.open(TASK_PATH, :in => rd) do |task|
126
+ test_results.call(wr, task.output, task.error)
127
+ end
128
+
129
+ assert rd.closed?
130
+
131
+ assert_raises(Errno::EPIPE) do
132
+ wr.puts "The pipe is closed on the other side.."
133
+ end
134
+
135
+ in_rd, in_wr = IO.pipe
136
+ out_rd, out_wr = IO.pipe
137
+ err_rd, err_wr = IO.pipe
138
+
139
+ spawn_child_daemon = Proc.new do
140
+ task = RExec::Task.open(TASK_PATH, :in => in_rd, :out => out_wr, :err => err_wr, :daemonize => true)
141
+ end
142
+
143
+ task = RExec::Task.open(spawn_child_daemon, :daemonize => true)
144
+
145
+ until !task.running? do
146
+ sleep 0.1
147
+ end
148
+
149
+ test_results.call(in_wr, out_rd, err_rd)
150
+
151
+ assert !task.running?
152
+ end
153
+
154
+ def test_task_passthrough
155
+ script = "echo " + "Hello World!".dump + " | #{TASK_PATH.realpath.to_s.dump}"
156
+
157
+ RExec::Task.open(script, :passthrough => :all) do
158
+
159
+ end
160
+
161
+ [$stdin, $stdout, $stderr].each do |io|
162
+ assert !io.closed?
163
+ end
164
+ end
165
+ end