summaryrefslogtreecommitdiff
path: root/classes/Net/SSH/Multi/SessionActions.html
blob: 78bd4a6c7aaca116c5a73b3da64cfe74fcfa1869 (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
<!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</title>
    <meta content='text/html; charset=US-ASCII' http-equiv='Content-Type'>
    <link href='../../../../css/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 target="docwin" href="../../../../files/lib/net/ssh/multi/session_actions_rb.html">lib/net/ssh/multi/session_actions.rb</a>
          </li>
        </ol>
        <div class='parent'>
          Parent:
          <strong><a target="docwin" href="../Multi.html">Multi</a></strong>
        </div>
      </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
            <code>servers</code> 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 target="docwin" href="#method-i-busy-3F">busy?</a></li>
              <li><a target="docwin" href="#method-i-connect-21">connect!</a></li>
              <li><a target="docwin" href="#method-i-exec">exec</a></li>
              <li><a target="docwin" href="#method-i-master">master</a></li>
              <li><a target="docwin" href="#method-i-open_channel">open_channel</a></li>
              <li><a target="docwin" href="#method-i-send_global_request">send_global_request</a></li>
              <li><a target="docwin" href="#method-i-sessions">sessions</a></li>
            </ol>
          </div>
          <div id='context'>
          </div>
          <div id='section'>
            <div id='methods'>
              <h2>Public Instance methods</h2>
              <div class='method public-instance' id='method-method-i-busy-3F'>
                <a name='method-i-busy-3F'></a>
                <div class='synopsis'>
                  <span class='name'>busy?</span>
                  <span class='arguments'>(include_invisible=false)</span>
                </div>
                <div class='description'>
                  
                  <p>Returns <code>true</code> if any server in the current container has an
                  open <a href="../../SSH.html">SSH</a> session that is currently processing
                  any channels. If <code>include_invisible</code> is <code>false</code> (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('method-i-busy-3F-source'); return false">
                    [show source]
                  </a>
                  <pre id='method-i-busy-3F-source'><span class="ruby-comment"># File lib/net/ssh/multi/session_actions.rb, line 29</span>&#x000A;<span class="ruby-keyword">def</span> <span class="ruby-identifier">busy?</span>(<span class="ruby-identifier">include_invisible</span>=<span class="ruby-keyword">false</span>)&#x000A;  <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;<span class="ruby-keyword">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-method-i-connect-21'>
                <a name='method-i-connect-21'></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('method-i-connect-21-source'); return false">
                    [show source]
                  </a>
                  <pre id='method-i-connect-21-source'><span class="ruby-comment"># File lib/net/ssh/multi/session_actions.rb, line 20</span>&#x000A;<span class="ruby-keyword">def</span> <span class="ruby-identifier">connect!</span>&#x000A;  <span class="ruby-identifier">sessions</span>&#x000A;  <span class="ruby-keyword">self</span>&#x000A;<span class="ruby-keyword">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-method-i-exec'>
                <a name='method-i-exec'></a>
                <div class='synopsis'>
                  <span class='name'>exec</span>
                  <span class='arguments'>(command, &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#method-i-open_channel">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 (<code>:stdout</code> or
                  <code>:stderr</code>) and a string containing the data that was received:</p>
                  
                  <pre class="ruby"><span class="ruby-identifier">session</span>.<span class="ruby-identifier">exec</span>(<span class="ruby-string">&quot;command&quot;</span>) <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">ch</span>, <span class="ruby-identifier">stream</span>, <span class="ruby-identifier">data</span><span class="ruby-operator">|</span>&#x000A;  <span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;[#{ch[:host]} : #{stream}] #{data}&quot;</span>&#x000A;<span class="ruby-keyword">end</span></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#method-i-exec">exec</a> will also
                  capture the exit status of the process in the <code>:exit_status</code>
                  property of each channel. Since <a
                  href="SessionActions.html#method-i-exec">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 class="ruby"><span class="ruby-identifier">channel</span> = <span class="ruby-identifier">session</span>.<span class="ruby-identifier">exec</span>(<span class="ruby-string">&quot;command&quot;</span>) { <span class="ruby-operator">...</span> }&#x000A;<span class="ruby-identifier">channel</span>.<span class="ruby-identifier">wait</span>&#x000A;&#x000A;<span class="ruby-keyword">if</span> <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">any?</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">c</span><span class="ruby-operator">|</span> <span class="ruby-identifier">c</span>[:<span class="ruby-identifier">exit_status</span>] <span class="ruby-operator">!=</span> <span class="ruby-value">0</span> }&#x000A;  <span class="ruby-identifier">puts</span> <span class="ruby-string">&quot;executing failed on at least one host!&quot;</span>&#x000A;<span class="ruby-keyword">end</span></pre>
                </div>
                <div class='source'>
                  <a class='source-toggle' href='#' onclick="toggleCode('method-i-exec-source'); return false">
                    [show source]
                  </a>
                  <pre id='method-i-exec-source'><span class="ruby-comment"># File lib/net/ssh/multi/session_actions.rb, line 119</span>&#x000A;<span class="ruby-keyword">def</span> <span class="ruby-identifier">exec</span>(<span class="ruby-identifier">command</span>, &amp;<span class="ruby-identifier">block</span>)&#x000A;  <span class="ruby-identifier">open_channel</span> <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">channel</span><span class="ruby-operator">|</span>&#x000A;    <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">exec</span>(<span class="ruby-identifier">command</span>) <span class="ruby-keyword">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;      <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">unless</span> <span class="ruby-identifier">success</span>&#x000A;&#x000A;      <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">on_data</span> <span class="ruby-keyword">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;        <span class="ruby-keyword">if</span> <span class="ruby-identifier">block</span>&#x000A;          <span class="ruby-identifier">block</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">ch</span>, <span class="ruby-value">:stdout</span>, <span class="ruby-identifier">data</span>)&#x000A;        <span class="ruby-keyword">else</span>&#x000A;          <span class="ruby-identifier">data</span>.<span class="ruby-identifier">chomp</span>.<span class="ruby-identifier">each_line</span> <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">line</span><span class="ruby-operator">|</span>&#x000A;            <span class="ruby-identifier">$stdout</span>.<span class="ruby-identifier">puts</span>(<span class="ruby-node">&quot;[#{ch[:host]}] #{line}&quot;</span>)&#x000A;          <span class="ruby-keyword">end</span>&#x000A;        <span class="ruby-keyword">end</span>&#x000A;      <span class="ruby-keyword">end</span>&#x000A;&#x000A;      <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">on_extended_data</span> <span class="ruby-keyword">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;        <span class="ruby-keyword">if</span> <span class="ruby-identifier">block</span>&#x000A;          <span class="ruby-identifier">block</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">ch</span>, <span class="ruby-value">:stderr</span>, <span class="ruby-identifier">data</span>)&#x000A;        <span class="ruby-keyword">else</span>&#x000A;          <span class="ruby-identifier">data</span>.<span class="ruby-identifier">chomp</span>.<span class="ruby-identifier">each_line</span> <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">line</span><span class="ruby-operator">|</span>&#x000A;            <span class="ruby-identifier">$stderr</span>.<span class="ruby-identifier">puts</span>(<span class="ruby-node">&quot;[#{ch[:host]}] #{line}&quot;</span>)&#x000A;          <span class="ruby-keyword">end</span>&#x000A;        <span class="ruby-keyword">end</span>&#x000A;      <span class="ruby-keyword">end</span>&#x000A;&#x000A;      <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">on_request</span>(<span class="ruby-string">&quot;exit-status&quot;</span>) <span class="ruby-keyword">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;        <span class="ruby-identifier">ch</span>[<span class="ruby-value">:exit_status</span>] = <span class="ruby-identifier">data</span>.<span class="ruby-identifier">read_long</span>&#x000A;      <span class="ruby-keyword">end</span>&#x000A;    <span class="ruby-keyword">end</span>&#x000A;  <span class="ruby-keyword">end</span>&#x000A;<span class="ruby-keyword">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-method-i-master'>
                <a name='method-i-master'></a>
                <div class='synopsis'>
                  <span class='name'>master</span>
                  <span class='arguments'>()</span>
                </div>
                <div class='description'>
                  
                  <p>Returns the session that is the "master". This defaults to
                  <code>self</code>, 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('method-i-master-source'); return false">
                    [show source]
                  </a>
                  <pre id='method-i-master-source'><span class="ruby-comment"># File lib/net/ssh/multi/session_actions.rb, line 12</span>&#x000A;<span class="ruby-keyword">def</span> <span class="ruby-identifier">master</span>&#x000A;  <span class="ruby-keyword">self</span>&#x000A;<span class="ruby-keyword">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-method-i-open_channel'>
                <a name='method-i-open_channel'></a>
                <div class='synopsis'>
                  <span class='name'>open_channel</span>
                  <span class='arguments'>(type="session", *extra, &on_confirm)</span>
                </div>
                <div class='description'>
                  
                  <p>Asks all sessions for all contained servers (see <a
                  href="SessionActions.html#method-i-sessions">sessions</a>) to open a new
                  channel. When each server responds, the <code>on_confirm</code> 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 "enhanced" slightly--they have two properties
                  set on them automatically, to make dealing with them in a multi-session
                  environment slightly easier:</p>
                  <ul><li>
                  <p>:server =&gt; the <a href="Server.html">Net::SSH::Multi::Server</a>
                  instance that spawned the channel</p>
                  </li><li>
                  <p>:host =&gt; the host name of the server</p>
                  </li></ul>
                  
                  <p>Having access to these things lets you more easily report which host (e.g.)
                  data was received from:</p>
                  
                  <pre class="ruby"><span class="ruby-identifier">session</span>.<span class="ruby-identifier">open_channel</span> <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">channel</span><span class="ruby-operator">|</span>&#x000A;  <span class="ruby-identifier">channel</span>.<span class="ruby-identifier">exec</span> <span class="ruby-string">&quot;command&quot;</span> <span class="ruby-keyword">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;    <span class="ruby-identifier">ch</span>.<span class="ruby-identifier">on_data</span> <span class="ruby-keyword">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;      <span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;got data #{data} from #{ch[:host]}&quot;</span>&#x000A;    <span class="ruby-keyword">end</span>&#x000A;  <span class="ruby-keyword">end</span>&#x000A;<span class="ruby-keyword">end</span></pre>
                </div>
                <div class='source'>
                  <a class='source-toggle' href='#' onclick="toggleCode('method-i-open_channel-source'); return false">
                    [show source]
                  </a>
                  <pre id='method-i-open_channel-source'><span class="ruby-comment"># File lib/net/ssh/multi/session_actions.rb, line 80</span>&#x000A;<span class="ruby-keyword">def</span> <span class="ruby-identifier">open_channel</span>(<span class="ruby-identifier">type</span>=<span class="ruby-string">&quot;session&quot;</span>, *<span class="ruby-identifier">extra</span>, &amp;<span class="ruby-identifier">on_confirm</span>)&#x000A;  <span class="ruby-identifier">channels</span> = <span class="ruby-identifier">sessions</span>.<span class="ruby-identifier">map</span> <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">ssh</span><span class="ruby-operator">|</span>&#x000A;    <span class="ruby-identifier">ssh</span>.<span class="ruby-identifier">open_channel</span>(<span class="ruby-identifier">type</span>, *<span class="ruby-identifier">extra</span>) <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">c</span><span class="ruby-operator">|</span>&#x000A;      <span class="ruby-identifier">c</span>[<span class="ruby-value">:server</span>] = <span class="ruby-identifier">c</span>.<span class="ruby-identifier">connection</span>[<span class="ruby-value">:server</span>]&#x000A;      <span class="ruby-identifier">c</span>[<span class="ruby-value">:host</span>] = <span class="ruby-identifier">c</span>.<span class="ruby-identifier">connection</span>[<span class="ruby-value">:server</span>].<span class="ruby-identifier">host</span>&#x000A;      <span class="ruby-identifier">on_confirm</span>[<span class="ruby-identifier">c</span>] <span class="ruby-keyword">if</span> <span class="ruby-identifier">on_confirm</span>&#x000A;    <span class="ruby-keyword">end</span>&#x000A;  <span class="ruby-keyword">end</span>&#x000A;  <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;<span class="ruby-keyword">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-method-i-send_global_request'>
                <a name='method-i-send_global_request'></a>
                <div class='synopsis'>
                  <span class='name'>send_global_request</span>
                  <span class='arguments'>(type, *extra, &callback)</span>
                </div>
                <div class='description'>
                  
                  <p>Sends a global request to the sessions for all contained servers (see <a
                  href="SessionActions.html#method-i-sessions">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('method-i-send_global_request-source'); return false">
                    [show source]
                  </a>
                  <pre id='method-i-send_global_request-source'><span class="ruby-comment"># File lib/net/ssh/multi/session_actions.rb, line 50</span>&#x000A;<span class="ruby-keyword">def</span> <span class="ruby-identifier">send_global_request</span>(<span class="ruby-identifier">type</span>, *<span class="ruby-identifier">extra</span>, &amp;<span class="ruby-identifier">callback</span>)&#x000A;  <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-identifier">extra</span>, &amp;<span class="ruby-identifier">callback</span>) }&#x000A;  <span class="ruby-keyword">self</span>&#x000A;<span class="ruby-keyword">end</span></pre>
                </div>
              </div>
              <div class='method public-instance' id='method-method-i-sessions'>
                <a name='method-i-sessions'></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('method-i-sessions-source'); return false">
                    [show source]
                  </a>
                  <pre id='method-i-sessions-source'><span class="ruby-comment"># File lib/net/ssh/multi/session_actions.rb, line 35</span>&#x000A;<span class="ruby-keyword">def</span> <span class="ruby-identifier">sessions</span>&#x000A;  <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">true</span>) } <span class="ruby-keyword">if</span> <span class="ruby-identifier">server</span>.<span class="ruby-identifier">session</span>.<span class="ruby-identifier">nil?</span> }&#x000A;  <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">if</span> <span class="ruby-identifier">thread</span> }&#x000A;  <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;<span class="ruby-keyword">end</span></pre>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div id='footer-push'></div>
    </div>
    <div id='footer'>
      <a target="docwin" href="http://github.com/mislav/hanna/tree/master"><strong>Hanna</strong> RDoc template</a>
    </div>
  </body>
</html>