net-ssh 0.6.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. data/doc/manual-html/chapter-1.html +59 -24
  2. data/doc/manual-html/chapter-2.html +116 -77
  3. data/doc/manual-html/chapter-3.html +80 -41
  4. data/doc/manual-html/chapter-4.html +111 -71
  5. data/doc/manual-html/chapter-5.html +267 -155
  6. data/doc/manual-html/chapter-6.html +211 -75
  7. data/doc/manual-html/chapter-7.html +331 -0
  8. data/doc/manual-html/index.html +39 -13
  9. data/doc/manual-html/{manual.css → stylesheets/manual.css} +81 -8
  10. data/doc/manual-html/stylesheets/ruby.css +17 -0
  11. data/doc/manual/chapter.erb +20 -0
  12. data/doc/manual/manual.rb +80 -9
  13. data/doc/manual/manual.yml +12 -2
  14. data/doc/manual/page.erb +1 -1
  15. data/doc/manual/parts/channels_callbacks.txt +11 -11
  16. data/doc/manual/parts/channels_loop.txt +6 -6
  17. data/doc/manual/parts/channels_open.txt +9 -9
  18. data/doc/manual/parts/exec_channels.txt +15 -15
  19. data/doc/manual/parts/exec_open.txt +17 -18
  20. data/doc/manual/parts/exec_popen3.txt +18 -18
  21. data/doc/manual/parts/forward_direct.txt +16 -16
  22. data/doc/manual/parts/forward_intro.txt +7 -7
  23. data/doc/manual/parts/forward_local.txt +9 -9
  24. data/doc/manual/parts/forward_remote.txt +9 -9
  25. data/doc/manual/parts/intro_getting.txt +11 -11
  26. data/doc/manual/parts/proxy_http.txt +27 -27
  27. data/doc/manual/parts/proxy_socks.txt +17 -17
  28. data/doc/manual/parts/session_key.txt +13 -14
  29. data/doc/manual/parts/session_options.txt +14 -14
  30. data/doc/manual/parts/session_session.txt +9 -9
  31. data/doc/manual/parts/session_start.txt +27 -27
  32. data/doc/manual/parts/shells_channels.txt +72 -0
  33. data/doc/manual/parts/shells_clients.txt +51 -0
  34. data/doc/manual/parts/shells_intro.txt +7 -0
  35. data/doc/manual/parts/shells_shell.txt +50 -0
  36. data/doc/manual/parts/shells_sync.txt +42 -0
  37. data/doc/manual/{manual.css → stylesheets/manual.css} +81 -8
  38. data/doc/manual/stylesheets/ruby.css +17 -0
  39. data/examples/channel-demo.rb +1 -1
  40. data/examples/port-forward.rb +1 -1
  41. data/examples/process-demo.rb +1 -1
  42. data/examples/remote-net-port-forward.rb +1 -1
  43. data/examples/remote-port-forward.rb +1 -1
  44. data/examples/shell-demo.rb +46 -0
  45. data/examples/ssh-client.rb +67 -0
  46. data/examples/sync-shell-demo.rb +69 -0
  47. data/examples/tail-demo.rb +1 -1
  48. data/lib/net/ssh.rb +1 -1
  49. data/lib/net/ssh/connection/channel.rb +61 -7
  50. data/lib/net/ssh/connection/constants.rb +1 -1
  51. data/lib/net/ssh/connection/driver.rb +61 -8
  52. data/lib/net/ssh/connection/services.rb +1 -1
  53. data/lib/net/ssh/connection/term.rb +1 -1
  54. data/lib/net/ssh/errors.rb +1 -1
  55. data/lib/net/ssh/proxy/errors.rb +1 -1
  56. data/lib/net/ssh/proxy/http.rb +1 -1
  57. data/lib/net/ssh/proxy/socks4.rb +1 -1
  58. data/lib/net/ssh/proxy/socks5.rb +1 -1
  59. data/lib/net/ssh/service/forward/driver.rb +1 -1
  60. data/lib/net/ssh/service/forward/local-network-handler.rb +1 -1
  61. data/lib/net/ssh/service/forward/remote-network-handler.rb +1 -1
  62. data/lib/net/ssh/service/forward/services.rb +1 -1
  63. data/lib/net/ssh/service/process/driver.rb +1 -1
  64. data/lib/net/ssh/service/process/open.rb +1 -1
  65. data/lib/net/ssh/service/process/popen3.rb +20 -2
  66. data/lib/net/ssh/service/process/services.rb +1 -1
  67. data/lib/net/ssh/service/services.rb +3 -1
  68. data/lib/net/ssh/service/shell/driver.rb +86 -0
  69. data/lib/net/ssh/service/shell/services.rb +54 -0
  70. data/lib/net/ssh/service/shell/shell.rb +213 -0
  71. data/lib/net/ssh/service/shell/sync.rb +114 -0
  72. data/lib/net/ssh/session.rb +9 -1
  73. data/lib/net/ssh/transport/algorithm-negotiator.rb +1 -1
  74. data/lib/net/ssh/transport/compress/compressor.rb +1 -1
  75. data/lib/net/ssh/transport/compress/decompressor.rb +1 -1
  76. data/lib/net/ssh/transport/compress/none-compressor.rb +1 -1
  77. data/lib/net/ssh/transport/compress/none-decompressor.rb +1 -1
  78. data/lib/net/ssh/transport/compress/services.rb +1 -1
  79. data/lib/net/ssh/transport/compress/zlib-compressor.rb +1 -1
  80. data/lib/net/ssh/transport/compress/zlib-decompressor.rb +1 -1
  81. data/lib/net/ssh/transport/constants.rb +1 -1
  82. data/lib/net/ssh/transport/errors.rb +1 -1
  83. data/lib/net/ssh/transport/identity-cipher.rb +1 -1
  84. data/lib/net/ssh/transport/kex/dh-gex.rb +1 -1
  85. data/lib/net/ssh/transport/kex/dh.rb +1 -1
  86. data/lib/net/ssh/transport/kex/services.rb +1 -1
  87. data/lib/net/ssh/transport/ossl/buffer-factory.rb +1 -1
  88. data/lib/net/ssh/transport/ossl/buffer.rb +1 -1
  89. data/lib/net/ssh/transport/ossl/cipher-factory.rb +1 -1
  90. data/lib/net/ssh/transport/ossl/digest-factory.rb +1 -1
  91. data/lib/net/ssh/transport/ossl/hmac-factory.rb +1 -1
  92. data/lib/net/ssh/transport/ossl/hmac/hmac.rb +1 -1
  93. data/lib/net/ssh/transport/ossl/hmac/md5-96.rb +1 -1
  94. data/lib/net/ssh/transport/ossl/hmac/md5.rb +1 -1
  95. data/lib/net/ssh/transport/ossl/hmac/none.rb +1 -1
  96. data/lib/net/ssh/transport/ossl/hmac/services.rb +1 -1
  97. data/lib/net/ssh/transport/ossl/hmac/sha1-96.rb +1 -1
  98. data/lib/net/ssh/transport/ossl/hmac/sha1.rb +1 -1
  99. data/lib/net/ssh/transport/ossl/key-factory.rb +5 -2
  100. data/lib/net/ssh/transport/ossl/services.rb +1 -1
  101. data/lib/net/ssh/transport/packet-stream.rb +1 -1
  102. data/lib/net/ssh/transport/services.rb +1 -1
  103. data/lib/net/ssh/transport/session.rb +10 -1
  104. data/lib/net/ssh/transport/version-negotiator.rb +1 -1
  105. data/lib/net/ssh/userauth/agent.rb +1 -1
  106. data/lib/net/ssh/userauth/constants.rb +1 -1
  107. data/lib/net/ssh/userauth/driver.rb +1 -1
  108. data/lib/net/ssh/userauth/methods/hostbased.rb +1 -1
  109. data/lib/net/ssh/userauth/methods/keyboard-interactive.rb +104 -0
  110. data/lib/net/ssh/userauth/methods/password.rb +1 -1
  111. data/lib/net/ssh/userauth/methods/publickey.rb +1 -1
  112. data/lib/net/ssh/userauth/methods/services.rb +28 -6
  113. data/lib/net/ssh/userauth/services.rb +8 -5
  114. data/lib/net/ssh/userauth/userkeys.rb +1 -1
  115. data/lib/net/ssh/util/buffer.rb +1 -1
  116. data/lib/net/ssh/util/openssl.rb +1 -1
  117. data/lib/net/ssh/util/prompter.rb +1 -1
  118. data/lib/net/ssh/version.rb +2 -2
  119. data/test/ALL-TESTS.rb +1 -1
  120. data/test/connection/tc_channel.rb +1 -1
  121. data/test/connection/tc_driver.rb +1 -1
  122. data/test/connection/tc_integration.rb +1 -1
  123. data/test/proxy/tc_http.rb +1 -1
  124. data/test/proxy/tc_socks4.rb +1 -1
  125. data/test/proxy/tc_socks5.rb +1 -1
  126. data/test/service/forward/tc_driver.rb +1 -1
  127. data/test/service/forward/tc_local_network_handler.rb +1 -1
  128. data/test/service/forward/tc_remote_network_handler.rb +1 -1
  129. data/test/service/process/tc_driver.rb +1 -1
  130. data/test/service/process/tc_integration.rb +1 -1
  131. data/test/service/process/tc_open.rb +1 -1
  132. data/test/service/process/tc_popen3.rb +13 -13
  133. data/test/tc_integration.rb +1 -1
  134. data/test/transport/compress/tc_none_compress.rb +1 -1
  135. data/test/transport/compress/tc_none_decompress.rb +1 -1
  136. data/test/transport/compress/tc_zlib_compress.rb +1 -1
  137. data/test/transport/compress/tc_zlib_decompress.rb +1 -1
  138. data/test/transport/kex/tc_dh.rb +2 -1
  139. data/test/transport/kex/tc_dh_gex.rb +1 -1
  140. data/test/transport/ossl/hmac/tc_hmac.rb +1 -1
  141. data/test/transport/ossl/hmac/tc_md5.rb +1 -1
  142. data/test/transport/ossl/hmac/tc_md5_96.rb +1 -1
  143. data/test/transport/ossl/hmac/tc_none.rb +1 -1
  144. data/test/transport/ossl/hmac/tc_sha1.rb +1 -1
  145. data/test/transport/ossl/hmac/tc_sha1_96.rb +1 -1
  146. data/test/transport/ossl/tc_buffer.rb +1 -1
  147. data/test/transport/ossl/tc_buffer_factory.rb +1 -1
  148. data/test/transport/ossl/tc_cipher_factory.rb +1 -1
  149. data/test/transport/ossl/tc_digest_factory.rb +1 -1
  150. data/test/transport/ossl/tc_hmac_factory.rb +1 -1
  151. data/test/transport/ossl/tc_key_factory.rb +1 -1
  152. data/test/transport/tc_algorithm_negotiator.rb +1 -1
  153. data/test/transport/tc_identity_cipher.rb +1 -1
  154. data/test/transport/tc_integration.rb +1 -1
  155. data/test/transport/tc_packet_stream.rb +1 -1
  156. data/test/transport/tc_session.rb +1 -1
  157. data/test/transport/tc_version_negotiator.rb +1 -1
  158. data/test/userauth/methods/tc_hostbased.rb +1 -1
  159. data/test/userauth/methods/tc_password.rb +1 -1
  160. data/test/userauth/methods/tc_publickey.rb +1 -1
  161. data/test/userauth/tc_agent.rb +1 -1
  162. data/test/userauth/tc_driver.rb +1 -1
  163. data/test/userauth/tc_integration.rb +15 -1
  164. data/test/userauth/tc_userkeys.rb +1 -1
  165. data/test/util/tc_buffer.rb +5 -5
  166. metadata +26 -6
