summaryrefslogtreecommitdiff
path: root/classes/Net/SSH/Multi/SessionActions.html
blob: ad9a7b44b917c3487744cd036ef45c74363bf917 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang='en'>
  <head>
    <title>: Net::SSH::Multi::SessionActions [Control multiple Net::SSH connections via a single interface.]</title>
    <meta content='text/html; charset=utf-8' http-equiv='Content-Type'>
    <link href='../../../../rdoc-style.css' media='screen' rel='stylesheet' type='text/css'>
    <script type='text/javascript'>
      //<![CDATA[
        function popupCode(url) {
          window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
        }
        
        function toggleCode(id) {
          var code = document.getElementById(id)
        
          code.style.display = code.style.display != 'block' ? 'block' : 'none'
          return true
        }
        
        // Make codeblocks hidden by default
        document.writeln('<' + 'style type="text/css">.method .source pre { display: none }<\/style>')
      //]]>
    </script>
  </head>
  <body class='page'>
    <div class='class' id='wrapper'>
      <div class='header'>
        <h1 class='name'>
          <span class='type'>Module</span>
          Net::SSH::Multi::SessionActions
        </h1>
        <ol class='paths'>
          <li>
            <a href="../../../../files/lib/net/ssh/multi/session_actions_rb.html">lib/net/ssh/multi/session_actions.rb</a>
          </li>
        </ol>
      </div>
      <div id='content'>
        <div id='text'>
          <div id='description'>
            <p>
            This module represents the actions that are available on session
            collections. Any class that includes this module needs only provide a
            <tt>servers</tt> method that returns a list of <a
            href="Server.html">Net::SSH::Multi::Server</a> instances, and the rest just
            works. See <a href="Session.html">Net::SSH::Multi::Session</a> and <a
            href="Subsession.html">Net::SSH::Multi::Subsession</a> for consumers of
            this module.
            </p>
          </div>
          <div id='method-list'>
            <h2>Methods</h2>
            <h3>public instance</h3>
            <ol>
              <li><a href="#M000004">busy?</a></li>
              <li><a href="#M000003">connect!</a></li>
              <li><a href="#M000008">exec</a></li>
              <li><a href="#M000002">master</a></li>
              <li><a href="#M000007">open_channel</a></li>
              <li><a href="#M000006">send_global_request</a></li>
              <li><a href="#M000005">sessions</a></li>
            </ol>
          </div>
          <div id='section'>
            <div id='methods'>
              <h2>Public instance methods</h2>
              <div class='method public-instance' id='method-M000004'>
                <a name='M000004'>      </a>
                <div class='synopsis'>
                  <span class='name'>busy?</span>
                  <span class='arguments'>(include_invisible=false)</span>
                </div>
                <div class='description'>
                  <p>
                  Returns <tt>true</tt> if any server in the current container has an open <a
                  href="../../SSH.html">SSH</a> session that is currently processing any
                  channels. If <tt>include_invisible</tt> is <tt>false</tt> (the default)
                  then invisible channels (such as those created by port forwarding) will not
                  be counted; otherwise, they will be.
                  </p>
                </div>
                <div class='source'>
                  <a class='source-toggle' href='#' onclick="toggleCode('M000004-source'); return false">
                    [show source]
                  </a>
                  <pre id='M000004-source'>    <span class="ruby-comment cmt"># File lib/net/ssh/multi/session_actions.rb, line 29</span>&#x000A;29:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">busy?</span>(<span class="ruby-identifier">include_invisible</span>=<span class="ruby-keyword kw">false</span>)&#x000A;30:       <span class="ruby-identifier">servers</span>.<span class="ruby-identifier">any?</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">server</span><span class="ruby-operator">|</span> <span class="ruby-identifier">server</span>.<span class="ruby-identifier">busy?</span>(<span class="ruby-identifier">include_invisible</span>) }&#x000A;31:     <span class="ruby-keyword kw">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-M000003'>
                <a name='M000003'>      </a>
                <div class='synopsis'>
                  <span class='name'>connect!</span>
                  <span class='arguments'>()</span>
                </div>
                <div class='description'>
                  <p>
                  Connections are normally established lazily, as soon as they are needed.
                  This method forces all servers in the current container to have their
                  connections established immediately, blocking until the connections have
                  been made.
                  </p>
                </div>
                <div class='source'>
                  <a class='source-toggle' href='#' onclick="toggleCode('M000003-source'); return false">
                    [show source]
                  </a>
                  <pre id='M000003-source'>    <span class="ruby-comment cmt"># File lib/net/ssh/multi/session_actions.rb, line 20</span>&#x000A;20:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">connect!</span>&#x000A;21:       <span class="ruby-identifier">sessions</span>&#x000A;22:       <span class="ruby-keyword kw">self</span>&#x000A;23:     <span class="ruby-keyword kw">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-M000008'>
                <a name='M000008'>      </a>
                <div class='synopsis'>
                  <span class='name'>exec</span>
                  <span class='arguments'>(command, &amp;block)</span>
                </div>
                <div class='description'>
                  <p>
                  A convenience method for executing a command on multiple hosts and either
                  displaying or capturing the output. It opens a channel on all active
                  sessions (see <a href="SessionActions.html#M000007">open_channel</a> and
                  active_sessions), and then executes a command on each channel
                  (Net::SSH::Connection::Channel#exec).
                  </p>
                  <p>
                  If a block is given, it will be invoked whenever data is received across
                  the channel, with three arguments: the channel object, a symbol identifying
                  which output stream the data was received on (<tt>:stdout</tt> or
                  <tt>:stderr</tt>) and a string containing the data that was received:
                  </p>
                  <pre>session.exec(&quot;command&quot;) do |ch, stream, data|&#x000A;  puts &quot;[#{ch[:host]} : #{stream}] #{data}&quot;&#x000A;end</pre>
                  <p>
                  If no block is given, all output will be written to +$stdout+ or +$stderr+,
                  as appropriate.
                  </p>
                  <p>
                  Note that <a href="SessionActions.html#M000008">exec</a> will also capture
                  the exit status of the process in the <tt>:exit_status</tt> property of
                  each channel. Since <a href="SessionActions.html#M000008">exec</a> returns
                  all of the channels in a <a
                  href="Channel.html">Net::SSH::Multi::Channel</a> object, you can check for
                  the exit status like this:
                  </p>
                  <pre>channel = session.exec(&quot;command&quot;) { ... }&#x000A;channel.wait&#x000A;&#x000A;if channel.any? { |c| c[:exit_status] != 0 }&#x000A;  puts &quot;executing failed on at least one host!&quot;&#x000A;end</pre>
                </div>
                <div class='source'>
                  <a class='source-toggle' href='#' onclick="toggleCode('M000008-source'); return false">
                    [show source]
                  </a>
                  <pre id='M000008-source'>     <span class="ruby-comment cmt"># File lib/net/ssh/multi/session_actions.rb, line 119</span>&#x000A;119:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">exec</span>(<span class="ruby-identifier">command</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>)&#x000A;120:       <span class="ruby-identifier">open_channel</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">channel</span><span class="ruby-operator">|</span>&#x000A;121:         <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">exec</span>(<span class="ruby-identifier">command</span>) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">ch</span>, <span class="ruby-identifier">success</span><span class="ruby-operator">|</span>&#x000A;122:           <span class="ruby-identifier">raise</span> <span class="ruby-node">&quot;could not execute command: #{command.inspect} (#{ch[:host]})&quot;</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">success</span>&#x000A;123: &#x000A;124:           <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">on_data</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">ch</span>, <span class="ruby-identifier">data</span><span class="ruby-operator">|</span>&#x000A;125:             <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">block</span>&#x000A;126:               <span class="ruby-identifier">block</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">ch</span>, <span class="ruby-identifier">:stdout</span>, <span class="ruby-identifier">data</span>)&#x000A;127:             <span class="ruby-keyword kw">else</span>&#x000A;128:               <span class="ruby-identifier">data</span>.<span class="ruby-identifier">chomp</span>.<span class="ruby-identifier">each_line</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">line</span><span class="ruby-operator">|</span>&#x000A;129:                 <span class="ruby-identifier">$stdout</span>.<span class="ruby-identifier">puts</span>(<span class="ruby-node">&quot;[#{ch[:host]}] #{line}&quot;</span>)&#x000A;130:               <span class="ruby-keyword kw">end</span>&#x000A;131:             <span class="ruby-keyword kw">end</span>&#x000A;132:           <span class="ruby-keyword kw">end</span>&#x000A;133: &#x000A;134:           <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">on_extended_data</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">ch</span>, <span class="ruby-identifier">type</span>, <span class="ruby-identifier">data</span><span class="ruby-operator">|</span>&#x000A;135:             <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">block</span>&#x000A;136:               <span class="ruby-identifier">block</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">ch</span>, <span class="ruby-identifier">:stderr</span>, <span class="ruby-identifier">data</span>)&#x000A;137:             <span class="ruby-keyword kw">else</span>&#x000A;138:               <span class="ruby-identifier">data</span>.<span class="ruby-identifier">chomp</span>.<span class="ruby-identifier">each_line</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">line</span><span class="ruby-operator">|</span>&#x000A;139:                 <span class="ruby-identifier">$stderr</span>.<span class="ruby-identifier">puts</span>(<span class="ruby-node">&quot;[#{ch[:host]}] #{line}&quot;</span>)&#x000A;140:               <span class="ruby-keyword kw">end</span>&#x000A;141:             <span class="ruby-keyword kw">end</span>&#x000A;142:           <span class="ruby-keyword kw">end</span>&#x000A;143: &#x000A;144:           <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">on_request</span>(<span class="ruby-value str">&quot;exit-status&quot;</span>) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">ch</span>, <span class="ruby-identifier">data</span><span class="ruby-operator">|</span>&#x000A;145:             <span class="ruby-identifier">ch</span>[<span class="ruby-identifier">:exit_status</span>] = <span class="ruby-identifier">data</span>.<span class="ruby-identifier">read_long</span>&#x000A;146:           <span class="ruby-keyword kw">end</span>&#x000A;147:         <span class="ruby-keyword kw">end</span>&#x000A;148:       <span class="ruby-keyword kw">end</span>&#x000A;149:     <span class="ruby-keyword kw">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-M000002'>
                <a name='M000002'>      </a>
                <div class='synopsis'>
                  <span class='name'>master</span>
                  <span class='arguments'>()</span>
                </div>
                <div class='description'>
                  <p>
                  Returns the session that is the &#8220;master&#8221;. This defaults to
                  <tt>self</tt>, but classes that include this module may wish to change this
                  if they are subsessions that depend on a master session.
                  </p>
                </div>
                <div class='source'>
                  <a class='source-toggle' href='#' onclick="toggleCode('M000002-source'); return false">
                    [show source]
                  </a>
                  <pre id='M000002-source'>    <span class="ruby-comment cmt"># File lib/net/ssh/multi/session_actions.rb, line 12</span>&#x000A;12:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">master</span>&#x000A;13:       <span class="ruby-keyword kw">self</span>&#x000A;14:     <span class="ruby-keyword kw">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-M000007'>
                <a name='M000007'>      </a>
                <div class='synopsis'>
                  <span class='name'>open_channel</span>
                  <span class='arguments'>(type=&quot;session&quot;, *extra, &amp;on_confirm)</span>
                </div>
                <div class='description'>
                  <p>
                  Asks all sessions for all contained servers (see <a
                  href="SessionActions.html#M000005">sessions</a>) to open a new channel.
                  When each server responds, the <tt>on_confirm</tt> block will be invoked
                  with a single argument, the channel object for that server. This means that
                  the block will be invoked one time for each session.
                  </p>
                  <p>
                  All new channels will be collected and returned, aggregated into a new <a
                  href="Channel.html">Net::SSH::Multi::Channel</a> instance.
                  </p>
                  <p>
                  Note that the channels are &#8220;enhanced&#8221; slightly&#8212;they have
                  two properties set on them automatically, to make dealing with them in a
                  multi-session environment slightly easier:
                  </p>
                  <ul>
                  <li>:server => the <a href="Server.html">Net::SSH::Multi::Server</a> instance
                  that spawned the channel
                  
                  </li>
                  <li>:host => the host name of the server
                  
                  </li>
                  </ul>
                  <p>
                  Having access to these things lets you more easily report which host (e.g.)
                  data was received from:
                  </p>
                  <pre>session.open_channel do |channel|&#x000A;  channel.exec &quot;command&quot; do |ch, success|&#x000A;    ch.on_data do |ch, data|&#x000A;      puts &quot;got data #{data} from #{ch[:host]}&quot;&#x000A;    end&#x000A;  end&#x000A;end</pre>
                </div>
                <div class='source'>
                  <a class='source-toggle' href='#' onclick="toggleCode('M000007-source'); return false">
                    [show source]
                  </a>
                  <pre id='M000007-source'>    <span class="ruby-comment cmt"># File lib/net/ssh/multi/session_actions.rb, line 80</span>&#x000A;80:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">open_channel</span>(<span class="ruby-identifier">type</span>=<span class="ruby-value str">&quot;session&quot;</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">extra</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">on_confirm</span>)&#x000A;81:       <span class="ruby-identifier">channels</span> = <span class="ruby-identifier">sessions</span>.<span class="ruby-identifier">map</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">ssh</span><span class="ruby-operator">|</span>&#x000A;82:         <span class="ruby-identifier">ssh</span>.<span class="ruby-identifier">open_channel</span>(<span class="ruby-identifier">type</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">extra</span>) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">c</span><span class="ruby-operator">|</span>&#x000A;83:           <span class="ruby-identifier">c</span>[<span class="ruby-identifier">:server</span>] = <span class="ruby-identifier">c</span>.<span class="ruby-identifier">connection</span>[<span class="ruby-identifier">:server</span>]&#x000A;84:           <span class="ruby-identifier">c</span>[<span class="ruby-identifier">:host</span>] = <span class="ruby-identifier">c</span>.<span class="ruby-identifier">connection</span>[<span class="ruby-identifier">:server</span>].<span class="ruby-identifier">host</span>&#x000A;85:           <span class="ruby-identifier">on_confirm</span>[<span class="ruby-identifier">c</span>] <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">on_confirm</span>&#x000A;86:         <span class="ruby-keyword kw">end</span>&#x000A;87:       <span class="ruby-keyword kw">end</span>&#x000A;88:       <span class="ruby-constant">Multi</span><span class="ruby-operator">::</span><span class="ruby-constant">Channel</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">master</span>, <span class="ruby-identifier">channels</span>)&#x000A;89:     <span class="ruby-keyword kw">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-M000006'>
                <a name='M000006'>      </a>
                <div class='synopsis'>
                  <span class='name'>send_global_request</span>
                  <span class='arguments'>(type, *extra, &amp;callback)</span>
                </div>
                <div class='description'>
                  <p>
                  Sends a global request to the sessions for all contained servers (see <a
                  href="SessionActions.html#M000005">sessions</a>). This can be used to
                  (e.g.) ping the remote servers to prevent them from timing out.
                  </p>
                  <pre>session.send_global_request(&quot;keep-alive@openssh.com&quot;)</pre>
                  <p>
                  If a block is given, it will be invoked when the server responds, with two
                  arguments: the <a href="../../SSH.html">Net::SSH</a> connection that is
                  responding, and a boolean indicating whether the request succeeded or not.
                  </p>
                </div>
                <div class='source'>
                  <a class='source-toggle' href='#' onclick="toggleCode('M000006-source'); return false">
                    [show source]
                  </a>
                  <pre id='M000006-source'>    <span class="ruby-comment cmt"># File lib/net/ssh/multi/session_actions.rb, line 50</span>&#x000A;50:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">send_global_request</span>(<span class="ruby-identifier">type</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">extra</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">callback</span>)&#x000A;51:       <span class="ruby-identifier">sessions</span>.<span class="ruby-identifier">each</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">ssh</span><span class="ruby-operator">|</span> <span class="ruby-identifier">ssh</span>.<span class="ruby-identifier">send_global_request</span>(<span class="ruby-identifier">type</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">extra</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">callback</span>) }&#x000A;52:       <span class="ruby-keyword kw">self</span>&#x000A;53:     <span class="ruby-keyword kw">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-M000005'>
                <a name='M000005'>      </a>
                <div class='synopsis'>
                  <span class='name'>sessions</span>
                  <span class='arguments'>()</span>
                </div>
                <div class='description'>
                  <p>
                  Returns an array of all <a href="../../SSH.html">SSH</a> sessions, blocking
                  until all sessions have connected.
                  </p>
                </div>
                <div class='source'>
                  <a class='source-toggle' href='#' onclick="toggleCode('M000005-source'); return false">
                    [show source]
                  </a>
                  <pre id='M000005-source'>    <span class="ruby-comment cmt"># File lib/net/ssh/multi/session_actions.rb, line 35</span>&#x000A;35:     <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">sessions</span>&#x000A;36:       <span class="ruby-identifier">threads</span> = <span class="ruby-identifier">servers</span>.<span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">server</span><span class="ruby-operator">|</span> <span class="ruby-constant">Thread</span>.<span class="ruby-identifier">new</span> { <span class="ruby-identifier">server</span>.<span class="ruby-identifier">session</span>(<span class="ruby-keyword kw">true</span>) } <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">server</span>.<span class="ruby-identifier">session</span>.<span class="ruby-identifier">nil?</span> }&#x000A;37:       <span class="ruby-identifier">threads</span>.<span class="ruby-identifier">each</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">thread</span><span class="ruby-operator">|</span> <span class="ruby-identifier">thread</span>.<span class="ruby-identifier">join</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">thread</span> }&#x000A;38:       <span class="ruby-identifier">servers</span>.<span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">server</span><span class="ruby-operator">|</span> <span class="ruby-identifier">server</span>.<span class="ruby-identifier">session</span> }.<span class="ruby-identifier">compact</span>&#x000A;39:     <span class="ruby-keyword kw">end</span></pre>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div id='footer-push'></div>
    </div>
    <div id='footer'>
      <a href="http://github.com/mislav/hanna/tree/master"><strong>Hanna</strong> RDoc template</a>
    </div>
  </body>
</html>