summaryrefslogtreecommitdiff
path: root/classes/Net/SSH/Multi/Session.html
diff options
context:
space:
mode:
Diffstat (limited to 'classes/Net/SSH/Multi/Session.html')
-rw-r--r--classes/Net/SSH/Multi/Session.html560
1 files changed, 560 insertions, 0 deletions
diff --git a/classes/Net/SSH/Multi/Session.html b/classes/Net/SSH/Multi/Session.html
new file mode 100644
index 0000000..e0ba392
--- /dev/null
+++ b/classes/Net/SSH/Multi/Session.html
@@ -0,0 +1,560 @@
+<!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::Session [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'>Class</span>
+ Net::SSH::Multi::Session
+ </h1>
+ <ol class='paths'>
+ <li>
+ <a href="../../../../files/lib/net/ssh/multi/session_rb.html">lib/net/ssh/multi/session.rb</a>
+ </li>
+ </ol>
+ <div class='parent'>
+ Parent:
+ <strong>Object</strong>
+ </div>
+ </div>
+ <div id='content'>
+ <div id='text'>
+ <div id='description'>
+ <p>
+ Represents a collection of connections to various servers. It provides an
+ interface for organizing the connections (<a
+ href="Session.html#M000067">group</a>), as well as a way to scope commands
+ to a subset of all connections (<a href="Session.html#M000072">with</a>).
+ You can also provide a default gateway connection that servers should use
+ when connecting (<a href="Session.html#M000068">via</a>). It exposes an
+ interface similar to Net::SSH::Connection::Session for opening <a
+ href="../../SSH.html">SSH</a> channels and executing commands, allowing for
+ these operations to be done in parallel across multiple connections.
+ </p>
+ <pre>Net::SSH::Multi.start do |session|&#x000A; # access servers via a gateway&#x000A; session.via 'gateway', 'gateway-user'&#x000A;&#x000A; # define the servers we want to use&#x000A; session.use 'user1@host1'&#x000A; session.use 'user2@host2'&#x000A;&#x000A; # define servers in groups for more granular access&#x000A; session.group :app do&#x000A; session.use 'user@app1'&#x000A; session.use 'user@app2'&#x000A; end&#x000A;&#x000A; # execute commands on all servers&#x000A; session.exec &quot;uptime&quot;&#x000A;&#x000A; # execute commands on a subset of servers&#x000A; session.with(:app).exec &quot;hostname&quot;&#x000A;&#x000A; # run the aggregated event loop&#x000A; session.loop&#x000A;end</pre>
+ <p>
+ Note that connections are established lazily, as soon as they are needed.
+ You can force the connections to be opened immediately, though, using the
+ connect! method.
+ </p>
+ <h2>Concurrent Connection Limiting</h2>
+ <p>
+ Sometimes you may be dealing with a large number of servers, and if you try
+ to have connections open to all of them simultaneously you&#8217;ll run
+ into open file handle limitations and such. If this happens to you, you can
+ set the concurrent_connections property of the session. <a
+ href="../Multi.html">Net::SSH::Multi</a> will then ensure that no more than
+ this number of connections are ever open simultaneously.
+ </p>
+ <pre>Net::SSH::Multi.start(:concurrent_connections =&gt; 5) do |session|&#x000A; # ...&#x000A;end</pre>
+ <p>
+ Opening channels and executing commands will still work exactly as before,
+ but <a href="../Multi.html">Net::SSH::Multi</a> will transparently close
+ finished connections and open pending ones.
+ </p>
+ <h2>Controlling Connection Errors</h2>
+ <p>
+ By default, <a href="../Multi.html">Net::SSH::Multi</a> will raise an
+ exception if a connection error occurs when connecting to a server. This
+ will typically bubble up and abort the entire connection process.
+ Sometimes, however, you might wish to ignore connection errors, for
+ instance when starting a daemon on a large number of boxes and you know
+ that some of the boxes are going to be unavailable.
+ </p>
+ <p>
+ To do this, simply set the on_error property of the session to :ignore (or
+ to :warn, if you want a warning message when a connection attempt fails):
+ </p>
+ <pre>Net::SSH::Multi.start(:on_error =&gt; :ignore) do |session|&#x000A; # ...&#x000A;end</pre>
+ <p>
+ The default is :fail, which causes the exception to bubble up.
+ Additionally, you can specify a Proc object as the value for on_error,
+ which will be invoked with the server in question if the connection attempt
+ fails. You can force the connection attempt to retry by throwing the :go
+ symbol, with :retry as the payload, or force the exception to be reraised
+ by throwing :go with :raise as the payload:
+ </p>
+ <pre>handler = Proc.new do |server|&#x000A; server[:connection_attempts] ||= 0&#x000A; if server[:connection_attempts] &lt; 3&#x000A; server[:connection_attempts] += 1&#x000A; throw :go, :retry&#x000A; else&#x000A; throw :go, :raise&#x000A; end&#x000A;end&#x000A;&#x000A;Net::SSH::Multi.start(:on_error =&gt; handler) do |session|&#x000A; # ...&#x000A;end</pre>
+ <p>
+ Any other thrown value (or no thrown value at all) will result in the
+ failure being ignored.
+ </p>
+ <h2>Lazily Evaluated <a href="Server.html">Server</a> Definitions</h2>
+ <p>
+ Sometimes you might be dealing with an environment where you don&#8217;t
+ know the names or addresses of the servers until runtime. You can certainly
+ dynamically build server names and pass them to <a
+ href="Session.html#M000069">use</a>, but if the operation to determine the
+ server names is expensive, you might want to defer it until the server is
+ actually needed (especially if the logic of your program is such that you
+ might not even need to connect to that server every time the program runs).
+ </p>
+ <p>
+ You can do this by passing a block to <a
+ href="Session.html#M000069">use</a>:
+ </p>
+ <pre>session.use do |opt|&#x000A; lookup_ip_address_of_remote_host&#x000A;end</pre>
+ <p>
+ See <a href="Session.html#M000069">use</a> for more information about this
+ usage.
+ </p>
+ </div>
+ <div id='method-list'>
+ <h2>Methods</h2>
+ <h3>public class</h3>
+ <ol>
+ <li><a href="#M000066">new</a></li>
+ </ol>
+ <h3>public instance</h3>
+ <ol>
+ <li><a href="#M000074">close</a></li>
+ <li><a href="#M000067">group</a></li>
+ <li><a href="#M000075">loop</a></li>
+ <li><a href="#M000076">loop_forever</a></li>
+ <li><a href="#M000073">on</a></li>
+ <li><a href="#M000077">process</a></li>
+ <li><a href="#M000070">servers</a></li>
+ <li><a href="#M000071">servers_for</a></li>
+ <li><a href="#M000069">use</a></li>
+ <li><a href="#M000068">via</a></li>
+ <li><a href="#M000072">with</a></li>
+ </ol>
+ </div>
+ <div id='context'>
+ <div id='includes'>
+ <h2>Included modules</h2>
+ <ol>
+ <li><a href="SessionActions.html">SessionActions</a></li>
+ </ol>
+ </div>
+ </div>
+ <div id='section'>
+ <div id='attribute-list'>
+ <h2 class='section-bar'>Attributes</h2>
+ <div class='name-list'>
+ <table>
+ <tr class='top-aligned-row context-row'>
+ <td class='context-item-name'>concurrent_connections</td>
+ <td class='context-item-value'>[RW]</td>
+ <td class='context-item-desc'>
+
+ The number of allowed concurrent connections. No more than this number of
+ sessions will be open at any given time.
+ </td>
+ </tr>
+ <tr class='top-aligned-row context-row'>
+ <td class='context-item-name'>default_gateway</td>
+ <td class='context-item-value'>[R]</td>
+ <td class='context-item-desc'>
+
+ The default Net::SSH::Gateway instance to use to connect to the servers. If
+ <tt>nil</tt>, no default gateway will be used.
+ </td>
+ </tr>
+ <tr class='top-aligned-row context-row'>
+ <td class='context-item-name'>default_user</td>
+ <td class='context-item-value'>[RW]</td>
+ <td class='context-item-desc'>
+
+ The default user name to use when connecting to a server. If a user name is
+ not given for a particular server, this value will be used. It defaults to
+ ENV[&#8216;USER&#8217;] || ENV[&#8216;USERNAME&#8217;], or
+ &#8220;unknown&#8221; if neither of those are set.
+ </td>
+ </tr>
+ <tr class='top-aligned-row context-row'>
+ <td class='context-item-name'>groups</td>
+ <td class='context-item-value'>[R]</td>
+ <td class='context-item-desc'>
+
+ The hash of group definitions, mapping each group name to a corresponding
+ <a href="ServerList.html">Net::SSH::Multi::ServerList</a>.
+ </td>
+ </tr>
+ <tr class='top-aligned-row context-row'>
+ <td class='context-item-name'>on_error</td>
+ <td class='context-item-value'>[RW]</td>
+ <td class='context-item-desc'>
+
+ How connection errors should be handled. This defaults to :fail, but may be
+ set to :ignore if connection errors should be ignored, or :warn if
+ connection errors should cause a warning.
+ </td>
+ </tr>
+ <tr class='top-aligned-row context-row'>
+ <td class='context-item-name'>server_list</td>
+ <td class='context-item-value'>[R]</td>
+ <td class='context-item-desc'>
+
+ The <a href="ServerList.html">Net::SSH::Multi::ServerList</a> managed by
+ this session.
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ <div id='methods'>
+ <h2>Public class methods</h2>
+ <div class='method public-class' id='method-M000066'>
+ <a name='M000066'> </a>
+ <div class='synopsis'>
+ <span class='name'>new</span>
+ <span class='arguments'>(options={})</span>
+ </div>
+ <div class='description'>
+ <p>
+ Creates a new <a href="Session.html">Net::SSH::Multi::Session</a> instance.
+ Initially, it contains no server definitions, no group definitions, and no
+ default gateway.
+ </p>
+ <p>
+ You can set the concurrent_connections property in the options. Setting it
+ to <tt>nil</tt> (the default) will cause <a
+ href="../Multi.html">Net::SSH::Multi</a> to ignore any concurrent
+ connection limit and allow all defined sessions to be open simultaneously.
+ Setting it to an integer will cause <a
+ href="../Multi.html">Net::SSH::Multi</a> to allow no more than that number
+ of concurrently open sessions, opening subsequent sessions only when other
+ sessions finish and close.
+ </p>
+ <pre>Net::SSH::Multi.start(:concurrent_connections =&gt; 10) do |session|&#x000A; session.use ...&#x000A;end</pre>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000066-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000066-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 171</span>&#x000A;171: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">options</span>={})&#x000A;172: <span class="ruby-ivar">@server_list</span> = <span class="ruby-constant">ServerList</span>.<span class="ruby-identifier">new</span>&#x000A;173: <span class="ruby-ivar">@groups</span> = <span class="ruby-constant">Hash</span>.<span class="ruby-identifier">new</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">h</span>,<span class="ruby-identifier">k</span><span class="ruby-operator">|</span> <span class="ruby-identifier">h</span>[<span class="ruby-identifier">k</span>] = <span class="ruby-constant">ServerList</span>.<span class="ruby-identifier">new</span> }&#x000A;174: <span class="ruby-ivar">@gateway</span> = <span class="ruby-keyword kw">nil</span>&#x000A;175: <span class="ruby-ivar">@open_groups</span> = []&#x000A;176: <span class="ruby-ivar">@connect_threads</span> = []&#x000A;177: <span class="ruby-ivar">@on_error</span> = <span class="ruby-identifier">:fail</span>&#x000A;178: <span class="ruby-ivar">@default_user</span> = <span class="ruby-constant">ENV</span>[<span class="ruby-value str">'USER'</span>] <span class="ruby-operator">||</span> <span class="ruby-constant">ENV</span>[<span class="ruby-value str">'USERNAME'</span>] <span class="ruby-operator">||</span> <span class="ruby-value str">&quot;unknown&quot;</span>&#x000A;179: &#x000A;180: <span class="ruby-ivar">@open_connections</span> = <span class="ruby-value">0</span>&#x000A;181: <span class="ruby-ivar">@pending_sessions</span> = []&#x000A;182: <span class="ruby-ivar">@session_mutex</span> = <span class="ruby-constant">Mutex</span>.<span class="ruby-identifier">new</span>&#x000A;183: &#x000A;184: <span class="ruby-identifier">options</span>.<span class="ruby-identifier">each</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">opt</span>, <span class="ruby-identifier">value</span><span class="ruby-operator">|</span> <span class="ruby-identifier">send</span>(<span class="ruby-node">&quot;#{opt}=&quot;</span>, <span class="ruby-identifier">value</span>) }&#x000A;185: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <h2>Public instance methods</h2>
+ <div class='method public-instance' id='method-M000074'>
+ <a name='M000074'> </a>
+ <div class='synopsis'>
+ <span class='name'>close</span>
+ <span class='arguments'>()</span>
+ </div>
+ <div class='description'>
+ <p>
+ Closes the multi-session by shutting down all open server sessions, and the
+ default gateway (if one was specified using <a
+ href="Session.html#M000068">via</a>). Note that other gateway connections
+ (e.g., those passed to <a href="Session.html#M000069">use</a> directly)
+ will <em>not</em> be closed by this method, and must be managed externally.
+ </p>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000074-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000074-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 402</span>&#x000A;402: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">close</span>&#x000A;403: <span class="ruby-identifier">server_list</span>.<span class="ruby-identifier">each</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">close_channels</span> }&#x000A;404: <span class="ruby-identifier">loop</span>(<span class="ruby-value">0</span>) { <span class="ruby-identifier">busy?</span>(<span class="ruby-keyword kw">true</span>) }&#x000A;405: <span class="ruby-identifier">server_list</span>.<span class="ruby-identifier">each</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">close</span> }&#x000A;406: <span class="ruby-identifier">default_gateway</span>.<span class="ruby-identifier">shutdown!</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">default_gateway</span>&#x000A;407: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000067'>
+ <a name='M000067'> </a>
+ <div class='synopsis'>
+ <span class='name'>group</span>
+ <span class='arguments'>(*args) {|self| ...}</span>
+ </div>
+ <div class='description'>
+ <p>
+ At its simplest, this associates a named group with a server definition. It
+ can be used in either of two ways:
+ </p>
+ <p>
+ First, you can use it to associate a group (or array of groups) with a
+ server definition (or array of server definitions). The server definitions
+ must already exist in the server_list array (typically by calling <a
+ href="Session.html#M000069">use</a>):
+ </p>
+ <pre>server1 = session.use('host1', 'user1')&#x000A;server2 = session.use('host2', 'user2')&#x000A;session.group :app =&gt; server1, :web =&gt; server2&#x000A;session.group :staging =&gt; [server1, server2]&#x000A;session.group %w(xen linux) =&gt; server2&#x000A;session.group %w(rackspace backup) =&gt; [server1, server2]</pre>
+ <p>
+ Secondly, instead of a mapping of groups to servers, you can just provide a
+ list of group names, and then a block. Inside the block, any calls to <a
+ href="Session.html#M000069">use</a> will automatically associate the new
+ server definition with those groups. You can nest <a
+ href="Session.html#M000067">group</a> calls, too, which will aggregate the
+ group definitions.
+ </p>
+ <pre>session.group :rackspace, :backup do&#x000A; session.use 'host1', 'user1'&#x000A; session.group :xen do&#x000A; session.use 'host2', 'user2'&#x000A; end&#x000A;end</pre>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000067-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000067-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 213</span>&#x000A;213: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">group</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">args</span>)&#x000A;214: <span class="ruby-identifier">mapping</span> = <span class="ruby-identifier">args</span>.<span class="ruby-identifier">last</span>.<span class="ruby-identifier">is_a?</span>(<span class="ruby-constant">Hash</span>) <span class="ruby-operator">?</span> <span class="ruby-identifier">args</span>.<span class="ruby-identifier">pop</span> <span class="ruby-operator">:</span> {}&#x000A;215: &#x000A;216: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">mapping</span>.<span class="ruby-identifier">any?</span> <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-identifier">block_given?</span>&#x000A;217: <span class="ruby-identifier">raise</span> <span class="ruby-constant">ArgumentError</span>, <span class="ruby-value str">&quot;must provide group mapping OR block, not both&quot;</span>&#x000A;218: <span class="ruby-keyword kw">elsif</span> <span class="ruby-identifier">block_given?</span>&#x000A;219: <span class="ruby-keyword kw">begin</span>&#x000A;220: <span class="ruby-identifier">saved_groups</span> = <span class="ruby-identifier">open_groups</span>.<span class="ruby-identifier">dup</span>&#x000A;221: <span class="ruby-identifier">open_groups</span>.<span class="ruby-identifier">concat</span>(<span class="ruby-identifier">args</span>.<span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">a</span><span class="ruby-operator">|</span> <span class="ruby-identifier">a</span>.<span class="ruby-identifier">to_sym</span> }).<span class="ruby-identifier">uniq!</span>&#x000A;222: <span class="ruby-keyword kw">yield</span> <span class="ruby-keyword kw">self</span>&#x000A;223: <span class="ruby-keyword kw">ensure</span>&#x000A;224: <span class="ruby-identifier">open_groups</span>.<span class="ruby-identifier">replace</span>(<span class="ruby-identifier">saved_groups</span>)&#x000A;225: <span class="ruby-keyword kw">end</span>&#x000A;226: <span class="ruby-keyword kw">else</span>&#x000A;227: <span class="ruby-identifier">mapping</span>.<span class="ruby-identifier">each</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">key</span>, <span class="ruby-identifier">value</span><span class="ruby-operator">|</span>&#x000A;228: (<span class="ruby-identifier">open_groups</span> <span class="ruby-operator">+</span> <span class="ruby-constant">Array</span>(<span class="ruby-identifier">key</span>)).<span class="ruby-identifier">uniq</span>.<span class="ruby-identifier">each</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">grp</span><span class="ruby-operator">|</span>&#x000A;229: <span class="ruby-identifier">groups</span>[<span class="ruby-identifier">grp</span>.<span class="ruby-identifier">to_sym</span>].<span class="ruby-identifier">concat</span>(<span class="ruby-constant">Array</span>(<span class="ruby-identifier">value</span>))&#x000A;230: <span class="ruby-keyword kw">end</span>&#x000A;231: <span class="ruby-keyword kw">end</span>&#x000A;232: <span class="ruby-keyword kw">end</span>&#x000A;233: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000075'>
+ <a name='M000075'> </a>
+ <div class='synopsis'>
+ <span class='name'>loop</span>
+ <span class='arguments'>(wait=nil, &amp;block)</span>
+ </div>
+ <div class='description'>
+ <p>
+ Run the aggregated event loop for all open server sessions, until the given
+ block returns <tt>false</tt>. If no block is given, the loop will run for
+ as long as busy? returns <tt>true</tt> (in other words, for as long as
+ there are any (non-invisible) channels open).
+ </p>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000075-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000075-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 415</span>&#x000A;415: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">loop</span>(<span class="ruby-identifier">wait</span>=<span class="ruby-keyword kw">nil</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>)&#x000A;416: <span class="ruby-identifier">running</span> = <span class="ruby-identifier">block</span> <span class="ruby-operator">||</span> <span class="ruby-constant">Proc</span>.<span class="ruby-identifier">new</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">c</span><span class="ruby-operator">|</span> <span class="ruby-identifier">busy?</span> }&#x000A;417: <span class="ruby-identifier">loop_forever</span> { <span class="ruby-keyword kw">break</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">process</span>(<span class="ruby-identifier">wait</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">running</span>) }&#x000A;418: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000076'>
+ <a name='M000076'> </a>
+ <div class='synopsis'>
+ <span class='name'>loop_forever</span>
+ <span class='arguments'>(wait=nil, &amp;block)</span>
+ </div>
+ <div class='description'>
+ <p>
+ Alias for <a href="Session.html#M000075">loop</a>
+ </p>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000073'>
+ <a name='M000073'> </a>
+ <div class='synopsis'>
+ <span class='name'>on</span>
+ <span class='arguments'>(*servers) {|subsession if block_given?| ...}</span>
+ </div>
+ <div class='description'>
+ <p>
+ Works as <a href="Session.html#M000072">with</a>, but for specific servers
+ rather than groups. It will return a new subsession (<a
+ href="Subsession.html">Net::SSH::Multi::Subsession</a>) consisting of the
+ given servers. (Note that it requires that the servers in question have
+ been created via calls to <a href="Session.html#M000069">use</a> on this
+ session object, or things will not work quite right.) If a block is given,
+ the new subsession will also be yielded to the block.
+ </p>
+ <pre>srv1 = session.use('host1', 'user')&#x000A;srv2 = session.use('host2', 'user')&#x000A;# ...&#x000A;session.on(srv1, srv2).exec('hostname')</pre>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000073-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000073-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 392</span>&#x000A;392: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">on</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">servers</span>)&#x000A;393: <span class="ruby-identifier">subsession</span> = <span class="ruby-constant">Subsession</span>.<span class="ruby-identifier">new</span>(<span class="ruby-keyword kw">self</span>, <span class="ruby-identifier">servers</span>)&#x000A;394: <span class="ruby-keyword kw">yield</span> <span class="ruby-identifier">subsession</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">block_given?</span>&#x000A;395: <span class="ruby-identifier">subsession</span>&#x000A;396: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000077'>
+ <a name='M000077'> </a>
+ <div class='synopsis'>
+ <span class='name'>process</span>
+ <span class='arguments'>(wait=nil, &amp;block)</span>
+ </div>
+ <div class='description'>
+ <p>
+ Run a single iteration of the aggregated event loop for all open server
+ sessions. The <tt>wait</tt> parameter indicates how long to wait for an
+ event to appear on any of the different sessions; <tt>nil</tt> (the
+ default) means &#8220;wait forever&#8221;. If the block is given, then it
+ will be used to determine whether <a
+ href="Session.html#M000077">process</a> returns <tt>true</tt> (the block
+ did not return <tt>false</tt>), or <tt>false</tt> (the block returned
+ <tt>false</tt>).
+ </p>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000077-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000077-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 426</span>&#x000A;426: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">process</span>(<span class="ruby-identifier">wait</span>=<span class="ruby-keyword kw">nil</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>)&#x000A;427: <span class="ruby-identifier">realize_pending_connections!</span>&#x000A;428: <span class="ruby-identifier">wait</span> = <span class="ruby-ivar">@connect_threads</span>.<span class="ruby-identifier">any?</span> <span class="ruby-value">? </span><span class="ruby-value">0</span> <span class="ruby-operator">:</span> <span class="ruby-identifier">wait</span>&#x000A;429: &#x000A;430: <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">false</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">preprocess</span>(<span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>)&#x000A;431: &#x000A;432: <span class="ruby-identifier">readers</span> = <span class="ruby-identifier">server_list</span>.<span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">s</span><span class="ruby-operator">|</span> <span class="ruby-identifier">s</span>.<span class="ruby-identifier">readers</span> }.<span class="ruby-identifier">flatten</span>&#x000A;433: <span class="ruby-identifier">writers</span> = <span class="ruby-identifier">server_list</span>.<span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">s</span><span class="ruby-operator">|</span> <span class="ruby-identifier">s</span>.<span class="ruby-identifier">writers</span> }.<span class="ruby-identifier">flatten</span>&#x000A;434: &#x000A;435: <span class="ruby-identifier">readers</span>, <span class="ruby-identifier">writers</span>, = <span class="ruby-constant">IO</span>.<span class="ruby-identifier">select</span>(<span class="ruby-identifier">readers</span>, <span class="ruby-identifier">writers</span>, <span class="ruby-keyword kw">nil</span>, <span class="ruby-identifier">wait</span>)&#x000A;436: &#x000A;437: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">readers</span>&#x000A;438: <span class="ruby-keyword kw">return</span> <span class="ruby-identifier">postprocess</span>(<span class="ruby-identifier">readers</span>, <span class="ruby-identifier">writers</span>)&#x000A;439: <span class="ruby-keyword kw">else</span>&#x000A;440: <span class="ruby-keyword kw">return</span> <span class="ruby-keyword kw">true</span>&#x000A;441: <span class="ruby-keyword kw">end</span>&#x000A;442: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000070'>
+ <a name='M000070'> </a>
+ <div class='synopsis'>
+ <span class='name'>servers</span>
+ <span class='arguments'>()</span>
+ </div>
+ <div class='description'>
+ <p>
+ Essentially an alias for <a href="Session.html#M000071">servers_for</a>
+ without any arguments. This is used primarily to satistfy the expectations
+ of the <a href="SessionActions.html">Net::SSH::Multi::SessionActions</a>
+ module.
+ </p>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000070-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000070-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 293</span>&#x000A;293: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">servers</span>&#x000A;294: <span class="ruby-identifier">servers_for</span>&#x000A;295: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000071'>
+ <a name='M000071'> </a>
+ <div class='synopsis'>
+ <span class='name'>servers_for</span>
+ <span class='arguments'>(*criteria)</span>
+ </div>
+ <div class='description'>
+ <p>
+ Returns the set of servers that match the given criteria. It can be used in
+ any (or all) of three ways.
+ </p>
+ <p>
+ First, you can omit any arguments. In this case, the full list of servers
+ will be returned.
+ </p>
+ <pre>all = session.servers_for</pre>
+ <p>
+ Second, you can simply specify a list of group names. All servers in all
+ named groups will be returned. If a server belongs to multiple matching
+ groups, then it will appear only once in the list (the resulting list will
+ contain only unique servers).
+ </p>
+ <pre>servers = session.servers_for(:app, :db)</pre>
+ <p>
+ Last, you can specify a hash with group names as keys, and property
+ constraints as the values. These property constraints are either
+ &#8220;only&#8221; constraints (which restrict the set of servers to
+ &#8220;only&#8221; those that match the given properties) or
+ &#8220;except&#8221; constraints (which restrict the set of servers to
+ those whose properties do <em>not</em> match). Properties are described
+ when the server is defined (via the :properties key):
+ </p>
+ <pre>session.group :db do&#x000A; session.use 'dbmain', 'user', :properties =&gt; { :primary =&gt; true }&#x000A; session.use 'dbslave', 'user2'&#x000A; session.use 'dbslve2', 'user2'&#x000A;end&#x000A;&#x000A;# return ONLY on the servers in the :db group which have the :primary&#x000A;# property set to true.&#x000A;primary = session.servers_for(:db =&gt; { :only =&gt; { :primary =&gt; true } })</pre>
+ <p>
+ You can, naturally, combine these methods:
+ </p>
+ <pre># all servers in :app and :web, and all servers in :db with the&#x000A;# :primary property set to true&#x000A;servers = session.servers_for(:app, :web, :db =&gt; { :only =&gt; { :primary =&gt; true } })</pre>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000071-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000071-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 334</span>&#x000A;334: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">servers_for</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">criteria</span>)&#x000A;335: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">criteria</span>.<span class="ruby-identifier">empty?</span>&#x000A;336: <span class="ruby-identifier">server_list</span>.<span class="ruby-identifier">flatten</span>&#x000A;337: <span class="ruby-keyword kw">else</span>&#x000A;338: <span class="ruby-comment cmt"># normalize the criteria list, so that every entry is a key to a</span>&#x000A;339: <span class="ruby-comment cmt"># criteria hash (possibly empty).</span>&#x000A;340: <span class="ruby-identifier">criteria</span> = <span class="ruby-identifier">criteria</span>.<span class="ruby-identifier">inject</span>({}) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">hash</span>, <span class="ruby-identifier">entry</span><span class="ruby-operator">|</span>&#x000A;341: <span class="ruby-keyword kw">case</span> <span class="ruby-identifier">entry</span>&#x000A;342: <span class="ruby-keyword kw">when</span> <span class="ruby-constant">Hash</span> <span class="ruby-keyword kw">then</span> <span class="ruby-identifier">hash</span>.<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">entry</span>)&#x000A;343: <span class="ruby-keyword kw">else</span> <span class="ruby-identifier">hash</span>.<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">entry</span> =<span class="ruby-operator">&gt;</span> {})&#x000A;344: <span class="ruby-keyword kw">end</span>&#x000A;345: <span class="ruby-keyword kw">end</span>&#x000A;346: &#x000A;347: <span class="ruby-identifier">list</span> = <span class="ruby-identifier">criteria</span>.<span class="ruby-identifier">inject</span>([]) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">aggregator</span>, (<span class="ruby-identifier">group</span>, <span class="ruby-identifier">properties</span>)<span class="ruby-operator">|</span>&#x000A;348: <span class="ruby-identifier">raise</span> <span class="ruby-constant">ArgumentError</span>, <span class="ruby-node">&quot;the value for any group must be a Hash, but got a #{properties.class} for #{group.inspect}&quot;</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">properties</span>.<span class="ruby-identifier">is_a?</span>(<span class="ruby-constant">Hash</span>)&#x000A;349: <span class="ruby-identifier">bad_keys</span> = <span class="ruby-identifier">properties</span>.<span class="ruby-identifier">keys</span> <span class="ruby-operator">-</span> [<span class="ruby-identifier">:only</span>, <span class="ruby-identifier">:except</span>]&#x000A;350: <span class="ruby-identifier">raise</span> <span class="ruby-constant">ArgumentError</span>, <span class="ruby-node">&quot;unknown constraint(s) #{bad_keys.inspect} for #{group.inspect}&quot;</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">bad_keys</span>.<span class="ruby-identifier">empty?</span>&#x000A;351: &#x000A;352: <span class="ruby-identifier">servers</span> = <span class="ruby-identifier">groups</span>[<span class="ruby-identifier">group</span>].<span class="ruby-identifier">select</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">server</span><span class="ruby-operator">|</span>&#x000A;353: (<span class="ruby-identifier">properties</span>[<span class="ruby-identifier">:only</span>] <span class="ruby-operator">||</span> {}).<span class="ruby-identifier">all?</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">prop</span>, <span class="ruby-identifier">value</span><span class="ruby-operator">|</span> <span class="ruby-identifier">server</span>[<span class="ruby-identifier">prop</span>] <span class="ruby-operator">==</span> <span class="ruby-identifier">value</span> } <span class="ruby-operator">&amp;&amp;</span>&#x000A;354: <span class="ruby-operator">!</span>(<span class="ruby-identifier">properties</span>[<span class="ruby-identifier">:except</span>] <span class="ruby-operator">||</span> {}).<span class="ruby-identifier">any?</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">prop</span>, <span class="ruby-identifier">value</span><span class="ruby-operator">|</span> <span class="ruby-identifier">server</span>[<span class="ruby-identifier">prop</span>] <span class="ruby-operator">==</span> <span class="ruby-identifier">value</span> }&#x000A;355: <span class="ruby-keyword kw">end</span>&#x000A;356: &#x000A;357: <span class="ruby-identifier">aggregator</span>.<span class="ruby-identifier">concat</span>(<span class="ruby-identifier">servers</span>)&#x000A;358: <span class="ruby-keyword kw">end</span>&#x000A;359: &#x000A;360: <span class="ruby-identifier">list</span>.<span class="ruby-identifier">uniq</span>&#x000A;361: <span class="ruby-keyword kw">end</span>&#x000A;362: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000069'>
+ <a name='M000069'> </a>
+ <div class='synopsis'>
+ <span class='name'>use</span>
+ <span class='arguments'>(*hosts, &amp;block)</span>
+ </div>
+ <div class='description'>
+ <p>
+ Defines a new server definition, to be managed by this session. The server
+ is at the given <tt>host</tt>, and will be connected to as the given
+ <tt>user</tt>. The other options are passed as-is to the <a
+ href="../../SSH.html">Net::SSH</a> session constructor.
+ </p>
+ <p>
+ If a default gateway has been specified previously (with <a
+ href="Session.html#M000068">via</a>) it will be passed to the new server
+ definition. You can override this by passing a different Net::SSH::Gateway
+ instance (or <tt>nil</tt>) with the :via key in the <tt>options</tt>.
+ </p>
+ <pre>session.use 'host'&#x000A;session.use 'user@host2', :via =&gt; nil&#x000A;session.use 'host3', :user =&gt; &quot;user3&quot;, :via =&gt; Net::SSH::Gateway.new('gateway.host', 'user')</pre>
+ <p>
+ If only a single host is given, the new server instance is returned. You
+ can give multiple hosts at a time, though, in which case an array of server
+ instances will be returned.
+ </p>
+ <pre>server1, server2 = session.use &quot;host1&quot;, &quot;host2&quot;</pre>
+ <p>
+ If given a block, this will save the block as a <a
+ href="DynamicServer.html">Net::SSH::Multi::DynamicServer</a> definition, to
+ be evaluated lazily the first time the server is needed. The block will
+ recive any options hash given to <a href="Session.html#M000069">use</a>,
+ and should return <tt>nil</tt> (if no servers are to be added), a String or
+ an array of Strings (to be interpreted as a connection specification), or a
+ <a href="Server.html">Server</a> or an array of Servers.
+ </p>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000069-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000069-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 274</span>&#x000A;274: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">use</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">hosts</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">block</span>)&#x000A;275: <span class="ruby-identifier">options</span> = <span class="ruby-identifier">hosts</span>.<span class="ruby-identifier">last</span>.<span class="ruby-identifier">is_a?</span>(<span class="ruby-constant">Hash</span>) <span class="ruby-operator">?</span> <span class="ruby-identifier">hosts</span>.<span class="ruby-identifier">pop</span> <span class="ruby-operator">:</span> {}&#x000A;276: <span class="ruby-identifier">options</span> = { <span class="ruby-identifier">:via</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">default_gateway</span> }.<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">options</span>)&#x000A;277: &#x000A;278: <span class="ruby-identifier">results</span> = <span class="ruby-identifier">hosts</span>.<span class="ruby-identifier">map</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">host</span><span class="ruby-operator">|</span>&#x000A;279: <span class="ruby-identifier">server_list</span>.<span class="ruby-identifier">add</span>(<span class="ruby-constant">Server</span>.<span class="ruby-identifier">new</span>(<span class="ruby-keyword kw">self</span>, <span class="ruby-identifier">host</span>, <span class="ruby-identifier">options</span>))&#x000A;280: <span class="ruby-keyword kw">end</span>&#x000A;281: &#x000A;282: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">block</span>&#x000A;283: <span class="ruby-identifier">results</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">server_list</span>.<span class="ruby-identifier">add</span>(<span class="ruby-constant">DynamicServer</span>.<span class="ruby-identifier">new</span>(<span class="ruby-keyword kw">self</span>, <span class="ruby-identifier">options</span>, <span class="ruby-identifier">block</span>))&#x000A;284: <span class="ruby-keyword kw">end</span>&#x000A;285: &#x000A;286: <span class="ruby-identifier">group</span> [] =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">results</span>&#x000A;287: <span class="ruby-identifier">results</span>.<span class="ruby-identifier">length</span> <span class="ruby-operator">&gt;</span> <span class="ruby-value">1</span> <span class="ruby-operator">?</span> <span class="ruby-identifier">results</span> <span class="ruby-operator">:</span> <span class="ruby-identifier">results</span>.<span class="ruby-identifier">first</span>&#x000A;288: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000068'>
+ <a name='M000068'> </a>
+ <div class='synopsis'>
+ <span class='name'>via</span>
+ <span class='arguments'>(host, user, options={})</span>
+ </div>
+ <div class='description'>
+ <p>
+ Sets up a default gateway to use when establishing connections to servers.
+ Note that any servers defined prior to this invocation will not use the
+ default gateway; it only affects servers defined subsequently.
+ </p>
+ <pre>session.via 'gateway.host', 'user'</pre>
+ <p>
+ You may override the default gateway on a per-server basis by passing the
+ :via key to the <a href="Session.html#M000069">use</a> method; see <a
+ href="Session.html#M000069">use</a> for details.
+ </p>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000068-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000068-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 243</span>&#x000A;243: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">via</span>(<span class="ruby-identifier">host</span>, <span class="ruby-identifier">user</span>, <span class="ruby-identifier">options</span>={})&#x000A;244: <span class="ruby-ivar">@default_gateway</span> = <span class="ruby-constant">Net</span><span class="ruby-operator">::</span><span class="ruby-constant">SSH</span><span class="ruby-operator">::</span><span class="ruby-constant">Gateway</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">host</span>, <span class="ruby-identifier">user</span>, <span class="ruby-identifier">options</span>)&#x000A;245: <span class="ruby-keyword kw">self</span>&#x000A;246: <span class="ruby-keyword kw">end</span></pre>
+ </div>
+ </div>
+ <div class='method public-instance' id='method-M000072'>
+ <a name='M000072'> </a>
+ <div class='synopsis'>
+ <span class='name'>with</span>
+ <span class='arguments'>(*groups) {|subsession if block_given?| ...}</span>
+ </div>
+ <div class='description'>
+ <p>
+ Returns a new <a href="Subsession.html">Net::SSH::Multi::Subsession</a>
+ instance consisting of the servers that meet the given criteria. If a block
+ is given, the subsession will be yielded to it. See <a
+ href="Session.html#M000071">servers_for</a> for a discussion of how these
+ criteria are interpreted.
+ </p>
+ <pre>session.with(:app).exec('hostname')&#x000A;&#x000A;session.with(:app, :db =&gt; { :primary =&gt; true }) do |s|&#x000A; s.exec 'date'&#x000A; s.exec 'uptime'&#x000A;end</pre>
+ </div>
+ <div class='source'>
+ <a class='source-toggle' href='#' onclick="toggleCode('M000072-source'); return false">
+ [show source]
+ </a>
+ <pre id='M000072-source'> <span class="ruby-comment cmt"># File lib/net/ssh/multi/session.rb, line 375</span>&#x000A;375: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">with</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">groups</span>)&#x000A;376: <span class="ruby-identifier">subsession</span> = <span class="ruby-constant">Subsession</span>.<span class="ruby-identifier">new</span>(<span class="ruby-keyword kw">self</span>, <span class="ruby-identifier">servers_for</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">groups</span>))&#x000A;377: <span class="ruby-keyword kw">yield</span> <span class="ruby-identifier">subsession</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">block_given?</span>&#x000A;378: <span class="ruby-identifier">subsession</span>&#x000A;379: <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>