@@ -16,10 +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
- <pre>
20
- ssh-keygen -t dsa
21
- </pre>
22
-
19
+ [!figure lang=shell,caption=Generating an SSH key
20
+ ssh-keygen -t dsa
21
+ !]
23
22
 
24
23
  (If you would rather use an RSA key, replace "dsa" with "rsa" in the command given above.)
25
24
 
@@ -33,19 +32,19 @@ h3. Connecting using public/private keys
33
32
 
34
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!
35
34
 
36
- <pre>
37
- Net::SSH.start( 'host', 'user' ) do |session|
38
- ...
39
- end
40
- </pre>
35
+ [!figure lang=ruby,number=true,caption=SSH authentication using keys
36
+ Net::SSH.start( 'host', 'user' ) do |session|
37
+ ...
38
+ end
39
+ !]
41
40
 
42
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:
43
42
 
44
- <pre>
45
- Net::SSH.start( 'host' ) do |session|
46
- ...
47
- end
48
- </pre>
43
+ [!figure lang=ruby,number=true,caption=Authentication with an implicit user name
44
+ Net::SSH.start( 'host' ) do |session|
45
+ ...
46
+ end
47
+ !]
49
48
 
50
49
  h3. Using keys with passphrases
51
50
 
@@ -7,7 +7,7 @@ The complete list of available options, and their valid values, is given in the
7
7
 
