net-ssh 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/manual-html/chapter-1.html +388 -0
- data/doc/manual-html/chapter-2.html +544 -0
- data/doc/manual-html/chapter-3.html +470 -0
- data/doc/manual-html/chapter-4.html +413 -0
- data/doc/manual-html/chapter-5.html +525 -0
- data/doc/manual-html/chapter-6.html +456 -0
- data/doc/manual-html/chapter-7.html +343 -0
- data/doc/manual-html/index.html +237 -0
- data/doc/manual-html/stylesheets/manual.css +270 -0
- data/doc/manual-html/stylesheets/ruby.css +17 -0
- data/doc/manual/manual.rb +2 -2
- data/doc/manual/manual.yml +41 -44
- data/doc/manual/parts/{intro_what_is.txt → 0000.txt} +0 -0
- data/doc/manual/parts/{intro_what_is_not.txt → 0001.txt} +0 -0
- data/doc/manual/parts/{intro_getting.txt → 0002.txt} +7 -6
- data/doc/manual/parts/{intro_license.txt → 0003.txt} +0 -0
- data/doc/manual/parts/{intro_support.txt → 0004.txt} +0 -0
- data/doc/manual/parts/{intro_author.txt → 0005.txt} +1 -1
- data/doc/manual/parts/{session_start.txt → 0006.txt} +11 -11
- data/doc/manual/parts/{session_key.txt → 0007.txt} +6 -6
- data/doc/manual/parts/{session_options.txt → 0008.txt} +2 -3
- data/doc/manual/parts/0009.txt +14 -0
- data/doc/manual/parts/{channels_what_are.txt → 0010.txt} +0 -0
- data/doc/manual/parts/{channels_loop.txt → 0011.txt} +2 -2
- data/doc/manual/parts/{channels_types.txt → 0012.txt} +0 -0
- data/doc/manual/parts/{channels_open.txt → 0013.txt} +2 -2
- data/doc/manual/parts/{channels_callbacks.txt → 0014.txt} +3 -3
- data/doc/manual/parts/{channels_operations.txt → 0015.txt} +1 -2
- data/doc/manual/parts/{exec_channels.txt → 0016.txt} +2 -2
- data/doc/manual/parts/{exec_open.txt → 0017.txt} +3 -3
- data/doc/manual/parts/{exec_popen3.txt → 0018.txt} +5 -5
- data/doc/manual/parts/{shells_intro.txt → 0019.txt} +0 -0
- data/doc/manual/parts/{shells_channels.txt → 0020.txt} +5 -5
- data/doc/manual/parts/{shells_shell.txt → 0021.txt} +6 -6
- data/doc/manual/parts/{shells_sync.txt → 0022.txt} +4 -4
- data/doc/manual/parts/{shells_clients.txt → 0023.txt} +3 -3
- data/doc/manual/parts/{forward_intro.txt → 0024.txt} +2 -2
- data/doc/manual/parts/{forward_local.txt → 0025.txt} +4 -4
- data/doc/manual/parts/{forward_remote.txt → 0026.txt} +6 -5
- data/doc/manual/parts/{forward_direct.txt → 0027.txt} +2 -2
- data/doc/manual/parts/{forward_handlers.txt → 0028.txt} +0 -0
- data/doc/manual/parts/{proxy_intro.txt → 0029.txt} +0 -0
- data/doc/manual/parts/{proxy_http.txt → 0030.txt} +6 -6
- data/doc/manual/parts/{proxy_socks.txt → 0031.txt} +4 -2
- data/doc/manual/stylesheets/manual.css +7 -2
- data/lib/net/ssh/connection/driver.rb +6 -0
- data/lib/net/ssh/transport/session.rb +6 -2
- data/lib/net/ssh/userauth/services.rb +1 -1
- data/lib/net/ssh/version.rb +1 -1
- data/test/transport/tc_session.rb +13 -0
- metadata +161 -149
- data/doc/manual/parts/session_session.txt +0 -14
File without changes
|
File without changes
|
@@ -1 +1 @@
|
|
1
|
-
Net::SSH was written by "Jamis Buck":mailto:
|
1
|
+
Net::SSH was written by "Jamis Buck":mailto:jamis_buck@byu.edu. Feel free to send him compliments, candy, money, praise, or new feature patches--he likes all those things. You can send him questions and suggestions, too, if you really want to. However, for bug reports and general feature requests, please use the trackers on the "Net::SSH project page":http://rubyforge.org/projects/net-ssh.
|
@@ -1,46 +1,46 @@
|
|
1
1
|
Before you can do anything with Net::SSH, you need to require the @net/ssh@ module:
|
2
2
|
|
3
|
-
|
3
|
+
{{{lang=ruby,caption=Requiring Net::SSH
|
4
4
|
require 'net/ssh'
|
5
|
-
|
5
|
+
}}}
|
6
6
|
|
7
7
|
Once you have required the @net/ssh@ module, you can begin an SSH session by calling @Net::SSH.start@. This may be used in one of two ways. If called without a block, it will return a reference to the new session as an instance of a @Net::SSH::Session@. Used this way, you must explicitly close the session when you are finished with it.
|
8
8
|
|
9
|
-
|
9
|
+
{{{lang=ruby,number=true,caption=Opening an SSH session
|
10
10
|
session = Net::SSH.start( 'host', 'user', 'passwd' )
|
11
11
|
...
|
12
12
|
session.close
|
13
|
-
|
13
|
+
}}}
|
14
14
|
|
15
15
|
The other approach involves attaching a block to the start method. When used this way, the new session is passed to the block, and the session is automatically closed when the block exits.
|
16
16
|
|
17
|
-
|
17
|
+
{{{lang=ruby,number=true,caption=Opening a transactional SSH session
|
18
18
|
Net::SSH.start( 'host', 'user', 'passwd' ) do |session|
|
19
19
|
...
|
20
20
|
end
|
21
|
-
|
21
|
+
}}}
|
22
22
|
|
23
23
|
If you need to specify a different port on the host to connect to (the default is 22), you can specify it immediately after the @host@ parameter, like so:
|
24
24
|
|
25
|
-
|
25
|
+
{{{lang=ruby,number=true,caption=Specifying the SSH port
|
26
26
|
Net::SSH.start( 'host', 1234, 'user', 'passwd' ) do |session|
|
27
27
|
...
|
28
28
|
end
|
29
|
-
|
29
|
+
}}}
|
30
30
|
|
31
31
|
h3. Using Keyword Arguments
|
32
32
|
|
33
33
|
Some people prefer using keyword arguments for functions with more than a couple of parameters. The @start@ method supports this approach as well, although the @host@ parameter is always positional and always comes first.
|
34
34
|
|
35
|
-
|
35
|
+
{{{lang=ruby,number=true,caption=Using keyword arguments
|
36
36
|
Net::SSH.start( 'host',
|
37
37
|
:password=>'passwd',
|
38
38
|
:port=>1234,
|
39
39
|
:username=>'user',
|
40
|
-
|
40
|
+
... ) do |session|
|
41
41
|
...
|
42
42
|
end
|
43
|
-
|
43
|
+
}}}
|
44
44
|
|
45
45
|
(More about the "@...@" stuff, later.)
|
46
46
|
|
@@ -16,9 +16,9 @@ The "id_dsa" key is the preferred key (since it uses the stronger DSA encryption
|
|
16
16
|
|
17
17
|
To create these keys, you can use the "ssh-keygen" utility from "OpenSSH":http://www.openssh.org. Alternatively, if you have the Net::SSH::Utilities package installed, you can use the "rb-keygen" utility (which is a pure-Ruby implementation of most of the functionality of ssh-keygen).
|
18
18
|
|
19
|
-
|
19
|
+
{{{lang=shell,caption=Generating an SSH key
|
20
20
|
ssh-keygen -t dsa
|
21
|
-
|
21
|
+
}}}
|
22
22
|
|
23
23
|
(If you would rather use an RSA key, replace "dsa" with "rsa" in the command given above.)
|
24
24
|
|
@@ -32,19 +32,19 @@ h3. Connecting using public/private keys
|
|
32
32
|
|
33
33
|
Public/private keys are always tried before the explicit password authentication, even if you provide a password. Thus, if you _only_ want to use public/private key authentication, simply remove the password from the argument list. If you can successfully obtain a session handle, then your keys are set up correctly!
|
34
34
|
|
35
|
-
|
35
|
+
{{{lang=ruby,number=true,caption=SSH authentication using keys
|
36
36
|
Net::SSH.start( 'host', 'user' ) do |session|
|
37
37
|
...
|
38
38
|
end
|
39
|
-
|
39
|
+
}}}
|
40
40
|
|
41
41
|
Furthermore, if your @USER@ environment variable is set to the username that you want to log into the remote machine as, you can even leave the @username@ parameter off:
|
42
42
|
|
43
|
-
|
43
|
+
{{{lang=ruby,number=true,caption=Authentication with an implicit user name
|
44
44
|
Net::SSH.start( 'host' ) do |session|
|
45
45
|
...
|
46
46
|
end
|
47
|
-
|
47
|
+
}}}
|
48
48
|
|
49
49
|
h3. Using keys with passphrases
|
50
50
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
There are various additional options that you can specify when connecting. These options allow you to specify such things as the cipher algorithm to use, whether or not the data stream will be compressed, or explicit paths to the private keys to use.
|
2
2
|
|
3
|
-
|
4
3
|
Options are specified as a hash in the last parameter to the @start@ method. If using the keyword parameters version of the @start@ method, the options hash is whatever is left after processing the @:username@, @:password@, and @:port@ options.
|
5
4
|
|
6
5
|
The complete list of available options, and their valid values, is given in the following table.
|
@@ -26,7 +25,7 @@ table(list).
|
|
26
25
|
|
27
26
|
For example, the following code snippet will connect to the given remote host, and requests that the @ssh-rsa@ host key type be used, with the @blowfish-cbc@ cipher algorithm, and requests that the given private key file be used. Also, the data stream will be compressed.
|
28
27
|
|
29
|
-
|
28
|
+
{{{lang=ruby,number=true,caption=Specifying options when connecting
|
30
29
|
require 'net/ssh'
|
31
30
|
require 'logger'
|
32
31
|
|
@@ -39,4 +38,4 @@ Net::SSH.start(
|
|
39
38
|
) do |session|
|
40
39
|
...
|
41
40
|
end
|
42
|
-
|
41
|
+
}}}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Alternatively, you can use @Net::SSH::Session@ to start your SSH sessions. The @Net::SSH.start@ interface described above is simply a convenience for creating a new Session object explicitly.
|
2
|
+
|
3
|
+
{{{lang=ruby,number=true,caption=Using Net::SSH::Session
|
4
|
+
require 'net/ssh'
|
5
|
+
|
6
|
+
Net::SSH::Session.new(
|
7
|
+
'host', 'username', 'password',
|
8
|
+
:compression => "zlib"
|
9
|
+
) do |session|
|
10
|
+
...
|
11
|
+
end
|
12
|
+
}}}
|
13
|
+
|
14
|
+
Note that @Net::SSH::Session#new@ accepts the same parameters as Net::SSH.start, and may also be called without a block.
|
File without changes
|
@@ -4,11 +4,11 @@ In order to allow the events to be processed in a continuous manner, you need to
|
|
4
4
|
|
5
5
|
The @loop@ method is easy to invoke:
|
6
6
|
|
7
|
-
|
7
|
+
{{{lang=ruby,caption=Session#loop,number=true
|
8
8
|
Net::SSH.start( 'host' ) do |session|
|
9
9
|
...
|
10
10
|
session.loop
|
11
11
|
end
|
12
|
-
|
12
|
+
}}}
|
13
13
|
|
14
14
|
Incidentally, the @loop@ method accepts an optional block, which if specified should return a "false" value when the loop should terminate. In the absense of a block, the loop will continue until there are no more open channels. Sometimes, however, you only want the loop to continue until some action occurs, at which time you then do some processing and then start the loop again.
|
File without changes
|
@@ -6,7 +6,7 @@ This behavior is typical of most of the methods in the Net::SSH API; they simply
|
|
6
6
|
|
7
7
|
Here is an example of opening a channel:
|
8
8
|
|
9
|
-
|
9
|
+
{{{lang=ruby,caption=Opening a channel,number=true
|
10
10
|
Net::SSH.start( 'host' ) do |session|
|
11
11
|
session.open_channel do |channel|
|
12
12
|
puts "channel successfully opened... closing..."
|
@@ -15,6 +15,6 @@ Net::SSH.start( 'host' ) do |session|
|
|
15
15
|
|
16
16
|
session.loop
|
17
17
|
end
|
18
|
-
|
18
|
+
}}}
|
19
19
|
|
20
20
|
Note the use of the @close@ method for the channel. Just like most methods in the Net::SSH API, it does not immediately close the channel, but instead sends a close request to the server and returns. When the server responds that the channel has been closed, the framework will then call any final callbacks for the channel and then remove it.
|
@@ -5,7 +5,7 @@ table(list).
|
|
5
5
|
|=^. @on_close@ | This callback should accept a single parameter: the channel being closed. It is called immediately after the channel is removed from the connection. The callback should not send any data through the channel, since at this point the channel is no longer connected to the remote host.|
|
6
6
|
|=^. @on_confirm_failed@ | This callback should accept four parameters: the channel instance, the reason code, a description of why the confirm failed, and the language code for the message. It is called immediately after the server has indicated that a channel could not be opened.|
|
7
7
|
|=^. @on_confirm_open@ | This callback should accept a single parameter: the channel being opened. It is called immediately after the server has confirmed that the channel has been opened. This callback is typically set by a block passed to an @#open_channel@ call.|
|
8
|
-
|=^. @on_data@ | This callback is invoked when data is received over the channel from the remote server. This data typically corresponds to the remote process's @stdout@ stream.
|
8
|
+
|=^. @on_data@ | This callback is invoked when data is received over the channel from the remote server. This data typically corresponds to the remote process's @stdout@ stream. The channel should accept two parameters: the channel itself, and the data being received.|
|
9
9
|
|=^. @on_eof@ | This callback is called when the server indicates that no more data will be sent _from the server_ over this channel. Your program is still welcome to send data to the server, but you are guaranteed at this point that your @on_data@ and @on_extended_data@ callbacks will no longer be called for this channel. The callback should accept a single parameter, the channel itself.|
|
10
10
|
|=^. @on_extended_data@ | This callback is called when _extended data_ is received from the server. There are (potentially) many _types_ of extended data. The callback should accept three parameters: the channel, an integer indicating the type of the data, and the data itself. Right now, you can pretty much count on the data type being a "1", which corresponds to the remote process's @stderr@ stream. Other data types are not defined in the SSH specification, but that does not mean some SSH servers won't try to invent their own.|
|
11
11
|
|=^. @on_failure@ | When a request is sent over a channel (via the @send_request@ or @send_request_string@ methods), it may either succeed or fail. If it fails, this callback will be invoked. It should take a single parameter: the channel itself.|
|
@@ -17,7 +17,7 @@ In general, you will never need to register callbacks for @on_failure@, @on_requ
|
|
17
17
|
|
18
18
|
Following is an example of registering callbacks on a channel:
|
19
19
|
|
20
|
-
|
20
|
+
{{{lang=ruby,caption=Registering callbacks on a channel,number=true
|
21
21
|
Net::SSH.start( 'host' ) do |session|
|
22
22
|
session.open_channel do |channel|
|
23
23
|
channel.on_close do |ch|
|
@@ -29,4 +29,4 @@ Net::SSH.start( 'host' ) do |session|
|
|
29
29
|
|
30
30
|
session.loop
|
31
31
|
end
|
32
|
-
|
32
|
+
}}}
|
@@ -11,5 +11,4 @@ table(list).
|
|
11
11
|
| @#send_signal@ | Indicates that the server should send the given signal to the process on the other end of the channel.|
|
12
12
|
| @#subsystem@ | Requests that the server start the given subsystem on this channel. This is how (for instance) the SFTP subsystem is invoked. |
|
13
13
|
|
14
|
-
See the API documentation for an exhaustive reference of all available channel
|
15
|
-
operations.
|
14
|
+
See the API documentation for an exhaustive reference of all available channel operations.
|
@@ -2,7 +2,7 @@ To run multiple processes in parallel, you can access the channel API directly,
|
|
2
2
|
|
3
3
|
Suppose, for example, that you wanted to run multiple "tail" commands on various logs on the remote machine, combining them all into the output on the client. Something like the following would suffice:
|
4
4
|
|
5
|
-
|
5
|
+
{{{lang=ruby,number=true,caption=Running "tail" on multiple remote files
|
6
6
|
def do_tail( session, file )
|
7
7
|
session.open_channel do |channel|
|
8
8
|
channel.on_data do |ch, data|
|
@@ -19,7 +19,7 @@ Net::SSH.start( 'host' ) do |session|
|
|
19
19
|
do_tail session, "/var/log/mysql/mysql.err"
|
20
20
|
session.loop
|
21
21
|
end
|
22
|
-
|
22
|
+
}}}
|
23
23
|
|
24
24
|
As you can see, four different logs are tailed on four separate channels. Each channel registers an @on_data@ callback (which simply displays the data it recieves, together with the name of the log file it came from). The @exec@ method of the channel is then invoked, which simply sends the request to execute the process to the server, and then returns.
|
25
25
|
|
@@ -4,7 +4,7 @@ Just open an SSH session. The @#process@ service of the session manages access t
|
|
4
4
|
|
5
5
|
Consider the "bc" command. It is a command-line calculator that accepts expressions on @stdin@ and writes the results to @stdout@. When it encounters the word @quit@ on the input, it exits. Sounds like a great way to demonstrate the @process@ service...
|
6
6
|
|
7
|
-
|
7
|
+
{{{lang=ruby,number=true,caption=Using #process.open
|
8
8
|
Net::SSH.start( 'host' ) do |session|
|
9
9
|
|
10
10
|
session.process.open( "bc" ) do |bc|
|
@@ -23,13 +23,13 @@ Net::SSH.start( 'host' ) do |session|
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
bc.on_exit do |p, status|
|
27
27
|
puts "process finished with exit status: #{status}"
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
32
|
-
|
32
|
+
}}}
|
33
33
|
|
34
34
|
Notice the progression. First, the session itself is started. Then, while the session is active, the process is invoked (via @#process.open@). After we have a handle to the process (which is yielded to the block, in this case), we set up the callbacks on the process. These are reminiscent of, but different from, the callbacks that we set up on the channel itself in the previous section.
|
35
35
|
|
@@ -4,7 +4,7 @@ If you are familiar with the "popen3" Ruby module, this will seem familiar. It's
|
|
4
4
|
|
5
5
|
Here's the previous "bc" example, rewritten to use @#popen3@:
|
6
6
|
|
7
|
-
|
7
|
+
{{{lang=ruby,number=true,caption=Using #process.popen3
|
8
8
|
Net::SSH.start( 'host' ) do |session|
|
9
9
|
|
10
10
|
input, output, error = session.process.popen3( "bc" )
|
@@ -17,19 +17,19 @@ Net::SSH.start( 'host' ) do |session|
|
|
17
17
|
input.puts "quit"
|
18
18
|
|
19
19
|
end
|
20
|
-
|
20
|
+
}}}
|
21
21
|
|
22
22
|
Much more concise, isn't it? One caveat, though: there is no way to kill the process (unless the process can terminate itself, such as through the use of issuing bc's "quit" command as used above) without closing the session. To remedy this, there is also a block version of popen3 that provides an explicit scope for the three data streams:
|
23
23
|
|
24
|
-
|
24
|
+
{{{lang=ruby,number=true,caption=Transactional form of #process.popen3
|
25
25
|
Net::SSH.start( 'host' ) do |session|
|
26
26
|
session.process.popen3( "bc" ) do |input, output, error|
|
27
27
|
[ "5+5", "7*12", "sqrt(2.000000)" ].each do |formula|
|
28
28
|
input.puts formula
|
29
|
-
|
29
|
+
puts "#{formula}=#{output.read}"
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
33
|
+
}}}
|
34
34
|
|
35
35
|
The three streams will be closed and process explicitly terminated when the block ends.
|
File without changes
|
@@ -1,6 +1,6 @@
|
|
1
1
|
At the lowest level, starting a shell is a matter of sending a "shell" request over a channel.
|
2
2
|
|
3
|
-
|
3
|
+
{{{lang=ruby,caption=Sending a shell request,number=true
|
4
4
|
Net::SSH.start( host ) do |session|
|
5
5
|
|
6
6
|
session.open_channel do |channel|
|
@@ -26,13 +26,13 @@ Net::SSH.start( host ) do |session|
|
|
26
26
|
session.loop
|
27
27
|
|
28
28
|
end
|
29
|
-
|
29
|
+
}}}
|
30
30
|
|
31
31
|
The @#send_request@ method accepts three parameters--the name of the request (in this case, "shell"), any additional data to send with the request (none, in this case), and whether or not you want the server to reply with the success or failure of the request. In general, it is a good idea to ask for the server to reply, so that you know when you can start sending data to the shell.
|
32
32
|
|
33
33
|
If you want to open a pty before starting the shell, you can use the #request_pty method of the channel:
|
34
34
|
|
35
|
-
|
35
|
+
{{{lang=ruby,number=true,caption=Opening a pty on a channel
|
36
36
|
Net::SSH.start( host ) do |session|
|
37
37
|
|
38
38
|
session.open_channel do |channel|
|
@@ -65,8 +65,8 @@ Net::SSH.start( host ) do |session|
|
|
65
65
|
session.loop
|
66
66
|
|
67
67
|
end
|
68
|
-
|
68
|
+
}}}
|
69
69
|
|
70
70
|
First, the pty is requested (with an indicator to the server that it should return a "success" or "failure" notification). When the pty is successfully opened, the "on_success" callback is changed, and the shell is then requested.
|
71
71
|
|
72
|
-
It's a lot of hoops to jump through, but it gives you the finest-grained control over opening a shell. For most things, though, you can live with less control. For those tasks, there are the _shell_ and _sync_ services.
|
72
|
+
It's a lot of hoops to jump through, but it gives you the finest-grained control over opening a shell. For most things, though, you can live with less control. For those tasks, there are the _shell_ and _sync_ services.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
To make interacting with shells, simpler, version 0.9 of Net::SSH introduced the _shell service_. This allows you to open a shell (with or without a pty), send a series of commands to the shell, and then wait for the output from the shell.
|
2
2
|
|
3
|
-
|
3
|
+
{{{lang=ruby,number=true,caption=Using the shell service
|
4
4
|
Net::SSH.start( 'localhost' ) do |session|
|
5
5
|
|
6
6
|
shell = session.shell.open
|
@@ -27,13 +27,13 @@ Net::SSH.start( 'localhost' ) do |session|
|
|
27
27
|
$stderr.print shell.stderr while shell.stderr?
|
28
28
|
|
29
29
|
end
|
30
|
-
|
30
|
+
}}}
|
31
31
|
|
32
32
|
Any unrecognized method that is sent to the shell object is interpreted as a command to send to the server. To explicitly send a command, use the @#send_data@ method (but remember to add a newline!). The @#send_data@ method may also be used to send data to any process running in the shell as that process' @stdin@ stream.
|
33
33
|
|
34
34
|
You can also specify that a pty should be allocated for this shell:
|
35
35
|
|
36
|
-
|
36
|
+
{{{lang=ruby,number=true,caption=Allocating a pty for the shell
|
37
37
|
Net::SSH.start( 'localhost' ) do |session|
|
38
38
|
|
39
39
|
shell = session.shell.open( :pty => true )
|
@@ -43,8 +43,8 @@ Net::SSH.start( 'localhost' ) do |session|
|
|
43
43
|
shell = session.shell.open( :pty => { ... } )
|
44
44
|
|
45
45
|
end
|
46
|
-
|
46
|
+
}}}
|
47
47
|
|
48
|
-
If you give a hash for the @:pty@ option, it must be a map of the options that describe the new pty. See the API documentation for the Channel#request_pty method for more information.
|
48
|
+
If you give a hash for the @:pty@ option, it must be a map of the options that describe the new pty. See the API documentation for the @Channel#request_pty@ method for more information.
|
49
49
|
|
50
|
-
Note that this is still an asynchronous approach. You send all the commands through the pipe and then wait for the output. (And be sure to give sufficient time or the processes to terminate!) This is fine for scripts that you just want to throw at the server, but many times you want a more interactive interface, for executing a command and receiving its output before moving on.
|
50
|
+
Note that this is still an asynchronous approach. You send all the commands through the pipe and then wait for the output. (And be sure to give sufficient time or the processes to terminate!) This is fine for scripts that you just want to throw at the server, but many times you want a more interactive interface, for executing a command and receiving its output before moving on.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
The SyncShell service allows you to execute commands on the shell and block until they finish. It is not fool-proof--it has to use some tricks to accomplish this task, and some commands may foul it up. But for most tasks, it works admirably.
|
2
2
|
|
3
|
-
|
3
|
+
{{{lang=ruby,number=true,caption=Using the SyncShell service
|
4
4
|
Net::SSH.start( 'localhost' ) do |session|
|
5
5
|
|
6
6
|
shell = session.shell.sync
|
@@ -20,7 +20,7 @@ Net::SSH.start( 'localhost' ) do |session|
|
|
20
20
|
|
21
21
|
out = shell.cd "/usr/lib"
|
22
22
|
|
23
|
-
|
23
|
+
out = shell.ls "-l"
|
24
24
|
p out.stdout
|
25
25
|
|
26
26
|
out = shell.send_command( "bc", <<CMD )
|
@@ -35,8 +35,8 @@ CMD
|
|
35
35
|
p shell.exit
|
36
36
|
|
37
37
|
end
|
38
|
-
|
38
|
+
}}}
|
39
39
|
|
40
40
|
The result of executing each command is an object that encapsulates the @stdout@ and @stderr@ streams, and the exit status of the command.
|
41
41
|
|
42
|
-
To explicitly execute a command, use the @#send_command@ instead of @#send_data@--otherwise, the command will be executed asynchronously, which is not what you want. Also, if you pass a second parameter to the @#send_command@ method, it is interpreted as the @stdin@ data to send to the new process.
|
42
|
+
To explicitly execute a command, use the @#send_command@ instead of @#send_data@--otherwise, the command will be executed asynchronously, which is not what you want. Also, if you pass a second parameter to the @#send_command@ method, it is interpreted as the @stdin@ data to send to the new process.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Using the shell service and pty's, you can now create a simple SSH terminal client. (You'll also want to download and install the "ruby-termios":http://arika.org/ruby/termios library so that your input is not interpreted in a linewise fashion.)
|
2
2
|
|
3
|
-
|
3
|
+
{{{lang=ruby,number=true,caption=A simple SSH terminal client in Ruby
|
4
4
|
begin
|
5
5
|
require 'termios'
|
6
6
|
rescue LoadError
|
@@ -26,7 +26,7 @@ end
|
|
26
26
|
|
27
27
|
Net::SSH.start( host, user ) do |session|
|
28
28
|
|
29
|
-
|
29
|
+
begin
|
30
30
|
stdin_buffer false
|
31
31
|
|
32
32
|
shell = session.shell.open( :pty => true )
|
@@ -46,6 +46,6 @@ Net::SSH.start( host, user ) do |session|
|
|
46
46
|
end
|
47
47
|
|
48
48
|
end
|
49
|
-
|
49
|
+
}}}
|
50
50
|
|
51
51
|
The above code is also available as an example script in the Net::SSH distribution (@examples/ssh-client.rb@).
|
@@ -5,13 +5,13 @@ Port forwarding is a feature of the SSH protocol that allows you to specify a po
|
|
5
5
|
|
6
6
|
All port forwarding in the Net::SSH library is managed by the @#forward@ service. Just invoke methods on that service to set up any of various port forwarding configurations.
|
7
7
|
|
8
|
-
|
8
|
+
{{{lang=ruby,number=true,caption=Accessing the #forward service
|
9
9
|
Net::SSH.start( 'host' ) do |session|
|
10
10
|
forward = session.forward
|
11
11
|
...
|
12
12
|
session.loop
|
13
13
|
end
|
14
|
-
|
14
|
+
}}}
|
15
15
|
|
16
16
|
You can define any number of forwards before invoking the main loop, in which case all of those forwards will be handled transparently (and silently) in parallel, over the same connection. (Isn't SSH lovely?)
|
17
17
|
|
@@ -1,18 +1,18 @@
|
|
1
1
|
Forwarding a local connection to a remote destination is simply a matter of invoking the @#local@ method of the @#forward@ service. The simplest version of the method just takes three parameters: the local port to listen on, and the remote host and port to forward the connection to:
|
2
2
|
|
3
|
-
|
3
|
+
{{{lang=ruby,number=true,caption=Forwarding a local port
|
4
4
|
Net::SSH.start( 'host' ) do |session|
|
5
5
|
session.forward.local( 1234, 'www.google.com', 80 )
|
6
6
|
session.loop
|
7
7
|
end
|
8
|
-
|
8
|
+
}}}
|
9
9
|
|
10
10
|
In the above example, then, any connection received on port 1234 will be forwarded to port 80 on "www.google.com". This means that if you were to point a browser at "http://localhost:1234", it would pull up "Google":http://www.google.com.
|
11
11
|
|
12
12
|
By default, only connections _from the local host_ are accepted. This is because the default bind address is 127.0.0.1. You can specify any bind address you want (including 0.0.0.0 to allow connections from anywhere) by specifying that address as the first parameter to @#local@, with the local port number immediately following.
|
13
13
|
|
14
|
-
|
14
|
+
{{{lang=ruby,caption=Specifying the bind address when forwarding a local port
|
15
15
|
session.forward.local( '0.0.0.0', 1234, 'www.google.com', 80 )
|
16
|
-
|
16
|
+
}}}
|
17
17
|
|
18
18
|
In this configuration, anyone from anywhere can connect to your machine on port 1234 and be forwarded to Google.
|