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.
- data/doc/manual-html/chapter-1.html +59 -24
- data/doc/manual-html/chapter-2.html +116 -77
- data/doc/manual-html/chapter-3.html +80 -41
- data/doc/manual-html/chapter-4.html +111 -71
- data/doc/manual-html/chapter-5.html +267 -155
- data/doc/manual-html/chapter-6.html +211 -75
- data/doc/manual-html/chapter-7.html +331 -0
- data/doc/manual-html/index.html +39 -13
- data/doc/manual-html/{manual.css → stylesheets/manual.css} +81 -8
- data/doc/manual-html/stylesheets/ruby.css +17 -0
- data/doc/manual/chapter.erb +20 -0
- data/doc/manual/manual.rb +80 -9
- data/doc/manual/manual.yml +12 -2
- data/doc/manual/page.erb +1 -1
- data/doc/manual/parts/channels_callbacks.txt +11 -11
- data/doc/manual/parts/channels_loop.txt +6 -6
- data/doc/manual/parts/channels_open.txt +9 -9
- data/doc/manual/parts/exec_channels.txt +15 -15
- data/doc/manual/parts/exec_open.txt +17 -18
- data/doc/manual/parts/exec_popen3.txt +18 -18
- data/doc/manual/parts/forward_direct.txt +16 -16
- data/doc/manual/parts/forward_intro.txt +7 -7
- data/doc/manual/parts/forward_local.txt +9 -9
- data/doc/manual/parts/forward_remote.txt +9 -9
- data/doc/manual/parts/intro_getting.txt +11 -11
- data/doc/manual/parts/proxy_http.txt +27 -27
- data/doc/manual/parts/proxy_socks.txt +17 -17
- data/doc/manual/parts/session_key.txt +13 -14
- data/doc/manual/parts/session_options.txt +14 -14
- data/doc/manual/parts/session_session.txt +9 -9
- data/doc/manual/parts/session_start.txt +27 -27
- data/doc/manual/parts/shells_channels.txt +72 -0
- data/doc/manual/parts/shells_clients.txt +51 -0
- data/doc/manual/parts/shells_intro.txt +7 -0
- data/doc/manual/parts/shells_shell.txt +50 -0
- data/doc/manual/parts/shells_sync.txt +42 -0
- data/doc/manual/{manual.css → stylesheets/manual.css} +81 -8
- data/doc/manual/stylesheets/ruby.css +17 -0
- data/examples/channel-demo.rb +1 -1
- data/examples/port-forward.rb +1 -1
- data/examples/process-demo.rb +1 -1
- data/examples/remote-net-port-forward.rb +1 -1
- data/examples/remote-port-forward.rb +1 -1
- data/examples/shell-demo.rb +46 -0
- data/examples/ssh-client.rb +67 -0
- data/examples/sync-shell-demo.rb +69 -0
- data/examples/tail-demo.rb +1 -1
- data/lib/net/ssh.rb +1 -1
- data/lib/net/ssh/connection/channel.rb +61 -7
- data/lib/net/ssh/connection/constants.rb +1 -1
- data/lib/net/ssh/connection/driver.rb +61 -8
- data/lib/net/ssh/connection/services.rb +1 -1
- data/lib/net/ssh/connection/term.rb +1 -1
- data/lib/net/ssh/errors.rb +1 -1
- data/lib/net/ssh/proxy/errors.rb +1 -1
- data/lib/net/ssh/proxy/http.rb +1 -1
- data/lib/net/ssh/proxy/socks4.rb +1 -1
- data/lib/net/ssh/proxy/socks5.rb +1 -1
- data/lib/net/ssh/service/forward/driver.rb +1 -1
- data/lib/net/ssh/service/forward/local-network-handler.rb +1 -1
- data/lib/net/ssh/service/forward/remote-network-handler.rb +1 -1
- data/lib/net/ssh/service/forward/services.rb +1 -1
- data/lib/net/ssh/service/process/driver.rb +1 -1
- data/lib/net/ssh/service/process/open.rb +1 -1
- data/lib/net/ssh/service/process/popen3.rb +20 -2
- data/lib/net/ssh/service/process/services.rb +1 -1
- data/lib/net/ssh/service/services.rb +3 -1
- data/lib/net/ssh/service/shell/driver.rb +86 -0
- data/lib/net/ssh/service/shell/services.rb +54 -0
- data/lib/net/ssh/service/shell/shell.rb +213 -0
- data/lib/net/ssh/service/shell/sync.rb +114 -0
- data/lib/net/ssh/session.rb +9 -1
- data/lib/net/ssh/transport/algorithm-negotiator.rb +1 -1
- data/lib/net/ssh/transport/compress/compressor.rb +1 -1
- data/lib/net/ssh/transport/compress/decompressor.rb +1 -1
- data/lib/net/ssh/transport/compress/none-compressor.rb +1 -1
- data/lib/net/ssh/transport/compress/none-decompressor.rb +1 -1
- data/lib/net/ssh/transport/compress/services.rb +1 -1
- data/lib/net/ssh/transport/compress/zlib-compressor.rb +1 -1
- data/lib/net/ssh/transport/compress/zlib-decompressor.rb +1 -1
- data/lib/net/ssh/transport/constants.rb +1 -1
- data/lib/net/ssh/transport/errors.rb +1 -1
- data/lib/net/ssh/transport/identity-cipher.rb +1 -1
- data/lib/net/ssh/transport/kex/dh-gex.rb +1 -1
- data/lib/net/ssh/transport/kex/dh.rb +1 -1
- data/lib/net/ssh/transport/kex/services.rb +1 -1
- data/lib/net/ssh/transport/ossl/buffer-factory.rb +1 -1
- data/lib/net/ssh/transport/ossl/buffer.rb +1 -1
- data/lib/net/ssh/transport/ossl/cipher-factory.rb +1 -1
- data/lib/net/ssh/transport/ossl/digest-factory.rb +1 -1
- data/lib/net/ssh/transport/ossl/hmac-factory.rb +1 -1
- data/lib/net/ssh/transport/ossl/hmac/hmac.rb +1 -1
- data/lib/net/ssh/transport/ossl/hmac/md5-96.rb +1 -1
- data/lib/net/ssh/transport/ossl/hmac/md5.rb +1 -1
- data/lib/net/ssh/transport/ossl/hmac/none.rb +1 -1
- data/lib/net/ssh/transport/ossl/hmac/services.rb +1 -1
- data/lib/net/ssh/transport/ossl/hmac/sha1-96.rb +1 -1
- data/lib/net/ssh/transport/ossl/hmac/sha1.rb +1 -1
- data/lib/net/ssh/transport/ossl/key-factory.rb +5 -2
- data/lib/net/ssh/transport/ossl/services.rb +1 -1
- data/lib/net/ssh/transport/packet-stream.rb +1 -1
- data/lib/net/ssh/transport/services.rb +1 -1
- data/lib/net/ssh/transport/session.rb +10 -1
- data/lib/net/ssh/transport/version-negotiator.rb +1 -1
- data/lib/net/ssh/userauth/agent.rb +1 -1
- data/lib/net/ssh/userauth/constants.rb +1 -1
- data/lib/net/ssh/userauth/driver.rb +1 -1
- data/lib/net/ssh/userauth/methods/hostbased.rb +1 -1
- data/lib/net/ssh/userauth/methods/keyboard-interactive.rb +104 -0
- data/lib/net/ssh/userauth/methods/password.rb +1 -1
- data/lib/net/ssh/userauth/methods/publickey.rb +1 -1
- data/lib/net/ssh/userauth/methods/services.rb +28 -6
- data/lib/net/ssh/userauth/services.rb +8 -5
- data/lib/net/ssh/userauth/userkeys.rb +1 -1
- data/lib/net/ssh/util/buffer.rb +1 -1
- data/lib/net/ssh/util/openssl.rb +1 -1
- data/lib/net/ssh/util/prompter.rb +1 -1
- data/lib/net/ssh/version.rb +2 -2
- data/test/ALL-TESTS.rb +1 -1
- data/test/connection/tc_channel.rb +1 -1
- data/test/connection/tc_driver.rb +1 -1
- data/test/connection/tc_integration.rb +1 -1
- data/test/proxy/tc_http.rb +1 -1
- data/test/proxy/tc_socks4.rb +1 -1
- data/test/proxy/tc_socks5.rb +1 -1
- data/test/service/forward/tc_driver.rb +1 -1
- data/test/service/forward/tc_local_network_handler.rb +1 -1
- data/test/service/forward/tc_remote_network_handler.rb +1 -1
- data/test/service/process/tc_driver.rb +1 -1
- data/test/service/process/tc_integration.rb +1 -1
- data/test/service/process/tc_open.rb +1 -1
- data/test/service/process/tc_popen3.rb +13 -13
- data/test/tc_integration.rb +1 -1
- data/test/transport/compress/tc_none_compress.rb +1 -1
- data/test/transport/compress/tc_none_decompress.rb +1 -1
- data/test/transport/compress/tc_zlib_compress.rb +1 -1
- data/test/transport/compress/tc_zlib_decompress.rb +1 -1
- data/test/transport/kex/tc_dh.rb +2 -1
- data/test/transport/kex/tc_dh_gex.rb +1 -1
- data/test/transport/ossl/hmac/tc_hmac.rb +1 -1
- data/test/transport/ossl/hmac/tc_md5.rb +1 -1
- data/test/transport/ossl/hmac/tc_md5_96.rb +1 -1
- data/test/transport/ossl/hmac/tc_none.rb +1 -1
- data/test/transport/ossl/hmac/tc_sha1.rb +1 -1
- data/test/transport/ossl/hmac/tc_sha1_96.rb +1 -1
- data/test/transport/ossl/tc_buffer.rb +1 -1
- data/test/transport/ossl/tc_buffer_factory.rb +1 -1
- data/test/transport/ossl/tc_cipher_factory.rb +1 -1
- data/test/transport/ossl/tc_digest_factory.rb +1 -1
- data/test/transport/ossl/tc_hmac_factory.rb +1 -1
- data/test/transport/ossl/tc_key_factory.rb +1 -1
- data/test/transport/tc_algorithm_negotiator.rb +1 -1
- data/test/transport/tc_identity_cipher.rb +1 -1
- data/test/transport/tc_integration.rb +1 -1
- data/test/transport/tc_packet_stream.rb +1 -1
- data/test/transport/tc_session.rb +1 -1
- data/test/transport/tc_version_negotiator.rb +1 -1
- data/test/userauth/methods/tc_hostbased.rb +1 -1
- data/test/userauth/methods/tc_password.rb +1 -1
- data/test/userauth/methods/tc_publickey.rb +1 -1
- data/test/userauth/tc_agent.rb +1 -1
- data/test/userauth/tc_driver.rb +1 -1
- data/test/userauth/tc_integration.rb +15 -1
- data/test/userauth/tc_userkeys.rb +1 -1
- data/test/util/tc_buffer.rb +5 -5
- metadata +26 -6
@@ -1,7 +1,7 @@
|
|
1
1
|
<html>
|
2
2
|
<head>
|
3
|
-
<title>Net::SSH Manual :: Chapter 5:
|
4
|
-
<link type="text/css" rel="stylesheet" href="manual.css" />
|
3
|
+
<title>Net::SSH Manual :: Chapter 5: User Shells</title>
|
4
|
+
<link type="text/css" rel="stylesheet" href="stylesheets/manual.css" />
|
5
5
|
</head>
|
6
6
|
|
7
7
|
<body>
|
@@ -14,8 +14,8 @@
|
|
14
14
|
</div>
|
15
15
|
</td><td valign='middle' align='right'>
|
16
16
|
<div class="info">
|
17
|
-
Net::SSH Version: <strong>0.
|
18
|
-
Manual Last Updated: <strong>
|
17
|
+
Net::SSH Version: <strong>0.9.0</strong><br />
|
18
|
+
Manual Last Updated: <strong>2005-01-11 21:39 GMT</strong>
|
19
19
|
</div>
|
20
20
|
</td></tr>
|
21
21
|
</table>
|
@@ -110,36 +110,56 @@
|
|
110
110
|
|
111
111
|
<li><strong>
|
112
112
|
<a href="chapter-5.html">
|
113
|
-
|
113
|
+
User Shells
|
114
114
|
</a>
|
115
115
|
</strong> <big>←</big>
|
116
116
|
<ol type="1">
|
117
117
|
|
118
118
|
<li><a href="chapter-5.html#s1">Introduction</a></li>
|
119
119
|
|
120
|
-
<li><a href="chapter-5.html#s2">
|
120
|
+
<li><a href="chapter-5.html#s2">Using Channels</a></li>
|
121
121
|
|
122
|
-
<li><a href="chapter-5.html#s3">
|
122
|
+
<li><a href="chapter-5.html#s3">Shell Service</a></li>
|
123
123
|
|
124
|
-
<li><a href="chapter-5.html#s4">
|
124
|
+
<li><a href="chapter-5.html#s4">SyncShell Service</a></li>
|
125
125
|
|
126
|
-
<li><a href="chapter-5.html#s5">
|
126
|
+
<li><a href="chapter-5.html#s5">Terminal Clients</a></li>
|
127
127
|
|
128
128
|
</ol>
|
129
129
|
</li>
|
130
130
|
|
131
131
|
<li>
|
132
132
|
<a href="chapter-6.html">
|
133
|
-
|
133
|
+
Port Forwarding
|
134
134
|
</a>
|
135
135
|
|
136
136
|
<ol type="1">
|
137
137
|
|
138
138
|
<li><a href="chapter-6.html#s1">Introduction</a></li>
|
139
139
|
|
140
|
-
<li><a href="chapter-6.html#s2"
|
140
|
+
<li><a href="chapter-6.html#s2">Local-to-Remote</a></li>
|
141
|
+
|
142
|
+
<li><a href="chapter-6.html#s3">Remote-to-Local</a></li>
|
143
|
+
|
144
|
+
<li><a href="chapter-6.html#s4">Direct Channels</a></li>
|
145
|
+
|
146
|
+
<li><a href="chapter-6.html#s5">Remote-to-Local Handlers</a></li>
|
147
|
+
|
148
|
+
</ol>
|
149
|
+
</li>
|
150
|
+
|
151
|
+
<li>
|
152
|
+
<a href="chapter-7.html">
|
153
|
+
Using Proxies
|
154
|
+
</a>
|
155
|
+
|
156
|
+
<ol type="1">
|
157
|
+
|
158
|
+
<li><a href="chapter-7.html#s1">Introduction</a></li>
|
159
|
+
|
160
|
+
<li><a href="chapter-7.html#s2"><span class="caps">HTTP</span></a></li>
|
141
161
|
|
142
|
-
<li><a href="chapter-
|
162
|
+
<li><a href="chapter-7.html#s3"><span class="caps">SOCKS</span></a></li>
|
143
163
|
|
144
164
|
</ol>
|
145
165
|
</li>
|
@@ -170,7 +190,17 @@
|
|
170
190
|
|
171
191
|
<div id="content">
|
172
192
|
|
173
|
-
|
193
|
+
<div class="top"><div class="prevnext">
|
194
|
+
|
195
|
+
<a href="chapter-4.html">Previous (4. Executing Commands)</a> |
|
196
|
+
|
197
|
+
<a href="index.html">Up</a>
|
198
|
+
|
199
|
+
| <a href="chapter-6.html">Next (6. Port Forwarding)</a>
|
200
|
+
|
201
|
+
</div></div>
|
202
|
+
|
203
|
+
<h1>5. User Shells</h1>
|
174
204
|
|
175
205
|
|
176
206
|
|
@@ -182,208 +212,290 @@
|
|
182
212
|
|
183
213
|
|
184
214
|
<div class="section">
|
185
|
-
<p>
|
186
|
-
<ol>
|
187
|
-
<li>A port on the local host is forwarded via the remote host to another machine. Any connection to the specified port will cause all subsequent data to be sent over the connection to the remote host, where it will then be forwarded to the requested destination host.</li>
|
188
|
-
<li>A port on the remote host is forwarded over the connection to the local host, and from there to (potentially) some other remote destination. Any connection to the specified port on the remote host is forwarded over the connection to the local host, which then makes a connection to the specified remote destination and sends the data there.</li>
|
189
|
-
</ol>
|
215
|
+
<p>A user’s <em>shell</em> is the environment in which commands are executed on a remote machine. There are a variety of different shells, including <a href="http://www.gnu.org/software/bash/bash.html">bash</a>, csh, tcsh, <a href="http://www.kornshell.com/">ksh</a>, and many others.</p>
|
190
216
|
|
191
|
-
<p>
|
217
|
+
<p>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.</p>
|
192
218
|
|
219
|
+
<p><span class="caps">SSH</span> 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, <span class="caps">SSH</span> supports pty’s (<em>pseudo-tty</em>’s, or terminals), which allow the shell to act as if it were running locally on the users own machine.</p>
|
193
220
|
|
194
|
-
<
|
195
|
-
Net::SSH.start( 'host' ) do |session|
|
196
|
-
forward = session.forward
|
197
|
-
...
|
198
|
-
session.loop
|
199
|
-
end
|
200
|
-
</pre>
|
201
|
-
<p>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 <span class="caps">SSH</span> lovely?)</p>
|
202
|
-
|
203
|
-
<p>Naturally, you can also have remote processes, <span class="caps">SFTP</span> sessions, and more all working at the same time on the connection.</p>
|
221
|
+
<p>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 <span class="caps">SSH</span>’s builtin shell support to execute the user’s preferred shell. This chapter will discuss this approach.</p>
|
204
222
|
</div>
|
205
223
|
|
206
224
|
|
207
225
|
|
208
226
|
<h2>
|
209
227
|
<a name="s2"></a>
|
210
|
-
5.2.
|
228
|
+
5.2. Using Channels
|
211
229
|
</h2>
|
212
230
|
|
213
231
|
|
214
232
|
|
215
233
|
<div class="section">
|
216
|
-
<p>
|
234
|
+
<p>At the lowest level, starting a shell is a matter of sending a “shell” request over a channel.</p>
|
235
|
+
|
236
|
+
<div class='figure'>
|
237
|
+
<span class='caption'>Sending a shell request [ruby]</span>
|
238
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="ident">host</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
|
239
|
+
|
240
|
+
<span class="ident">session</span><span class="punct">.</span><span class="ident">open_channel</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">channel</span><span class="punct">|</span>
|
241
|
+
|
242
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">on_success</span> <span class="keyword">do</span>
|
243
|
+
<span class="ident">puts</span> <span class="punct">"</span><span class="string">shell was started successfully!</span><span class="punct">"</span>
|
244
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">send_data</span> <span class="punct">"</span><span class="string">exit</span><span class="expr">\n</span><span class="punct">"</span> <span class="comment"># tell the shell to exit</span>
|
245
|
+
<span class="keyword">end</span>
|
246
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">on_failure</span> <span class="keyword">do</span>
|
247
|
+
<span class="ident">puts</span> <span class="punct">"</span><span class="string">shell could not be started!</span><span class="punct">"</span>
|
248
|
+
<span class="keyword">end</span>
|
249
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">on_data</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">ch</span><span class="punct">,</span><span class="ident">data</span><span class="punct">|</span>
|
250
|
+
<span class="ident">puts</span> <span class="punct">"</span><span class="string">recieved </span><span class="expr">#{data}</span><span class="string"> from shell</span><span class="punct">"</span>
|
251
|
+
<span class="keyword">end</span>
|
252
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">on_close</span> <span class="keyword">do</span>
|
253
|
+
<span class="ident">puts</span> <span class="punct">"</span><span class="string">shell terminated</span><span class="punct">"</span>
|
254
|
+
<span class="keyword">end</span>
|
255
|
+
|
256
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">send_request</span> <span class="punct">"</span><span class="string">shell</span><span class="punct">",</span> <span class="constant">nil</span><span class="punct">,</span> <span class="constant">true</span>
|
257
|
+
|
258
|
+
<span class="keyword">end</span>
|
259
|
+
|
260
|
+
<span class="ident">session</span><span class="punct">.</span><span class="ident">loop</span>
|
261
|
+
|
262
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
263
|
+
|
264
|
+
<p>The <code>#send_request</code> 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.</p>
|
265
|
+
|
266
|
+
<p>If you want to open a pty before starting the shell, you can use the #request_pty method of the channel:</p>
|
267
|
+
|
268
|
+
<div class='figure'>
|
269
|
+
<span class='caption'>Opening a pty on a channel [ruby]</span>
|
270
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="ident">host</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
|
271
|
+
|
272
|
+
<span class="ident">session</span><span class="punct">.</span><span class="ident">open_channel</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">channel</span><span class="punct">|</span>
|
217
273
|
|
274
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">on_success</span> <span class="keyword">do</span>
|
275
|
+
<span class="ident">puts</span> <span class="punct">"</span><span class="string">pty was requested successfully!</span><span class="punct">"</span>
|
218
276
|
|
219
|
-
<
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
end
|
224
|
-
</pre>
|
225
|
-
<p>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 <a href="http://www.google.com">Google</a>.</p>
|
277
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">on_success</span> <span class="keyword">do</span>
|
278
|
+
<span class="ident">puts</span> <span class="punct">"</span><span class="string">shell was started successfully!</span><span class="punct">"</span>
|
279
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">send_data</span> <span class="punct">"</span><span class="string">exit</span><span class="expr">\n</span><span class="punct">"</span> <span class="comment"># tell the shell to exit</span>
|
280
|
+
<span class="keyword">end</span>
|
226
281
|
|
227
|
-
|
282
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">send_request</span> <span class="punct">"</span><span class="string">shell</span><span class="punct">",</span> <span class="constant">nil</span><span class="punct">,</span> <span class="constant">true</span>
|
283
|
+
<span class="keyword">end</span>
|
228
284
|
|
285
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">on_failure</span> <span class="keyword">do</span>
|
286
|
+
<span class="ident">puts</span> <span class="punct">"</span><span class="string">shell could not be started!</span><span class="punct">"</span>
|
287
|
+
<span class="keyword">end</span>
|
288
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">on_data</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">ch</span><span class="punct">,</span><span class="ident">data</span><span class="punct">|</span>
|
289
|
+
<span class="ident">puts</span> <span class="punct">"</span><span class="string">recieved </span><span class="expr">#{data}</span><span class="string"> from shell</span><span class="punct">"</span>
|
290
|
+
<span class="keyword">end</span>
|
291
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">on_close</span> <span class="keyword">do</span>
|
292
|
+
<span class="ident">puts</span> <span class="punct">"</span><span class="string">shell terminated</span><span class="punct">"</span>
|
293
|
+
<span class="keyword">end</span>
|
229
294
|
|
230
|
-
<
|
231
|
-
|
232
|
-
</
|
233
|
-
|
295
|
+
<span class="ident">channel</span><span class="punct">.</span><span class="ident">request_pty</span> <span class="symbol">:want_reply</span> <span class="punct">=></span> <span class="constant">true</span>
|
296
|
+
|
297
|
+
<span class="keyword">end</span>
|
298
|
+
|
299
|
+
<span class="ident">session</span><span class="punct">.</span><span class="ident">loop</span>
|
300
|
+
|
301
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
302
|
+
|
303
|
+
<p>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.</p>
|
304
|
+
|
305
|
+
<p>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 <em>shell</em> and <em>sync</em> services.</p>
|
234
306
|
</div>
|
235
307
|
|
236
308
|
|
237
309
|
|
238
310
|
<h2>
|
239
311
|
<a name="s3"></a>
|
240
|
-
5.3.
|
312
|
+
5.3. Shell Service
|
241
313
|
</h2>
|
242
314
|
|
243
315
|
|
244
316
|
|
245
317
|
<div class="section">
|
246
|
-
<p>
|
318
|
+
<p>To make interacting with shells, simpler, version 0.9 of Net::SSH introduced the <em>shell service</em>. 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.</p>
|
319
|
+
|
320
|
+
<div class='figure'>
|
321
|
+
<span class='caption'>Using the shell service [ruby]</span>
|
322
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="punct">'</span><span class="string">localhost</span><span class="punct">'</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
|
323
|
+
|
324
|
+
<span class="ident">shell</span> <span class="punct">=</span> <span class="ident">session</span><span class="punct">.</span><span class="ident">shell</span><span class="punct">.</span><span class="ident">open</span>
|
325
|
+
|
326
|
+
<span class="comment"># script what we want to do</span>
|
327
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">pwd</span>
|
328
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">cd</span> <span class="punct">"</span><span class="string">/</span><span class="punct">"</span>
|
329
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">pwd</span>
|
330
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">test</span> <span class="punct">"</span><span class="string">-e foo</span><span class="punct">"</span>
|
331
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">cd</span> <span class="punct">"</span><span class="string">/really/bogus/directory</span><span class="punct">"</span>
|
332
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">send_data</span> <span class="punct">"</span><span class="string">/sbin/ifconfig</span><span class="expr">\n</span><span class="punct">"</span>
|
333
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">pwd</span>
|
334
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">ruby</span> <span class="punct">"</span><span class="string">-v</span><span class="punct">"</span>
|
335
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">cd</span> <span class="punct">"</span><span class="string">/usr/lib</span><span class="punct">"</span>
|
336
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">pwd</span>
|
337
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">exit</span>
|
338
|
+
|
339
|
+
<span class="comment"># give the above commands sufficient time to terminate</span>
|
340
|
+
<span class="ident">sleep</span> <span class="number">0.5</span>
|
247
341
|
|
342
|
+
<span class="comment"># display the output</span>
|
343
|
+
<span class="global">$stdout</span><span class="punct">.</span><span class="ident">print</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">stdout</span> <span class="keyword">while</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">stdout?</span>
|
344
|
+
<span class="global">$stderr</span><span class="punct">.</span><span class="ident">puts</span> <span class="punct">"</span><span class="string">-- stderr: --</span><span class="punct">"</span>
|
345
|
+
<span class="global">$stderr</span><span class="punct">.</span><span class="ident">print</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">stderr</span> <span class="keyword">while</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">stderr?</span>
|
248
346
|
|
249
|
-
<pre>
|
250
|
-
Net::SSH.start( 'host' ) do |session|
|
251
|
-
session.forward.remote_to( 80, 'www.google.com', 1234 )
|
252
|
-
session.loop
|
253
|
-
end
|
254
|
-
</pre>
|
255
|
-
<p>The above example causes any connection on port 1234 of the remote machine (<em>from</em> the remote machine) to be forwarded via the local host to port 80 at www.google.com. To make things a bit more open, you could specify a bind address of 0.0.0.0:</p>
|
347
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
256
348
|
|
349
|
+
<p>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 <code>#send_data</code> method (but remember to add a newline!). The <code>#send_data</code> method may also be used to send data to any process running in the shell as that process’ <code>stdin</code> stream.</p>
|
257
350
|
|
258
|
-
<
|
259
|
-
|
260
|
-
|
351
|
+
<p>You can also specify that a pty should be allocated for this shell:</p>
|
352
|
+
|
353
|
+
<div class='figure'>
|
354
|
+
<span class='caption'>Allocating a pty for the shell [ruby]</span>
|
355
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="punct">'</span><span class="string">localhost</span><span class="punct">'</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
|
356
|
+
|
357
|
+
<span class="ident">shell</span> <span class="punct">=</span> <span class="ident">session</span><span class="punct">.</span><span class="ident">shell</span><span class="punct">.</span><span class="ident">open</span><span class="punct">(</span> <span class="symbol">:pty</span> <span class="punct">=></span> <span class="constant">true</span> <span class="punct">)</span>
|
358
|
+
|
359
|
+
<span class="comment"># or</span>
|
360
|
+
|
361
|
+
<span class="ident">shell</span> <span class="punct">=</span> <span class="ident">session</span><span class="punct">.</span><span class="ident">shell</span><span class="punct">.</span><span class="ident">open</span><span class="punct">(</span> <span class="symbol">:pty</span> <span class="punct">=></span> <span class="punct">{</span> <span class="punct">...</span> <span class="punct">}</span> <span class="punct">)</span>
|
362
|
+
|
363
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
364
|
+
|
365
|
+
<p>If you give a hash for the <code>:pty</code> option, it must be a map of the options that describe the new pty. See the <span class="caps">API</span> documentation for the Channel#request_pty method for more information.</p>
|
366
|
+
|
367
|
+
<p>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.</p>
|
261
368
|
</div>
|
262
369
|
|
263
370
|
|
264
371
|
|
265
372
|
<h2>
|
266
373
|
<a name="s4"></a>
|
267
|
-
5.4.
|
374
|
+
5.4. SyncShell Service
|
268
375
|
</h2>
|
269
376
|
|
270
377
|
|
271
378
|
|
272
379
|
<div class="section">
|
273
|
-
<p>
|
274
|
-
|
275
|
-
<
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
channel.send_data "subsequent request"
|
316
|
-
end
|
317
|
-
|
318
|
-
def process( channel )
|
319
|
-
channel.send_data "initial request"
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
Net::SSH.start( 'host' ) do |session|
|
324
|
-
session.forward.direct_channel( 1234, 'somewhere.else.net',
|
325
|
-
4321, Handler.new )
|
326
|
-
|
327
|
-
session.loop
|
328
|
-
end
|
329
|
-
</pre>
|
330
|
-
<p>The local port number for <code>#direct_channel</code> has no real purpose, other than to report to the <span class="caps">SSH</span> server that the “virtual” connection occurred on that port.</p>
|
380
|
+
<p>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.</p>
|
381
|
+
|
382
|
+
<div class='figure'>
|
383
|
+
<span class='caption'>Using the SyncShell service [ruby]</span>
|
384
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="punct">'</span><span class="string">localhost</span><span class="punct">'</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
|
385
|
+
|
386
|
+
<span class="ident">shell</span> <span class="punct">=</span> <span class="ident">session</span><span class="punct">.</span><span class="ident">shell</span><span class="punct">.</span><span class="ident">sync</span>
|
387
|
+
|
388
|
+
<span class="ident">out</span> <span class="punct">=</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">pwd</span>
|
389
|
+
<span class="ident">p</span> <span class="ident">out</span><span class="punct">.</span><span class="ident">stdout</span>
|
390
|
+
|
391
|
+
<span class="ident">out</span> <span class="punct">=</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">test</span> <span class="punct">"</span><span class="string">-e foo</span><span class="punct">"</span>
|
392
|
+
<span class="ident">p</span> <span class="ident">out</span><span class="punct">.</span><span class="ident">status</span>
|
393
|
+
|
394
|
+
<span class="ident">out</span> <span class="punct">=</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">cd</span> <span class="punct">"</span><span class="string">/really/bogus/directory</span><span class="punct">"</span>
|
395
|
+
<span class="ident">p</span> <span class="ident">out</span><span class="punct">.</span><span class="ident">stderr</span>
|
396
|
+
<span class="ident">p</span> <span class="ident">out</span><span class="punct">.</span><span class="ident">status</span>
|
397
|
+
|
398
|
+
<span class="ident">out</span> <span class="punct">=</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">ruby</span> <span class="punct">"</span><span class="string">-v</span><span class="punct">"</span>
|
399
|
+
<span class="ident">p</span> <span class="ident">out</span><span class="punct">.</span><span class="ident">stdout</span>
|
400
|
+
|
401
|
+
<span class="ident">out</span> <span class="punct">=</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">cd</span> <span class="punct">"</span><span class="string">/usr/lib</span><span class="punct">"</span>
|
402
|
+
|
403
|
+
<span class="ident">out</span> <span class="punct">=</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">ls</span> <span class="punct">"</span><span class="string">-l</span><span class="punct">"</span>
|
404
|
+
<span class="ident">p</span> <span class="ident">out</span><span class="punct">.</span><span class="ident">stdout</span>
|
405
|
+
|
406
|
+
<span class="ident">out</span> <span class="punct">=</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">send_command</span><span class="punct">(</span> <span class="punct">"</span><span class="string">bc</span><span class="punct">",</span> <span class="punct"><<</span><span class="constant">CMD</span><span class="string"> )
|
407
|
+
5+5
|
408
|
+
10*2
|
409
|
+
scale=5
|
410
|
+
3/4
|
411
|
+
quit
|
412
|
+
</span><span class="constant">CMD</span>
|
413
|
+
<span class="ident">p</span> <span class="ident">out</span><span class="punct">.</span><span class="ident">stdout</span>
|
414
|
+
|
415
|
+
<span class="ident">p</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">exit</span>
|
416
|
+
|
417
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
418
|
+
|
419
|
+
<p>The result of executing each command is an object that encapsulates the <code>stdout</code> and <code>stderr</code> streams, and the exit status of the command.</p>
|
420
|
+
|
421
|
+
<p>To explicitly execute a command, use the <code>#send_command</code> instead of <code>#send_data</code>—otherwise, the command will be executed asynchronously, which is not what you want. Also, if you pass a second parameter to the <code>#send_command</code> method, it is interpreted as the <code>stdin</code> data to send to the new process.</p>
|
331
422
|
</div>
|
332
423
|
|
333
424
|
|
334
425
|
|
335
426
|
<h2>
|
336
427
|
<a name="s5"></a>
|
337
|
-
5.5.
|
428
|
+
5.5. Terminal Clients
|
338
429
|
</h2>
|
339
430
|
|
340
431
|
|
341
432
|
|
342
433
|
<div class="section">
|
343
|
-
<p>
|
344
|
-
|
345
|
-
<
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
434
|
+
<p>Using the shell service and pty’s, you can now create a simple <span class="caps">SSH</span> terminal client. (You’ll also want to download and install the <a href="http://arika.org/ruby/termios">ruby-termios</a> library so that your input is not interpreted in a linewise fashion.)</p>
|
435
|
+
|
436
|
+
<div class='figure'>
|
437
|
+
<span class='caption'>A simple SSH terminal client in Ruby [ruby]</span>
|
438
|
+
<div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">begin</span>
|
439
|
+
<span class="ident">require</span> <span class="punct">'</span><span class="string">termios</span><span class="punct">'</span>
|
440
|
+
<span class="keyword">rescue</span> <span class="constant">LoadError</span>
|
441
|
+
<span class="keyword">end</span>
|
442
|
+
|
443
|
+
<span class="keyword">def </span><span class="method">stdin_buffer</span><span class="punct">(</span> <span class="ident">enable</span> <span class="punct">)</span>
|
444
|
+
<span class="keyword">return</span> <span class="keyword">unless</span> <span class="keyword">defined?</span><span class="punct">(</span> <span class="constant">Termios</span> <span class="punct">)</span>
|
445
|
+
<span class="ident">attr</span> <span class="punct">=</span> <span class="constant">Termios</span><span class="punct">::</span><span class="ident">getattr</span><span class="punct">(</span> <span class="global">$stdin</span> <span class="punct">)</span>
|
446
|
+
<span class="keyword">if</span> <span class="ident">enable</span>
|
447
|
+
<span class="ident">attr</span><span class="punct">.</span><span class="ident">c_lflag</span> <span class="punct">|=</span> <span class="constant">Termios</span><span class="punct">::</span><span class="constant">ICANON</span> <span class="punct">|</span> <span class="constant">Termios</span><span class="punct">::</span><span class="constant">ECHO</span>
|
448
|
+
<span class="keyword">else</span>
|
449
|
+
<span class="ident">attr</span><span class="punct">.</span><span class="ident">c_lflag</span> <span class="punct">&=</span> ~<span class="punct">(</span><span class="constant">Termios</span><span class="punct">::</span><span class="constant">ICANON</span><span class="punct">|</span><span class="constant">Termios</span><span class="punct">::</span><span class="constant">ECHO</span><span class="punct">)</span>
|
450
|
+
<span class="keyword">end</span>
|
451
|
+
<span class="constant">Termios</span><span class="punct">::</span><span class="ident">setattr</span><span class="punct">(</span> <span class="global">$stdin</span><span class="punct">,</span> <span class="constant">Termios</span><span class="punct">::</span><span class="constant">TCSANOW</span><span class="punct">,</span> <span class="ident">attr</span> <span class="punct">)</span>
|
452
|
+
<span class="keyword">end</span>
|
453
|
+
|
454
|
+
<span class="ident">host</span> <span class="punct">=</span> <span class="constant">ARGV</span><span class="punct">.</span><span class="ident">shift</span> <span class="keyword">or</span> <span class="ident">abort</span> <span class="punct">"</span><span class="string">You must specify the [user@]host to connect to</span><span class="punct">"</span>
|
455
|
+
<span class="keyword">if</span> <span class="ident">host</span> <span class="punct">=~</span> <span class="punct">/</span><span class="regex">@</span><span class="punct">/</span>
|
456
|
+
<span class="ident">user</span><span class="punct">,</span> <span class="ident">host</span> <span class="punct">=</span> <span class="ident">host</span><span class="punct">.</span><span class="ident">match</span><span class="punct">(</span> <span class="punct">/</span><span class="regex">(.*?)@(.*)</span><span class="punct">/</span> <span class="punct">)[</span><span class="number">1</span><span class="punct">,</span><span class="number">2</span><span class="punct">]</span>
|
457
|
+
<span class="keyword">else</span>
|
458
|
+
<span class="ident">user</span> <span class="punct">=</span> <span class="constant">ENV</span><span class="punct">['</span><span class="string">USER</span><span class="punct">']</span> <span class="punct">||</span> <span class="constant">ENV</span><span class="punct">['</span><span class="string">USER_NAME</span><span class="punct">']</span>
|
459
|
+
<span class="keyword">end</span>
|
460
|
+
|
461
|
+
<span class="constant">Net</span><span class="punct">::</span><span class="constant">SSH</span><span class="punct">.</span><span class="ident">start</span><span class="punct">(</span> <span class="ident">host</span><span class="punct">,</span> <span class="ident">user</span> <span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">session</span><span class="punct">|</span>
|
462
|
+
|
463
|
+
<span class="keyword">begin</span>
|
464
|
+
<span class="ident">stdin_buffer</span> <span class="constant">false</span>
|
465
|
+
|
466
|
+
<span class="ident">shell</span> <span class="punct">=</span> <span class="ident">session</span><span class="punct">.</span><span class="ident">shell</span><span class="punct">.</span><span class="ident">open</span><span class="punct">(</span> <span class="symbol">:pty</span> <span class="punct">=></span> <span class="constant">true</span> <span class="punct">)</span>
|
467
|
+
|
468
|
+
<span class="ident">loop</span> <span class="keyword">do</span>
|
469
|
+
<span class="keyword">break</span> <span class="keyword">unless</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">open?</span>
|
470
|
+
<span class="keyword">if</span> <span class="constant">IO</span><span class="punct">.</span><span class="ident">select</span><span class="punct">([</span><span class="global">$stdin</span><span class="punct">],</span><span class="constant">nil</span><span class="punct">,</span><span class="constant">nil</span><span class="punct">,</span><span class="number">0.01</span><span class="punct">)</span>
|
471
|
+
<span class="ident">data</span> <span class="punct">=</span> <span class="global">$stdin</span><span class="punct">.</span><span class="ident">sysread</span><span class="punct">(</span><span class="number">1</span><span class="punct">)</span>
|
472
|
+
<span class="ident">shell</span><span class="punct">.</span><span class="ident">send_data</span> <span class="ident">data</span>
|
473
|
+
<span class="keyword">end</span>
|
474
|
+
|
475
|
+
<span class="global">$stdout</span><span class="punct">.</span><span class="ident">print</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">stdout</span> <span class="keyword">while</span> <span class="ident">shell</span><span class="punct">.</span><span class="ident">stdout?</span>
|
476
|
+
<span class="global">$stdout</span><span class="punct">.</span><span class="ident">flush</span>
|
477
|
+
<span class="keyword">end</span>
|
478
|
+
<span class="keyword">ensure</span>
|
479
|
+
<span class="ident">stdin_buffer</span> <span class="constant">true</span>
|
480
|
+
<span class="keyword">end</span>
|
481
|
+
|
482
|
+
<span class="keyword">end</span></pre></div></td></tr></table></div></div>
|
483
|
+
|
484
|
+
<p>The above code is also available as an example script in the Net::SSH distribution (<code>examples/ssh-client.rb</code>).</p>
|
383
485
|
</div>
|
384
486
|
|
385
487
|
|
386
488
|
|
489
|
+
<div class="bottom"><div class="prevnext">
|
490
|
+
|
491
|
+
<a href="chapter-4.html">Previous (4. Executing Commands)</a> |
|
492
|
+
|
493
|
+
<a href="index.html">Up</a>
|
494
|
+
|
495
|
+
| <a href="chapter-6.html">Next (6. Port Forwarding)</a>
|
496
|
+
|
497
|
+
</div></div>
|
498
|
+
|
387
499
|
|
388
500
|
</div>
|
389
501
|
|