8
8
  table(list).
9
9
  |_. Option |_. Description |
10
- |^=. @:auth_methods@ | This is the list of authorization methods to try. It defaults to "publickey", "keyboard-interactive", "password", and "hostbased". (These are also the only authorization methods that are supported.) If you want them to be tried in a different order, or if you don't want certain methods to be used, you can specify your own list via this option.|
10
+ |^=. @:auth_methods@ | This is the list of authorization methods to try. It defaults to "publickey", "hostbased", "password", and "keyboard-interactive". (These are also the only authorization methods that are supported.) If you want them to be tried in a different order, or if you don't want certain methods to be used, you can specify your own list via this option.|
11
11
  |^=. @:compression@ | The compression algorithm to use when compressing the data stream. Valid values are @none@ and @zlib@. The default is @none@.|
12
12
  |^=. @:compression_level@ | This is only used when the compression algorithm is @zlib@. It is an integer value from 0 to 9, representing the quality of the compression. A 0 is no compression, and a 9 is most compression. The default is 6.|
13
13
  |^=. @:container@ | This is the dependency injection container to use when registering all of the services that Net::SSH uses internally. If unspecified (the default) a new container will be created. This option allows you to reuse a single container for multiple application components.|
@@ -26,17 +26,17 @@ table(list).
26
26
 
27
27
  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
28
 
29
- <pre>
30
- require 'net/ssh'
31
- require 'logger'
29
+ [!figure lang=ruby,number=true,caption=Specifying options when connecting
30
+ require 'net/ssh'
31
+ require 'logger'
32
32
 
33
- Net::SSH.start(
34
- 'host', 'user',
35
- :host_key => "ssh-rsa",
36
- :encryption => "blowfish-cbc",
37
- :keys => [ "/tmp/temporary-key" ],
38
- :compression => "zlib"
39
- ) do |session|
40
- ...
41
- end
42
- </pre>
33
+ Net::SSH.start(
34
+ 'host', 'user',
35
+ :host_key => "ssh-rsa",
36
+ :encryption => "blowfish-cbc",
37
+ :keys => [ "/tmp/temporary-key" ],
38
+ :compression => "zlib"
39
+ ) do |session|
40
+ ...
41
+ end
42
+ !]
@@ -1,14 +1,14 @@
1
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
2
 
3
- <pre>
4
- require 'net/ssh'
3
+ [!figure lang=ruby,number=true,caption=Using Net::SSH::Session
4
+ require 'net/ssh'
5
5
 
6
- Net::SSH::Session.new(
7
- 'host', 'username', 'password',
8
- :compression => "zlib"
9
- ) do |session|
10
- ...
11
- end
12
- </pre>
6
+ Net::SSH::Session.new(
7
+ 'host', 'username', 'password',
8
+ :compression => "zlib"
9
+ ) do |session|
10
+ ...
11
+ end
12
+ !]
13
13
 
14
14
  Note that Net::SSH::Session#new accepts the same parameters as Net::SSH.start, and may also be called without a block.
@@ -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
- <pre>
4
- require 'net/ssh'
5
- </pre>
3
+ [!figure lang=ruby,caption=Requiring Net::SSH
4
+ require 'net/ssh'
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
- <pre>
10
- session = Net::SSH.start( 'host', 'user', 'passwd' )
11
- ...
12
- session.close
13
- </pre>
9
+ [!figure lang=ruby,number=true,caption=Opening an SSH session
10
+ session = Net::SSH.start( 'host', 'user', 'passwd' )
11
+ ...
12
+ session.close
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
- <pre>
18
- Net::SSH.start( 'host', 'user', 'passwd' ) do |session|
19
- ...
20
- end
21
- </pre>
17
+ [!figure lang=ruby,number=true,caption=Opening a transactional SSH session
18
+ Net::SSH.start( 'host', 'user', 'passwd' ) do |session|
19
+ ...
20
+ end
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
- <pre>
26
- Net::SSH.start( 'host', 1234, 'user', 'passwd' ) do |session|
27
- ...
28
- end
29
- </pre>
25
+ [!figure lang=ruby,number=true,caption=Specifying the SSH port
26
+ Net::SSH.start( 'host', 1234, 'user', 'passwd' ) do |session|
27
+ ...
28
+ end
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
- <pre>
36
- Net::SSH.start( 'host',
37
- :password=>'passwd',
38
- :port=>1234,
39
- :username=>'user',
40
- ... ) do |session|
41
- ...
42
- end
43
- </pre>
35
+ [!figure lang=ruby,number=true,caption=Using keyword arguments
36
+ Net::SSH.start( 'host',
37
+ :password=>'passwd',
38
+ :port=>1234,
39
+ :username=>'user',
40
+ ... ) do |session|
41
+ ...
42
+ end
43
+ !]
44
44
 
45
45
  (More about the "@...@" stuff, later.)
46
46
 
@@ -0,0 +1,72 @@
1
+ At the lowest level, starting a shell is a matter of sending a "shell" request over a channel.
2
+
3
+ [!figure lang=ruby,caption=Sending a shell request,number=true
4
+ Net::SSH.start( host ) do |session|
5
+
6
+ session.open_channel do |channel|
7
+
8
+ channel.on_success do
9
+ puts "shell was started successfully!"
10
+ channel.send_data "exit\n" # tell the shell to exit
11
+ end
12
+ channel.on_failure do
13
+ puts "shell could not be started!"
14
+ end
15
+ channel.on_data do |ch,data|
16
+ puts "recieved #{data} from shell"
17
+ end
18
+ channel.on_close do
19
+ puts "shell terminated"
20
+ end
21
+
22
+ channel.send_request "shell", nil, true
23
+
24
+ end
25
+
26
+ session.loop
27
+
28
+ end
29
+ !]
30
+
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
+
33
+ If you want to open a pty before starting the shell, you can use the #request_pty method of the channel:
34
+
35
+ [!figure lang=ruby,number=true,caption=Opening a pty on a channel
36
+ Net::SSH.start( host ) do |session|
37
+
38
+ session.open_channel do |channel|
39
+
40
+ channel.on_success do
41
+ puts "pty was requested successfully!"
42
+
43
+ channel.on_success do
44
+ puts "shell was started successfully!"
45
+ channel.send_data "exit\n" # tell the shell to exit
46
+ end
47
+
48
+ channel.send_request "shell", nil, true
49
+ end
50
+
51
+ channel.on_failure do
52
+ puts "shell could not be started!"
53
+ end
54
+ channel.on_data do |ch,data|
55
+ puts "recieved #{data} from shell"
56
+ end
57
+ channel.on_close do
58
+ puts "shell terminated"
59
+ end
60
+
61
+ channel.request_pty :want_reply => true
62
+
63
+ end
64
+
65
+ session.loop
66
+
67
+ end
68
+ !]
69
+
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
+
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.
@@ -0,0 +1,51 @@
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
+
3
+ [!figure lang=ruby,number=true,caption=A simple SSH terminal client in Ruby
4
+ begin
5
+ require 'termios'
6
+ rescue LoadError
7
+ end
8
+
9
+ def stdin_buffer( enable )
10
+ return unless defined?( Termios )
11
+ attr = Termios::getattr( $stdin )
12
+ if enable
13
+ attr.c_lflag |= Termios::ICANON | Termios::ECHO
14
+ else
15
+ attr.c_lflag &= ~(Termios::ICANON|Termios::ECHO)
16
+ end
17
+ Termios::setattr( $stdin, Termios::TCSANOW, attr )
18
+ end
19
+
20
+ host = ARGV.shift or abort "You must specify the [user@]host to connect to"
21
+ if host =~ /@/
22
+ user, host = host.match( /(.*?)@(.*)/ )[1,2]
23
+ else
24
+ user = ENV['USER'] || ENV['USER_NAME']
25
+ end
26
+
27
+ Net::SSH.start( host, user ) do |session|
28
+
29
+ begin
30
+ stdin_buffer false
31
+
32
+ shell = session.shell.open( :pty => true )
33
+
34
+ loop do
35
+ break unless shell.open?
36
+ if IO.select([$stdin],nil,nil,0.01)
37
+ data = $stdin.sysread(1)
38
+ shell.send_data data
39
+ end
40
+
41
+ $stdout.print shell.stdout while shell.stdout?
42
+ $stdout.flush
43
+ end
44
+ ensure
45
+ stdin_buffer true
46
+ end
47
+
48
+ end
49
+ !]
50
+
51
+ The above code is also available as an example script in the Net::SSH distribution (@examples/ssh-client.rb@).
@@ -0,0 +1,7 @@
1
+ A user's _shell_ is the environment in which commands are executed on a remote machine. There are a variety of different shells, including "bash":http://www.gnu.org/software/bash/bash.html, csh, tcsh, "ksh":http://www.kornshell.com/, and many others.
2
+
3
+ A shell may be executed like any other program, and when run, it (more-or-less) enters a read-execute-prompt cycle in which the user may interactively run commands.
4
+
5
+ SSH has special support for shells, allowing you to start a shell on a channel and have all subsequent data sent to that channel interpreted as the user's input to the shell. Also, SSH supports pty's (_pseudo-tty_'s, or terminals), which allow the shell to act as if it were running locally on the users own machine.
6
+
7
+ Because a shell is just a program, you can always start a shell simply by executing it (as described in the previous chapter). However, you can also take advantage of SSH's builtin shell support to execute the user's preferred shell. This chapter will discuss this approach.
@@ -0,0 +1,50 @@
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
+
3
+ [!figure lang=ruby,number=true,caption=Using the shell service
4
+ Net::SSH.start( 'localhost' ) do |session|
5
+
6
+ shell = session.shell.open
7
+
8
+ # script what we want to do
9
+ shell.pwd
10
+ shell.cd "/"
11
+ shell.pwd
12
+ shell.test "-e foo"
13
+ shell.cd "/really/bogus/directory"
14
+ shell.send_data "/sbin/ifconfig\n"
15
+ shell.pwd
16
+ shell.ruby "-v"
17
+ shell.cd "/usr/lib"
18
+ shell.pwd
19
+ shell.exit
20
+
21
+ # give the above commands sufficient time to terminate
22
+ sleep 0.5
23
+
24
+ # display the output
25
+ $stdout.print shell.stdout while shell.stdout?
26
+ $stderr.puts "-- stderr: --"
27
+ $stderr.print shell.stderr while shell.stderr?
28
+
29
+ end
30
+ !]
31
+
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
+
34
+ You can also specify that a pty should be allocated for this shell:
35
+
36
+ [!figure lang=ruby,number=true,caption=Allocating a pty for the shell
37
+ Net::SSH.start( 'localhost' ) do |session|
38
+
39
+ shell = session.shell.open( :pty => true )
40
+
41
+ # or
42
+
43
+ shell = session.shell.open( :pty => { ... } )
44
+
45
+ end
46
+ !]
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.
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.
@@ -0,0 +1,42 @@
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
+
3
+ [!figure lang=ruby,number=true,caption=Using the SyncShell service
4
+ Net::SSH.start( 'localhost' ) do |session|
5
+
6
+ shell = session.shell.sync
7
+
8
+ out = shell.pwd
9
+ p out.stdout
10
+
11
+ out = shell.test "-e foo"
12
+ p out.status
13
+
14
+ out = shell.cd "/really/bogus/directory"
15
+ p out.stderr
16
+ p out.status
17
+
18
+ out = shell.ruby "-v"
19
+ p out.stdout
20
+
21
+ out = shell.cd "/usr/lib"
22
+
23
+ out = shell.ls "-l"
24
+ p out.stdout
25
+
26
+ out = shell.send_command( "bc", <<CMD )
27
+ 5+5
28
+ 10*2
29
+ scale=5
30
+ 3/4
31
+ quit
32
+ CMD
33
+ p out.stdout
34
+
35
+ p shell.exit
36
+
37
+ end
38
+ !]
39
+
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
+
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.
@@ -107,12 +107,6 @@ a:hover {
107
107
  text-align: justify;
108
108
  }
109
109
 
110
- #content pre {
111
- background: #FFE;
112
- border: 1px dotted #AAA;
113
- padding: 1em;
114
- }
115
-
116
110
  #content h1 {
117
111
  background: #005;
118
112
  color: #FFF;
@@ -186,7 +180,86 @@ a:hover {
186
180
  text-align: center;
187
181
  }
188
182
 
189
- table.list td {
190
- border-bottom: 1px dotted #005;
183
+ table.list {
184
+ margin: 2em;
185
+ border: 1px solid black;
186
+ background: #FFD;
187
+ padding: 0px;
188
+ border-spacing: 0px;
189
+ }
190
+
191
+ table.list th {
192
+ border-bottom: 1px solid #005;
191
193
  padding-bottom: 5px;
194
+ background: #008;
195
+ color: white;
196
+ padding: 0.5em;
197
+ text-align: left;
198
+ }
199
+
200
+ table.list td {
201
+ padding: 0.2em;
202
+ text-align: left;
203
+ vertical-align: top;
204
+ border-bottom: 1px solid;
205
+ }
206
+
207
+ .prevnext {
208
+ padding: 0.5em 1em 0.5em 1em;
209
+ background: #557;
210
+ color: #FFF;
211
+ font-size: small;
212
+ font-weight: bold;
213
+ border: 1px solid #000;
214
+ }
215
+
216
+ .prevnext a {
217
+ color: #FF0;
218
+ }
219
+
220
+ .top .prevnext {
221
+ margin: 0 0 1em 0;
222
+ text-align: left;
223
+ }
224
+
225
+ .bottom .prevnext {
226
+ margin: 1em 0 0 0;
227
+ text-align: right;
228
+ }
229
+
230
+ .figure {
231
+ border: 1px solid black;
232
+ line-height: normal;
233
+ background: #FFD;
234
+ margin: 2em;
235
+ }
236
+
237
+ .figure .caption {
238
+ background: #008;
239
+ color: white;
240
+ font-weight: bold;
241
+ font-size: small;
242
+ padding: 4px 24px 4px 8px;
243
+ margin-left: -4px;
244
+ border: 1px dotted #77F;
245
+ }
246
+
247
+ .figure .body {
248
+ padding-left: 1em;
249
+ }
250
+
251
+ .figure pre {
252
+ padding: 0px;
253
+ background: transparent;
254
+ border: none;
255
+ font-size: small;
256
+ font-family: mono;
257
+ }
258
+
259
+ .figure .lineno {
260
+ text-align: right;
261
+ color: #B00;
262
+ font-family: mono;
263
+ font-size: small;
264
+ padding-right: 1em;
192
265
  }