<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Planet DevOps</title>
	<atom:link href="http://www.planetdevops.net/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.planetdevops.net</link>
	<description>A Planet for the DevOps Community</description>
	<lastBuildDate>Mon, 30 Aug 2010 19:04:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Virtualbox Savestate Restore Network Problems</title>
		<link>http://feedproxy.google.com/~r/jedi/IZwx/~3/ar9DEoIVu48/</link>
		<comments>http://feedproxy.google.com/~r/jedi/IZwx/~3/ar9DEoIVu48/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 19:04:27 +0000</pubDate>
		<dc:creator>JEDI - Just Enough Developed Infrastructure</dc:creator>
				<category><![CDATA[NAT]]></category>
		<category><![CDATA[restore]]></category>
		<category><![CDATA[savestate]]></category>
		<category><![CDATA[virtualbox]]></category>

		<guid isPermaLink="false">http://www.jedi.be/blog/2010/08/30/virtualbox-savestate-restore-network-problem/</guid>
		<description><![CDATA[Virtualbox Savestate and restore does not restore the network

I make extensive use of Virtualbox to test my installations. When I automate the installation , I use the savestate and restore to rollback changes I do to the virtual machine. Recently the...]]></description>
			<content:encoded><![CDATA[<h3>Virtualbox Savestate and restore does not restore the network</h3>

<p>I make extensive use of Virtualbox to test my installations. When I automate the installation , I use the savestate and restore to rollback changes I do to the virtual machine. Recently the network of the virtual machine would not be accessible anymore after the restore. A network ping from both inside or outside the virtualmachine fails. Several tickets have been created for it, and the bug seems to pop up every new update or so <a href="http://www.virtualbox.org/changeset/25205">Fixed in 25205</a> , <a href="http://www.virtualbox.org/ticket/5666">re-introduced in Ticket 5666</a>, <a href="http://www.virtualbox.org/ticket/5654">Ticket 5654</a> .</p>

<p>The first work-around I found was:</p>

<p>On a linux machine restart the network stack with  a <em>/etc/init.d/network restart</em> . But that is not very portable, and it's hard to automate because the network is gone.</p>

<p>A more generic work-around is to temporary disable the network link:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ VBoxManage controlvm <span class="Operators">&lt;</span>yourvmname<span class="Operators">&gt;</span> setlinkstate1 off
$ VBoxManage controlvm <span class="Operators">&lt;</span>yourvmname<span class="Operators">&gt;</span> setlinkstate1 on
$ sleep 2

</pre>
</div>


<h3>NAT: re-establish port-forwarding after savestate / restore state</h3>

<p>Another quite annoying bug is that virtualbox sometimes looses it's NAT mappings <a href="http://www.virtualbox.org/changeset/25402">Ticket 25402</a>
There is no other way then re-executing the NAT mapping.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.planetdevops.net/?feed=rss2&amp;p=6510</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Capturing the Screen or Video of Your Virtual Machines Using X, Vnc, Rdp or Native ways</title>
		<link>http://feedproxy.google.com/~r/jedi/IZwx/~3/WwG1EiS5C-E/</link>
		<comments>http://feedproxy.google.com/~r/jedi/IZwx/~3/WwG1EiS5C-E/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 13:30:09 +0000</pubDate>
		<dc:creator>JEDI - Just Enough Developed Infrastructure</dc:creator>
				<category><![CDATA[automation]]></category>
		<category><![CDATA[avi]]></category>
		<category><![CDATA[ffmpeg]]></category>
		<category><![CDATA[kvm]]></category>
		<category><![CDATA[rdesktop]]></category>
		<category><![CDATA[rdp]]></category>
		<category><![CDATA[screenshot]]></category>
		<category><![CDATA[virtualbox]]></category>
		<category><![CDATA[vnc]]></category>
		<category><![CDATA[xen]]></category>
		<category><![CDATA[xvfb]]></category>

		<guid isPermaLink="false">http://www.jedi.be/blog/2010/08/30/capturing-the-screen-of-your-virtual-machines-using-x-vnc-rdp-or-native/</guid>
		<description><![CDATA[




With this blogpost we continue the previous investigation to interact with a virtual machine using X, VNC , RDP or native ways with a virtual machine. This time instead of ]]></description>
			<content:encoded><![CDATA[<table>
<tr>
<td><a href=http://www.flickr.com/photos/nlscotland/4700299708/sizes/o/in/photostream/
"><img src='http://feedproxy.google.com/blog/2010/08/30/capturing-the-screen-of-your-virtual-machines-using-x-vnc-rdp-or-native/window-capture.jpg'></a>
</td>
<td>
With this blogpost we continue the previous investigation to interact with a virtual machine using X, VNC , RDP or native ways with a virtual machine. This time instead of <a href="<a href="http://feedproxy.google.com/~r/jedi/IZwx/~3/WwG1EiS5C-E/2010/08/29/sending-keystrokes-to-your-virtual-machines-using-X-vnc-rdp-or-native/">sending keystrokes</a> we are looking for <b>capture screenshots or even capture the complete session as a video</b>. 
</td>
</tr>
</table>




<hr>


<h3>Interacting with X-Windows</h3>

<h4>Capturing a screenshot:</h4>

<p>Grabbing a screen of an X-Windows session is easy: in order to grab the screen on an X-session on :1 issue the following command:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ import -window root -display :1 screenshot.png
</pre>
</div>


<h4>Recording a video:</h4>

<p>I got the idea of using the <a href="http://www.ffmpeg.org">ffmpeg</a> command for capturing the X-session from</p>

<p><a href="http://gasubasu.com/2009/05/06/flash2video/">http://gasubasu.com/2009/05/06/flash2video/</a></p>

<p>So I installed ffmpeg using macports</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ sudo port install ffmpeg
</pre>
</div>


<p>When I executed it, it complained about <em>Unknown input format: 'x11grab'</em></p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ffmpeg -f x11grab -vc x264 -s vga -r 30 -b 2000k -g 300 -i :1.0 session-recording.avi
FFmpeg version 0.6, Copyright (c) 2000-2010 the FFmpeg developers
  built on Aug 29 2010 16:56:51 with gcc 4.2.1 (Apple Inc. build 5664)
  configuration: --prefix=/opt/local --enable-gpl --enable-postproc --enable-swscale --enable-avfilter --enable-avfilter-lavf --enable-libmp3lame --enable-libvorbis --enable-libtheora --enable-libdirac --enable-libschroedinger --enable-libfaac --enable-libfaad --enable-libxvid --enable-libx264 --enable-libvpx --enable-libspeex --enable-nonfree --mandir=/opt/local/share/man --enable-shared --enable-pthreads --disable-indevs --cc=/usr/bin/gcc-4.2 --arch=x86_64
  libavutil     50.15. 1 / 50.15. 1
  libavcodec    52.72. 2 / 52.72. 2
  libavformat   52.64. 2 / 52.64. 2
  libavdevice   52. 2. 0 / 52. 2. 0
  libavfilter    1.19. 0 /  1.19. 0
  libswscale     1.11. 0 /  1.11. 0
  libpostproc   51. 2. 0 / 51. 2. 0
Unknown input format: <span class="Strings"><span class="Strings">'</span>x11grab<span class="Strings">'</span></span>
</pre>
</div>


<p>There was no variant or option for macports to have ffmpeg take this flag for compiling. So I downloaded the sourcecode from the ffmpeg repository:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ wget http://www.ffmpeg.org/releases/ffmpeg-0.6.tar.gz
$ cd ffmpeg-0.6
$  ./configure --enable-x11grab --enable-gpl
</pre>
</div>


<p>Although I had specified the <em>--enable-x11grab</em> option, ffmpeg still complained about the Unknown input format.</p>

<p>I got some clues <a href="http://soledadpenades.com/2010/04/26/unknown-input-or-output-format-x11grab-ubuntu/">here</a> and <a href="http://www.linuxquestions.org/questions/slackware-14/ffmpeg-x11grab-unknown-format-522296/">here</a>. And after a look at the the configure file, I found that in order to work, it required the Xfixes and Xext libraries:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
enabled x11grab                         <span class="Operators">&amp;&amp;</span>
check_header <span class="Variables">X11</span><span class="Operators">/</span>Xlib.h                 <span class="Operators">&amp;&amp;</span>
check_header <span class="Variables">X11</span><span class="Operators">/</span>extensions<span class="Operators">/</span><span class="Variables">XShm</span>.h      <span class="Operators">&amp;&amp;</span>
check_header <span class="Variables">X11</span><span class="Operators">/</span>extensions<span class="Operators">/</span>Xfixes.h    <span class="Operators">&amp;&amp;</span>
check_func <span class="Variables">XOpenDisplay</span> <span class="Operators">-</span>lX11           <span class="Operators">&amp;&amp;</span>
check_func <span class="Variables">XShmCreateImage</span> <span class="Operators">-</span>lX11 <span class="Operators">-</span>lXext <span class="Operators">&amp;&amp;</span>
check_func <span class="Variables">XFixesGetCursorImage</span> <span class="Operators">-</span>lX11 <span class="Operators">-</span>lXext <span class="Operators">-</span>lXfixes
</pre>
</div>


<p>So after installing those libraries:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ sudo port install xorg<span class="Operators">-</span>libXext
$ sudo port install xorg<span class="Operators">-</span>libXfixes
$  .<span class="Operators">/</span>configure <span class="Operators">-</span><span class="Operators">-</span>enable<span class="Operators">-</span>x11grab <span class="Operators">-</span><span class="Operators">-</span>enable<span class="Operators">-</span>gpl <span class="Operators">-</span><span class="Operators">-</span>enable<span class="Operators">-</span>nonfree <span class="Operators">-</span><span class="Operators">-</span>extra<span class="Operators">-</span>cflags<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span>-I/opt/local/include -I/opt/local/include/X11<span class="Strings">&quot;</span></span>  <span class="Operators">-</span><span class="Operators">-</span>extra<span class="Operators">-</span>ldflags<span class="Operators">=</span><span class="Operators">-</span><span class="Variables">L</span><span class="Operators">/</span>opt<span class="Operators">/</span>local<span class="Operators">/</span>lib

....
<span class="Variables">Enabled</span> indevs:
x11_grab_device
...
</pre>
</div>


<p>Now with the input x11_grab_device available, I was all set to record a running session.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ .<span class="Operators">/</span>ffmpeg <span class="Operators">-</span>f x11grab <span class="Operators">-</span>vc x264  <span class="Operators">-</span>s xga <span class="Operators">-</span>r <span class="Numbers">30</span> <span class="Operators">-</span>b 2000k <span class="Operators">-</span>g <span class="Numbers">300</span> <span class="Operators">-</span>i :<span class="Numbers">1.0</span> session<span class="Operators">-</span>recording.avi
<span class="Variables">FFmpeg</span> version <span class="Numbers">0.6</span>, <span class="Variables">Copyright</span> (c) <span class="Numbers">2000</span><span class="Operators">-</span><span class="Numbers">2010</span> the <span class="Variables">FFmpeg</span> developers
  built on <span class="Variables">Aug</span> <span class="Numbers">30</span> <span class="Numbers">2010</span> <span class="Numbers">09</span>:<span class="Numbers">11</span>:<span class="Numbers">02</span> with gcc <span class="Numbers">4.2</span>.<span class="Numbers">1</span> (<span class="Variables">Apple</span> <span class="Variables">Inc</span>. build <span class="Numbers">5664</span>)
  configuration: <span class="Operators">-</span><span class="Operators">-</span>enable<span class="Operators">-</span>x11grab <span class="Operators">-</span><span class="Operators">-</span>enable<span class="Operators">-</span>gpl <span class="Operators">-</span><span class="Operators">-</span>enable<span class="Operators">-</span>nonfree <span class="Operators">-</span><span class="Operators">-</span>extra<span class="Operators">-</span>cflags<span class="Operators">=</span><span class="Strings"><span class="Strings">'</span>-I/opt/local/include -I/opt/local/include/X11<span class="Strings">'</span></span> <span class="Operators">-</span><span class="Operators">-</span>extra<span class="Operators">-</span>ldflags<span class="Operators">=</span><span class="Operators">-</span><span class="Variables">L</span><span class="Operators">/</span>opt<span class="Operators">/</span>local<span class="Operators">/</span>lib <span class="Operators">-</span><span class="Operators">-</span>disable<span class="Operators">-</span>shared
  libavutil     <span class="Numbers">50.15</span>. <span class="Numbers">1</span> <span class="Operators">/</span> <span class="Numbers">50.15</span>. <span class="Numbers">1</span>
  libavcodec    <span class="Numbers">52.72</span>. <span class="Numbers">2</span> <span class="Operators">/</span> <span class="Numbers">52.72</span>. <span class="Numbers">2</span>
  libavformat   <span class="Numbers">52.64</span>. <span class="Numbers">2</span> <span class="Operators">/</span> <span class="Numbers">52.64</span>. <span class="Numbers">2</span>
  libavdevice   <span class="Numbers">52</span>. <span class="Numbers">2</span>. <span class="Numbers">0</span> <span class="Operators">/</span> <span class="Numbers">52</span>. <span class="Numbers">2</span>. <span class="Numbers">0</span>
  libswscale     <span class="Numbers">0.11</span>. <span class="Numbers">0</span> <span class="Operators">/</span>  <span class="Numbers">0.11</span>. <span class="Numbers">0</span>
[x11grab @ <span class="Numbers">0x10100b000</span>]device: :<span class="Numbers">1.0</span> <span class="Operators">-</span><span class="Operators">&gt;</span> display: :<span class="Numbers">1.0</span> x: <span class="Numbers">0</span> y: <span class="Numbers">0</span> width: <span class="Numbers">1024</span> height: <span class="Numbers">768</span>
[x11grab @ <span class="Numbers">0x10100b000</span>]shared memory extension  found
[x11grab @ <span class="Numbers">0x10100b000</span>]<span class="Variables">Estimating</span> duration from bitrate, this may be inaccurate
<span class="Variables">Input</span> <span class="Comments"><span class="Comments">#</span>0, x11grab, from ':1.0':</span>
  <span class="Variables">Duration</span>: <span class="Variables">N</span><span class="Operators">/</span><span class="Variables">A</span>, start: <span class="Numbers">1283153847.281641</span>, bitrate: <span class="Numbers">754974</span> kb<span class="Operators">/</span>s
    <span class="Variables">Stream</span> <span class="Comments"><span class="Comments">#</span>0.0: Video: rawvideo, bgra, 1024x768, 754974 kb/s, 30 tbr, 1000k tbn, 30 tbc</span>
<span class="Variables">File</span> <span class="Strings"><span class="Strings">'</span>session-recording.avi<span class="Strings">'</span></span> already exists. <span class="Variables">Overwrite</span> <span class="Operators">?</span> [y<span class="Operators">/</span><span class="Variables">N</span>] y
<span class="Variables">Output</span> <span class="Comments"><span class="Comments">#</span>0, avi, to 'session-recording.avi':</span>
  <span class="Variables">Metadata</span>:
    <span class="Variables">ISFT</span>            : <span class="Variables">Lavf52</span>.<span class="Numbers">64.2</span>
    <span class="Variables">Stream</span> <span class="Comments"><span class="Comments">#</span>0.0: Video: mpeg4, yuv420p, 1024x768, q=2-31, 2000 kb/s, 30 tbn, 30 tbc</span>
<span class="Variables">Stream</span> mapping:
  <span class="Variables">Stream</span> <span class="Comments"><span class="Comments">#</span>0.0 -&gt; #0.0</span>
<span class="Variables">Press</span> [q] to stop encoding
frame<span class="Operators">=</span>  <span class="Numbers">310</span> fps<span class="Operators">=</span> <span class="Numbers">30</span> q<span class="Operators">=</span><span class="Numbers">2.0</span> <span class="Variables">Lsize</span><span class="Operators">=</span>    2810kB time<span class="Operators">=</span><span class="Numbers">11.83</span> bitrate<span class="Operators">=</span><span class="Numbers">1945.</span>1kbits<span class="Operators">/</span>s dup<span class="Operators">=</span><span class="Numbers">0</span> drop<span class="Operators">=</span><span class="Numbers">21</span>    
video:2796kB audio:0kB global headers:0kB muxing overhead <span class="Numbers">0.502798</span><span class="Operators">%</span>
</pre>
</div>


<p>This worked fine! But the recording only captured 1024x768 (flag = xga), when I tried to have ffmpeg capture a larger screen 1600x1024 (flag wsxga), it told me an error about <em>Can't get shared memory</em> . No clue why. For now, the xga option is enough for me.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
.<span class="Operators">/</span>ffmpeg <span class="Operators">-</span>f x11grab <span class="Operators">-</span>vc x264  <span class="Operators">-</span>s wsxga <span class="Operators">-</span>r <span class="Numbers">30</span> <span class="Operators">-</span>b 2000k <span class="Operators">-</span>g <span class="Numbers">300</span> <span class="Operators">-</span>i :<span class="Numbers">1.0</span> session<span class="Operators">-</span>recording.avi
<span class="Variables">FFmpeg</span> version <span class="Numbers">0.6</span>, <span class="Variables">Copyright</span> (c) <span class="Numbers">2000</span><span class="Operators">-</span><span class="Numbers">2010</span> the <span class="Variables">FFmpeg</span> developers
  built on <span class="Variables">Aug</span> <span class="Numbers">30</span> <span class="Numbers">2010</span> <span class="Numbers">09</span>:<span class="Numbers">11</span>:<span class="Numbers">02</span> with gcc <span class="Numbers">4.2</span>.<span class="Numbers">1</span> (<span class="Variables">Apple</span> <span class="Variables">Inc</span>. build <span class="Numbers">5664</span>)
  configuration: <span class="Operators">-</span><span class="Operators">-</span>enable<span class="Operators">-</span>x11grab <span class="Operators">-</span><span class="Operators">-</span>enable<span class="Operators">-</span>gpl <span class="Operators">-</span><span class="Operators">-</span>enable<span class="Operators">-</span>nonfree <span class="Operators">-</span><span class="Operators">-</span>extra<span class="Operators">-</span>cflags<span class="Operators">=</span><span class="Strings"><span class="Strings">'</span>-I/opt/local/include -I/opt/local/include/X11<span class="Strings">'</span></span> <span class="Operators">-</span><span class="Operators">-</span>extra<span class="Operators">-</span>ldflags<span class="Operators">=</span><span class="Operators">-</span><span class="Variables">L</span><span class="Operators">/</span>opt<span class="Operators">/</span>local<span class="Operators">/</span>lib <span class="Operators">-</span><span class="Operators">-</span>disable<span class="Operators">-</span>shared
  libavutil     <span class="Numbers">50.15</span>. <span class="Numbers">1</span> <span class="Operators">/</span> <span class="Numbers">50.15</span>. <span class="Numbers">1</span>
  libavcodec    <span class="Numbers">52.72</span>. <span class="Numbers">2</span> <span class="Operators">/</span> <span class="Numbers">52.72</span>. <span class="Numbers">2</span>
  libavformat   <span class="Numbers">52.64</span>. <span class="Numbers">2</span> <span class="Operators">/</span> <span class="Numbers">52.64</span>. <span class="Numbers">2</span>
  libavdevice   <span class="Numbers">52</span>. <span class="Numbers">2</span>. <span class="Numbers">0</span> <span class="Operators">/</span> <span class="Numbers">52</span>. <span class="Numbers">2</span>. <span class="Numbers">0</span>
  libswscale     <span class="Numbers">0.11</span>. <span class="Numbers">0</span> <span class="Operators">/</span>  <span class="Numbers">0.11</span>. <span class="Numbers">0</span>
[x11grab @ <span class="Numbers">0x10100b000</span>]device: :<span class="Numbers">1.0</span> <span class="Operators">-</span><span class="Operators">&gt;</span> display: :<span class="Numbers">1.0</span> x: <span class="Numbers">0</span> y: <span class="Numbers">0</span> width: <span class="Numbers">1600</span> height: <span class="Numbers">1024</span>
[x11grab @ <span class="Numbers">0x10100b000</span>]shared memory extension  found
[x11grab @ <span class="Numbers">0x10100b000</span>]<span class="Variables">Fatal</span>: <span class="Variables">Can</span><span class="Strings"><span class="Strings">'</span>t get shared memory!</span>
</pre>
</div>




<hr>


<h3>Interacting with VNC</h3>

<h4>Capturing a screenshot:</h4>

<p>I found two projects that touted the ability to capture the screen of a VNC session:</p>

<ul>
<li>VncSnapshot (C)- <a href="http://vncsnapshot.sourceforge.net/">http://vncsnapshot.sourceforge.net/</a></li>
<li>VncCapture (Perl) - <a href="http://search.cpan.org/~lbrocard/Net-VNC-0.36/bin/vnccapture">http://search.cpan.org/~lbrocard/Net-VNC-0.36/bin/vnccapture</a></li>
</ul>


<p>None of them really worked for me. So I resorted back to using Xvfb as an intermediate:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ vncpasswd mypasswordfile
$ <span class="Variables">Xvfb</span>  :<span class="Numbers">1</span> <span class="Operators">-</span>screen <span class="Numbers">0</span> 1024x768x24 <span class="Operators">-</span>fbdir <span class="Operators">/</span>var<span class="Operators">/</span>tmp<span class="Operators">/</span>
(<span class="Variables">EE</span>) <span class="Variables">AIGLX</span> error: dlopen of <span class="Operators">/</span>usr<span class="Operators">/</span><span class="Variables">X11</span><span class="Operators">/</span>lib<span class="Operators">/</span>dri<span class="Operators">/</span>swrast_dri.so failed (dlopen(<span class="RegularExpressions"><span class="RegularExpressions">/</span></span><span class="RegularExpressions">usr</span><span class="RegularExpressions"><span class="RegularExpressions">/</span></span><span class="Variables">X11</span><span class="Operators">/</span>lib<span class="Operators">/</span>dri<span class="Operators">/</span>swrast_dri.so, <span class="Numbers">5</span>): image <span class="Operators">not</span> found)
(<span class="Variables">EE</span>) <span class="Variables">GLX</span>: could <span class="Operators">not</span> load software renderer
(<span class="Variables">EE</span>) <span class="Variables">XKB</span>: <span class="Variables">Couldn</span><span class="Strings"><span class="Strings">'</span>t open rules file /usr/X11/share/X11/xkb/rules/base</span>
<span class="Strings">(EE) XKB: No components provided for device Virtual core keyboard</span>
<span class="Strings">$ DISPLAY=:1 rdesktop -u username -p password -d domain remotehost</span>
<span class="Strings">$ import -window root -display :1 screenshot-rdp.png</span>
</pre>
</div>


<h4>Recording a video:</h4>

<p>To record an vnc session to flash I found the following pointers:</p>

<ul>
<li><a href="http://www.cs.ubc.ca/~bsd/vncrecording.html">http://www.cs.ubc.ca/~bsd/vncrecording.html</a></li>
<li><a href="http://www.unixuser.org/~euske/vnc2swf/">http://www.unixuser.org/~euske/vnc2swf/</a></li>
<li><a href="http://www.unixuser.org/~euske/vnc2swf/pyvnc2swf.html">http://www.unixuser.org/~euske/vnc2swf/pyvnc2swf.html</a></li>
<li><a href="http://www.unixuser.org/~euske/python/vnc2flv/index.html">http://www.unixuser.org/~euske/python/vnc2flv/index.html</a></li>
</ul>


<p>I went for the C version of vnc2swf :</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ wget http<span class="Constants"><span class="Constants">:</span>/</span><span class="Operators">/</span>www.unixuser.org<span class="Operators">/</span><span class="Operators">~</span>euske<span class="Operators">/</span>vnc2swf<span class="Operators">/</span>vnc2swf<span class="Operators">-</span><span class="Numbers">0.5</span>.<span class="Numbers">0</span>.tar.gz
$ cd vnc2swf<span class="Operators">-</span><span class="Numbers">0.5</span>.<span class="Numbers">0</span>
$  <span class="Variables">LDFLAGS</span><span class="Operators">=</span><span class="Operators">-</span><span class="Variables">L</span><span class="Operators">/</span>usr<span class="Operators">/</span><span class="Variables">X11R6</span><span class="Operators">/</span>lib  .<span class="Operators">/</span>configure 
$  <span class="Variables">LDFLAGS</span><span class="Operators">=</span><span class="Operators">-</span><span class="Variables">L</span><span class="Operators">/</span>usr<span class="Operators">/</span><span class="Variables">X11R6</span><span class="Operators">/</span>lib  make
$ .<span class="Operators">/</span>vnc2swf
usage: .<span class="Operators">/</span>vnc2swf [<span class="Operators">&lt;</span>options<span class="Operators">&gt;</span>] <span class="Operators">&lt;</span>out.swf<span class="Operators">&gt;</span> <span class="Operators">&lt;</span>host<span class="Operators">&gt;</span><span class="Constants"><span class="Constants">:</span>&lt;</span>display<span class="Comments"><span class="Comments">#</span>&gt;</span>
       .<span class="Operators">/</span>vnc2swf [<span class="Operators">&lt;</span>options<span class="Operators">&gt;</span>] <span class="Operators">&lt;</span>out.swf<span class="Operators">&gt;</span> <span class="Operators">-</span>listen [<span class="Operators">&lt;</span>display<span class="Comments"><span class="Comments">#</span>&gt;]</span>

<span class="Operators">&lt;</span>options<span class="Operators">&gt;</span> are standard <span class="Variables">Xt</span> options, <span class="Operators">or</span>:
              <span class="Operators">-</span>shared
              <span class="Operators">-</span>viewonly
              <span class="Operators">-</span>fullscreen
              <span class="Operators">-</span>passwd <span class="Operators">&lt;</span>passwd<span class="Operators">-</span>file<span class="Operators">&gt;</span>
              <span class="Operators">-</span>noauto
              <span class="Operators">-</span>encodings <span class="Operators">&lt;</span>encoding<span class="Operators">-</span>list<span class="Operators">&gt;</span> (e.g. <span class="Strings"><span class="Strings">&quot;</span>raw copyrect<span class="Strings">&quot;</span></span>)
              <span class="Operators">-</span>geometry <span class="Operators">&lt;</span>geometry<span class="Operators">&gt;</span>
              <span class="Operators">-</span>bgr233
              <span class="Operators">-</span>owncmap
              <span class="Operators">-</span>truecolour
              <span class="Operators">-</span>depth <span class="Operators">&lt;</span>depth<span class="Operators">&gt;</span>
              <span class="Operators">-</span>framerate <span class="Operators">&lt;</span>frames<span class="Operators">-</span>per<span class="Operators">-</span>sec<span class="Operators">&gt;</span>
              <span class="Operators">-</span>startrecording
              <span class="Operators">-</span>nowindow
              <span class="Operators">-</span>nostatus
              <span class="Operators">-</span>clippinggeometry <span class="Operators">&lt;</span>geometry<span class="Operators">&gt;</span>
</pre>
</div>


<p>Àn alternative is to ffmpeg as explained in the X-session, with vncviewer  displayed in Xvfb session</p>

<hr>


<h3>Interacting with RDP</h3>

<h4>Capturing a screenshot:</h4>

<p>I found <strong>0 tools</strong> to capture a screenshot directly from an RDP (at least a tool on Linux or MacosX). While poking around I found a reference to VNC inside the code of Rdesktop: there was mention of <em>rdp2vnc</em></p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ .<span class="Operators">/</span>configure <span class="Operators">-</span><span class="Operators">-</span>help <span class="Operators">|</span>grep vnc
  <span class="Operators">-</span><span class="Operators">-</span>with<span class="Operators">-</span>libvncserver<span class="Operators">-</span>config<span class="Operators">=</span><span class="Variables">CMD</span>  use <span class="Variables">CMD</span> as libvncserver<span class="Operators">-</span>config
  <span class="Operators">-</span><span class="Operators">-</span>with<span class="Operators">-</span>libvncserver     make rdp2vnc
</pre>
</div>


<p>I almost got it to work by checking out the latest svn</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ svn co https<span class="Constants"><span class="Constants">:</span>/</span><span class="Operators">/</span>rdesktop.svn.sourceforge.net<span class="Operators">/</span>svnroot<span class="Operators">/</span>rdesktop rdesktop
$ cd rdesktop
</pre>
</div>


<p>It required the installation of LibVNCServer library - <a href="http://libvncserver.sourceforge.net/">http://libvncserver.sourceforge.net/</a></p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
.<span class="Operators">/</span>configure <span class="Operators">-</span><span class="Operators">-</span>prefix <span class="Operators">/</span>opt
make
make install
</pre>
</div>




<div class="UltraViolet">
<pre class="pastels_on_dark">
$ cd rdesktop
$ .<span class="Operators">/</span>configure  <span class="Operators">-</span><span class="Operators">-</span>with<span class="Operators">-</span>libvncserver  <span class="Operators">-</span><span class="Operators">-</span>x<span class="Operators">-</span>includes<span class="Operators">=</span><span class="RegularExpressions"><span class="RegularExpressions">/</span></span><span class="RegularExpressions">opt</span><span class="RegularExpressions"><span class="RegularExpressions">/</span></span>local<span class="Operators">/</span><span class="Keywords">include</span><span class="Operators">/</span> <span class="Operators">-</span><span class="Operators">-</span>x<span class="Operators">-</span>libraries<span class="Operators">=</span><span class="RegularExpressions"><span class="RegularExpressions">/</span></span><span class="RegularExpressions">opt</span><span class="RegularExpressions"><span class="RegularExpressions">/</span></span>local<span class="Operators">/</span>lib <span class="Operators">-</span><span class="Operators">-</span>with<span class="Operators">-</span>libvncserver<span class="Operators">-</span>config
</pre>
</div>


<p>But in the end - nothing and I was facing a <a href="http://osdir.com/ml/network.rdesktop.devel/2007-01/msg00037.html">Compile problem</a></p>

<p>So of to the X-session fallback using rdesktop and xvfb:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ <span class="Variables">Xvfb</span>  :<span class="Numbers">1</span> <span class="Operators">-</span>screen <span class="Numbers">0</span> 1024x768x24 <span class="Operators">-</span>fbdir <span class="Operators">/</span>var<span class="Operators">/</span>tmp<span class="Operators">/</span>
(<span class="Variables">EE</span>) <span class="Variables">AIGLX</span> error: dlopen of <span class="Operators">/</span>usr<span class="Operators">/</span><span class="Variables">X11</span><span class="Operators">/</span>lib<span class="Operators">/</span>dri<span class="Operators">/</span>swrast_dri.so failed (dlopen(<span class="RegularExpressions"><span class="RegularExpressions">/</span></span><span class="RegularExpressions">usr</span><span class="RegularExpressions"><span class="RegularExpressions">/</span></span><span class="Variables">X11</span><span class="Operators">/</span>lib<span class="Operators">/</span>dri<span class="Operators">/</span>swrast_dri.so, <span class="Numbers">5</span>): image <span class="Operators">not</span> found)
(<span class="Variables">EE</span>) <span class="Variables">GLX</span>: could <span class="Operators">not</span> load software renderer
(<span class="Variables">EE</span>) <span class="Variables">XKB</span>: <span class="Variables">Couldn</span><span class="Strings"><span class="Strings">'</span>t open rules file /usr/X11/share/X11/xkb/rules/base</span>
<span class="Strings">(EE) XKB: No components provided for device Virtual core keyboard</span>
<span class="Strings">$ DISPLAY=:1 vncviewer -FullColor --Passwordfile mypasswordfile localhost</span>
<span class="Strings">$ import -window root -display :1 screenshot-vnc.png</span>
</pre>
</div>


<h4>Recording a video:</h4>

<p>The only way (I found) is to capture the RDP session as a video is to use ffmpeg as explained in the X-session, with rdesktop displayed in Xvfb session.</p>

<hr>


<h3>Virtual Server helpers:</h3>

<h4>Capturing screenshots with Vmware Esx</h4>

<p>The Vsphere API allows the creation of a task by using CreateScreenshot_Task() command. I used the <a href="http://vijava.sourceforge.net/">VMware VI (vSphere) Java API</a> - <a href="http://vijava.sourceforge.net/">http://vijava.sourceforge.net/</a> and coded an example to create the screenshot. The file itself is saved by vmware in the datastore root, so you need something like scp to grab it from there.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark"><span class="Keywords">import</span> java.net.URL;
<span class="Keywords">import</span> com.vmware.vim25.*;
<span class="Keywords">import</span> com.vmware.vim25.mo.*;

public class takescreenshot 
{
    public static void main(String[] args) <span class="Keywords">throws</span> Exception
    {
        String url=<span class="Strings"><span class="Strings">&quot;</span>https://localhost/sdk<span class="Strings">&quot;</span></span>; 
        String username=<span class="Strings"><span class="Strings">&quot;</span>root<span class="Strings">&quot;</span></span>; 
        String password=<span class="Strings"><span class="Strings">&quot;</span>thepassword<span class="Strings">&quot;</span></span>
        long start = System.currentTimeMillis();
        ServiceInstance si = <span class="Keywords">new</span> ServiceInstance(<span class="Keywords">new</span> <span class="Constants">URL</span>(url), username, password, <span class="LanguageConstants">true</span>);
        long end = System.currentTimeMillis();
        System.out.println(<span class="Strings"><span class="Strings">&quot;</span>time taken:<span class="Strings">&quot;</span></span> <span class="Operators">+</span> (end<span class="Operators">-</span>start));
        Folder rootFolder = si.getRootFolder();
        String name = rootFolder.getName();
        System.out.println(<span class="Strings"><span class="Strings">&quot;</span>root:<span class="Strings">&quot;</span></span> <span class="Operators">+</span> name);
        ManagedEntity[] mes = <span class="Keywords">new</span> InventoryNavigator(rootFolder).searchManagedEntities(<span class="Strings"><span class="Strings">&quot;</span>VirtualMachine<span class="Strings">&quot;</span></span>);
        <span class="ControlStructures">if</span>(mes<span class="Operators">==</span><span class="LanguageConstants">null</span> <span class="Operators">||</span> mes.length <span class="Operators">==</span><span class="Numbers">0</span>)
        {
            <span class="ControlStructures">return</span>;
        }
        
        VirtualMachine vm = (VirtualMachine) mes[<span class="Numbers">0</span>]; 
        Task screentask=vm.CreateScreenshot_Task();
        si.getServerConnection().logout();
    }
}
</pre>
</div>


<p>For an example using the perl API have a look at the script at <a href="http://communities.vmware.com/docs/DOC-10497">http://communities.vmware.com/docs/DOC-10497</a></p>

<h4>Screencapture and recording a video in Virtualbox</h4>

<p>I found that virtualbox itself has a way to capture the screen (--capture) and to record the session to file. Internally it uses ffmpeg. I wasn't able to run it on my mac, as it is not supported on that platform, but it might work for you.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ <span class="Variables">VBoxVRDP</span> <span class="Operators">-</span><span class="Operators">-</span>help
<span class="Variables">Oracle</span> <span class="Variables">VM</span> <span class="Variables">VirtualBox</span> <span class="Variables">Headless</span> <span class="Variables">Interface</span> <span class="Numbers">3.2</span>.<span class="Numbers">8</span>
(<span class="Variables">C</span>) <span class="Numbers">2008</span><span class="Operators">-</span><span class="Numbers">2010</span> <span class="Variables">Oracle</span> <span class="Variables">Corporation</span>
<span class="Variables">All</span> rights reserved.

<span class="Variables">Usage</span>:
   <span class="Operators">-</span>s, <span class="Operators">-</span>startvm, <span class="Operators">-</span><span class="Operators">-</span>startvm <span class="Operators">&lt;</span>name<span class="Operators">|</span>uuid<span class="Operators">&gt;</span>   <span class="Variables">Start</span> given <span class="Variables">VM</span> (required argument)
   <span class="Operators">-</span>v, <span class="Operators">-</span>vrdp, <span class="Operators">-</span><span class="Operators">-</span>vrdp on<span class="Operators">|</span>off<span class="Operators">|</span>config       <span class="Variables">Enable</span> (default) <span class="Operators">or</span> disable the <span class="Variables">VRDP</span>
                                         server <span class="Operators">or</span> don<span class="Strings"><span class="Strings">'</span>t change the setting</span>
<span class="Strings">   -p, -vrdpport, --vrdpport &lt;ports&gt;     Comma-separated list of ports the VRDP</span>
<span class="Strings">                                         server can bind to. Use a dash between</span>
<span class="Strings">                                         two port numbers to specify a range</span>
<span class="Strings">   -a, -vrdpaddress, --vrdpaddress &lt;ip&gt;  Interface IP the VRDP will bind to </span>
<span class="Strings">   -c, -capture, --capture               Record the VM screen output to a file</span>
<span class="Strings">   -w, --width                           Frame width when recording</span>
<span class="Strings">   -h, --height                          Frame height when recording</span>
<span class="Strings">   -r, --bitrate                         Recording bit rate when recording</span>
<span class="Strings">   -f, --filename                        File name when recording.  The codec</span>
<span class="Strings">                                         used will be chosen based on the</span>
<span class="Strings">                                         file extension</span>
</pre>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.planetdevops.net/?feed=rss2&amp;p=6505</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sending Keystrokes to Your (Virtual) Machines using X, Vnc , Rdp or Native ways</title>
		<link>http://feedproxy.google.com/~r/jedi/IZwx/~3/nalgRK13lTI/</link>
		<comments>http://feedproxy.google.com/~r/jedi/IZwx/~3/nalgRK13lTI/#comments</comments>
		<pubDate>Sun, 29 Aug 2010 14:35:42 +0000</pubDate>
		<dc:creator>JEDI - Just Enough Developed Infrastructure</dc:creator>
				<category><![CDATA[automation]]></category>
		<category><![CDATA[kvm]]></category>
		<category><![CDATA[rdesktop]]></category>
		<category><![CDATA[rdp]]></category>
		<category><![CDATA[virtualbox]]></category>
		<category><![CDATA[vnc]]></category>
		<category><![CDATA[xen]]></category>
		<category><![CDATA[xvfb]]></category>

		<guid isPermaLink="false">http://www.jedi.be/blog/2010/08/29/sending-keystrokes-to-your-virtual-machines-using-X-vnc-rdp-or-native/</guid>
		<description><![CDATA[Options overview






The most common way to interact with a virtual machine is by remote login via ssh. This blogpost is about a different way of interaction: it will show you how to send keystrokes (or mouse) directly to the remote screen of the mac...]]></description>
			<content:encoded><![CDATA[<h3>Options overview</h3>

<table>
<tr>
<td><img src='http://feedproxy.google.com/blog/2010/08/29/sending-keystrokes-to-your-virtual-machines-using-X-vnc-rdp-or-native/mission-impossible.jpg'>
</td>
<td>
The most common way to interact with a virtual machine is by remote login via ssh. This blogpost is about a different way of interaction: it will show you how to send keystrokes (or mouse) directly to the remote screen of the machine. This can be used for instance for kickstarting a machine before the network is up (typing linux), or automating things that require screen interaction. 
</td>
</tr>
</table>


<p>In general three types of remote screen sessions exist:</p>

<ul>
<li><a href="http://en.wikipedia.org/wiki/Vnc">VNC</a>: is a graphical desktop sharing system that uses the RFB protocol</li>
<li><a href="http://en.wikipedia.org/wiki/Remote_Desktop_Protocol">RDP</a>: A proprietary developed by Microsoft</li>
<li><a href="http://en.wikipedia.org/wiki/X_Window_System">X-session</a>: based on the X Window System (commonly X or X11)</li>
</ul>


<p>Most virtualization solutions allow you to activate one of these remote session options:</p>

<ul>
<li><a href="http://bradarsenault.com/post/482">Enable VNC in Vmware Fusion</a></li>
<li><a href="http://www.petri.co.il/virtual_using_vnc_and_vmware_server.htm">Enable VNC in Vmware Esx</a></li>
<li><a href="http://www.virtuatopia.com/index.php/Configuring_a_VNC_based_Graphical_Console_for_a_Xen_Paravirtualized_domainU_Guest#Configuring_a_Xen_domainU_for_VNC_Access">Enable VNC in Xen</a></li>
<li><a href="http://www.howtoforge.com/virtualization-with-kvm-on-a-fedora-13-server">Enable VNC in KVM</a></li>
<li><a href="http://www.virtualbox.org/manual/ch07.html">Enable RDP in Virtualbox</a></li>
</ul>


<hr>


<h3>Keycodes versus keys</h3>

<p>Before we start of with the different solutions, I would like to point out that sending keystrokes to these remote sessions is not the same as printing a character to the screen.</p>

<p>Keyboards and for that matter virtual keyboards interact with <a href="http://en.wikipedia.org/wiki/Scancode">scancodes</a> : every key on the keyboard is assigned a scancode. This has a few consequences:</p>

<ul>
<li>An uppercase letter is a combination of a scancode for Shift and a scancode for the letter</li>
<li>The same scancode on a different keyboard layout can cause a different letter to be send: f.i. scancode 10 (hex) generate a 'Q' on a Qwerty keyboard but 'A' on an Azerty keyboard</li>
</ul>


<p>Most of the tools assume the use of a US Layout keyboard. A good overview of the different scancodes can be found at <a href="http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html">http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html</a></p>

<hr>


<h3>Interacting with X-Windows</h3>

<p>Before VNC and RDP existed , people already had the option of using an X-client to an X-server.</p>

<p>P.S. I know you are probably looking for RDP or VNC interaction, but this description will come in handy as we will use this through Xvfb.</p>

<p>I found two tools that help sending keystrokes:</p>

<ul>
<li>xte : <a href="http://hoopajoo.net/projects/xautomation.html">http://hoopajoo.net/projects/xautomation.html</a></li>
<li>xdotool : <a href="http://www.semicomplete.com/projects/xdotool/">http://www.semicomplete.com/projects/xdotool/</a></li>
<li>C++ example code : <a href="http://www.doctort.org/adam/nerd-notes/x11-fake-keypress-event.html">http://www.doctort.org/adam/nerd-notes/x11-fake-keypress-event.html</a></li>
</ul>


<p>I couldn't get xte to compile on my mac but xdotool is conveniently available in macports.</p>

<p>What is xdotool?
This tool lets you simulate keyboard input and mouse activity, move and resize windows, etc. It does this using X11's XTEST extension and other Xlib functions.
Additionally, you can search for windows and move, resize, hide, and modify window properties like the title. If your window manager supports it, you can use xdotool to switch desktops, move windows between desktops, and change the number of desktops.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ sudo port install xdotool
---<span class="Operators">&gt;</span>  Computing dependencies <span class="ControlStructures">for</span> xdotool
---<span class="Operators">&gt;</span>  Fetching xdotool
---<span class="Operators">&gt;</span>  Verifying checksum(s) <span class="ControlStructures">for</span> xdotool
---<span class="Operators">&gt;</span>  Extracting xdotool
---<span class="Operators">&gt;</span>  Applying patches to xdotool
---<span class="Operators">&gt;</span>  Configuring xdotool
---<span class="Operators">&gt;</span>  Building xdotool
---<span class="Operators">&gt;</span>  Staging xdotool into destroot
---<span class="Operators">&gt;</span>  Installing xdotool @2.20100818.3004_0
---<span class="Operators">&gt;</span>  Activating xdotool @2.20100818.3004_0

To use xdotool (and avoid the error message <span class="Strings"><span class="Strings">&quot;</span>Error: XTEST extension unavailable</span>
<span class="Strings">on '(null)'<span class="Strings">&quot;</span></span>) you need to enable the XTEST extension. If you<span class="Strings"><span class="Strings">'</span>re using Apple<span class="Strings">'</span></span>s
X11.app, the command to <span class="ControlStructures">do</span> so is: 

defaults write org.x.X11 enable_test_extensions -boolean true 

If you<span class="Strings"><span class="Strings">'</span>re using the MacPorts X11.app, use: </span>
<span class="Strings"></span>
<span class="Strings">defaults write org.macports.X11 enable_test_extensions -boolean true </span>
<span class="Strings"></span>
<span class="Strings">This only needs to be done once.</span>
<span class="Strings">---&gt;  Cleaning xdotool</span>
</pre>
</div>


<p>Sending the key 'a' to your X-sessions</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ xdotool key <span class="Strings"><span class="Strings">'</span>a<span class="Strings">'</span></span>
</pre>
</div>


<p>The tool has a lot of ways of interacting with the windows, and for our purposes it has a option to send a <em>key</em> and even <em>mouse</em> .</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ xdotool
Usage: xdotool <span class="Operators">&lt;</span>cmd<span class="Operators">&gt;</span> <span class="Operators">&lt;</span>args<span class="Operators">&gt;</span>
Available commands:
  getactivewindow
  getwindowfocus
  getwindowname
  getwindowpid
  search
  selectwindow
  help
  version
  click
  getmouselocation
  key
  keydown
  keyup
  mousedown
  mousemove
  mousemove_relative
  mouseup
  type
  windowactivate
  windowfocus
  windowmap
  windowmove
  windowraise
  windowsize
  windowunmap
  windowreparent
  windowkill
  set_window
  behave
  set_num_desktops
  get_num_desktops
  set_desktop
  get_desktop
  set_desktop_for_window
  get_desktop_for_window
  get_desktop_viewport
  set_desktop_viewport
</pre>
</div>




<hr>


<h3>Interacting with VNC</h3>

<h4>Using Ruby-vnc</h4>

<p>The easiest way I found to interact with a VNC session is by using the excellent ruby-vnc library <a href="http://code.google.com/p/ruby-vnc/">http://code.google.com/p/ruby-vnc/</a></p>

<p>The example on the website gives you a good idea on how it works:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
<span class="Comments"><span class="Comments">#</span> launch xclock on localhost. note that there is an xterm in the top-left</span>
Net::VNC.open <span class="Strings"><span class="Strings">'</span>localhost:0<span class="Strings">'</span></span>, <span class="Constants"><span class="Constants">:</span>shared</span> =&gt; <span class="LanguageConstants">true</span>, <span class="Constants"><span class="Constants">:</span>password</span> =&gt; <span class="Strings"><span class="Strings">'</span>mypass<span class="Strings">'</span></span> <span class="ControlStructures">do </span>|<span class="Variables">vnc</span>|
  vnc.pointer_move <span class="Numbers">10</span>, <span class="Numbers">10</span>
  vnc.type <span class="Strings"><span class="Strings">'</span>xclock<span class="Strings">'</span></span>
  vnc.key_press <span class="Constants"><span class="Constants">:</span>return</span>
<span class="ControlStructures">end</span>
</pre>
</div>


<h4>Using vncviewer and xvfb</h4>

<p>If you are not that confident with ruby, there is another option. Xvfb allows you to create a virtual screen on which you can interact. Together with the vncviewer (X-client) we can use it with xdotool to interact with a vnc session.</p>

<p>The first step is to create a vnc password file, as with vncviewer the password can not be supplied on the commandline.</p>

<p>Create password file name 'mypasswordfile'</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ vncpasswd mypasswordfile
Password:
Verify:
</pre>
</div>


<p>Start Xfvb screen (:1 means another display and 24 is the colordepth)</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ Xvfb  :1 -screen 0 1024x768x24 -fbdir /var/tmp/
(EE) AIGLX error: dlopen of /usr/X11/lib/dri/swrast_dri.so failed (dlopen(/usr/X11/lib/dri/swrast_dri.so, 5): image not found)
(EE) GLX: could not load software renderer
(EE) XKB: Couldn<span class="Strings"><span class="Strings">'</span>t open rules file /usr/X11/share/X11/xkb/rules/base</span>
<span class="Strings">(EE) XKB: No components provided for device Virtual core keyboard</span>
</pre>
</div>


<p>Now we can start vncviewer (that logs in automatically) within the Virtual Frame buffer</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ DISPLAY=:1 vncviewer -FullColor --Passwordfile mypasswordfile localhost
</pre>
</div>


<p>Now we are back to using xdotool to interact with the session.</p>

<hr>


<h3>Interacting with RDP</h3>

<h4>Using properjavardp</h4>

<p><em>Properjava rdp</em> -  <a href="http://properjavardp.sourceforge.net/">http://properjavardp.sourceforge.net/</a> is a full implementation of the RDP protocol in Java. It doesn't seem to be maintained and several 'forks' are available.</p>

<ul>
<li><a href="http://github.com/kohsuke/properjavardp/tree/master/src/net/propero/">http://github.com/kohsuke/properjavardp/tree/master/src/net/propero/</a></li>
<li><a href="http://www.elusiva.com/opensource/">http://www.elusiva.com/opensource/</a></li>
<li><a href="http://jrdesktop.sourceforge.net/">http://jrdesktop.sourceforge.net/</a></li>
</ul>


<p>I used the original source to get it running:</p>

<ul>
<li>Import the src directory in a java project</li>
<li>Add the src files like RdpPacket_Localised for the src-1.4 directory</li>
<li>Add the jar files to the project (log4j.jar, ..)</li>
</ul>


<p>The following code will give you an idea on how you can use it</p>

<div class="UltraViolet">
<pre class="pastels_on_dark"><span class="Keywords">package</span> net.propero.rdp;

<span class="Keywords">import</span> java.net.InetAddress;
<span class="Keywords">import</span> net.propero.rdp.rdp5.Rdp5;
<span class="Keywords">import</span> net.propero.rdp.rdp5.VChannels;

public class SendKeysRdp {
    public static void main(String[] args) {
        int logonflags = Rdp.<span class="Constants">RDP_LOGON_NORMAL</span>;
        Rdp5 RdpLayer = <span class="LanguageConstants">null</span>;
    
        VChannels channels = <span class="Keywords">new</span> VChannels();
        RdpLayer = <span class="Keywords">new</span> Rdp5(channels);
        Common.rdp = RdpLayer;      
        <span class="ControlStructures">try</span> {
<span class="CommentsBlock"><span class="CommentsBlock">/*</span></span>
<span class="CommentsBlock"> *                  RdpLayer.connect(Options.username, InetAddress</span>
<span class="CommentsBlock">                            .getByName(server), logonflags, Options.domain,</span>
<span class="CommentsBlock">                            Options.password, Options.command,</span>
<span class="CommentsBlock">                            Options.directory);         </span>
<span class="CommentsBlock"> <span class="CommentsBlock">*/</span></span>
            RdpLayer.connect(<span class="Strings"><span class="Strings">&quot;</span>Username<span class="Strings">&quot;</span></span>, InetAddress.getByName(<span class="Strings"><span class="Strings">&quot;</span>192.168.2.30<span class="Strings">&quot;</span></span>) , logonflags, <span class="Strings"><span class="Strings">&quot;</span>Domain<span class="Strings">&quot;</span></span>,<span class="Strings"><span class="Strings">&quot;</span>Command<span class="Strings">&quot;</span></span>, <span class="Strings"><span class="Strings">&quot;</span><span class="Strings">&quot;</span></span>,<span class="Strings"><span class="Strings">&quot;</span>Directory<span class="Strings">&quot;</span></span>);
            RdpLayer.sendInput(Input.getTime(), Input.<span class="Constants">RDP_INPUT_SCANCODE</span>, Input.<span class="Constants">RDP_KEYPRESS</span>, <span class="Numbers">0x1f</span>, <span class="Numbers">0</span>);

        } <span class="ControlStructures">catch</span>(Exception e){
            System.out.println(e.toString());
        }
    }
}
</pre>
</div>


<h4>Using rdesktop and Xvfb</h4>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ sudo port install rdesktop
$ Xvfb  :1 -screen 0 1024x768x24 -fbdir /var/tmp/
(EE) AIGLX error: dlopen of /usr/X11/lib/dri/swrast_dri.so failed (dlopen(/usr/X11/lib/dri/swrast_dri.so, 5): image not found)
(EE) GLX: could not load software renderer
(EE) XKB: Couldn<span class="Strings"><span class="Strings">'</span>t open rules file /usr/X11/share/X11/xkb/rules/base</span>
<span class="Strings">(EE) XKB: No components provided for device Virtual core keyboard</span>
</pre>
</div>


<div class="UltraViolet">
<pre class="pastels_on_dark">
$ DISPLAY=:1 rdesktop -u <span class="Operators">&lt;</span>username<span class="Operators">&gt;</span> -p <span class="Operators">&lt;</span>password<span class="Operators">&gt;</span> -d <span class="Operators">&lt;</span>domain<span class="Operators">&gt;</span> remotehost
</pre>
</div>


<h4>Directly from C code re-using code from rdesktop</h4>

<p>I found a link to an xrdp overflow tool that seems to use the <em>rdp_send_scancode</em> function to send the keystroke.</p>

<p><a href="http://webcache.googleusercontent.com/search?q=cache:GIucABEgkT8J:packetstormsecurity.org/0904-exploits/xrdp-overflow.txt+rdp_send_scancode&amp;cd=7&amp;hl=nl&amp;ct=clnk&amp;gl=be&amp;client=firefox-a">http://webcache.googleusercontent.com/search?q=cache:GIucABEgkT8J:packetstormsecurity.org/0904-exploits/xrdp-overflow.txt+rdp_send_scancode&amp;cd=7&amp;hl=nl&amp;ct=clnk&amp;gl=be&amp;client=firefox-a</a></p>

<p>Another cool trick I picked up, was the way to launch commands using rdesktop :</p>

<p><a href="http://www.singularity.be/2008/03/using-rdesktop-to-script-windows.html">http://www.singularity.be/2008/03/using-rdesktop-to-script-windows.html</a></p>

<hr>


<h3>Virtualbox option</h3>

<p>Virtualbox provides a way to send keyboard scancodes directly using it's excellent API. The option <em>keyboardputscancode</em> allows to specify the hex code of the scancode. You can also send multiple keycodes after each other. In my experience this doesn't work well for a long sequence. It seems the buffer it limited and your best option is to send the different keycodes in multiple calls to the command line.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
VBoxManage controlvm        <span class="Operators">&lt;</span>uuid<span class="Operators">&gt;</span><span class="Operators">|</span><span class="Operators">&lt;</span>name<span class="Operators">&gt;</span>
                            pause<span class="Operators">|</span>resume<span class="Operators">|</span>reset<span class="Operators">|</span>poweroff<span class="Operators">|</span>savestate<span class="Operators">|</span>
                            acpipowerbutton<span class="Operators">|</span>acpisleepbutton<span class="Operators">|</span>
                            keyboardputscancode <span class="Operators">&lt;</span>hex<span class="Operators">&gt;</span> [<span class="Operators">&lt;</span>hex<span class="Operators">&gt;</span> ...]<span class="Operators">|</span>
</pre>
</div>




<hr>


<h3>Using a non-headless solution</h3>

<p>In order to automate visual tasks, there exist a lot of macro/recording tools, the downside of them is that they need an actual display to run. When scripting you are mostly looking for headless solutions though. The disadvantage of headless solutions is that they are cumbersome to create as you have to move the pointer and the keys at the exact spot.</p>

<h4>Sikuli</h4>

<p>When you are interacting with a session you as a person do a lot more then just typing things. You yourself also locate which window to focus, what button to click.</p>

<p>Sikuli is a great tool that tries to help you in those tasks. It uses image recognition tools to find the correct place on the screen. Think of it a visual scripting language for screen interaction. An example script looks like this:</p>

<p><img src='http://feedproxy.google.com/blog/2010/08/29/sending-keystrokes-to-your-virtual-machines-using-X-vnc-rdp-or-native/sikuli-example.png'></p>

<p>It allows you use these commands within java and it seems that someone is working on <a href="https://answers.launchpad.net/sikuli/+question/118598">replacing the java.awt.robot to a vnc version</a></p>

<p>More background can be found at:</p>

<ul>
<li><a href="http://www.software-testing.com.au/blog/2010/08/16/automating-flash-ajax-popups-and-more-using-ruby-watir-and-sikuli/">http://www.software-testing.com.au/blog/2010/08/16/automating-flash-ajax-popups-and-more-using-ruby-watir-and-sikuli/
</a></li>
<li><a href="http://groups.csail.mit.edu/uid/projects/sikuli/sikuli-uist2009.pdf">http://groups.csail.mit.edu/uid/projects/sikuli/sikuli-uist2009.pdf</a></li>
<li><a href="http://sikuli.org/documentation.shtml#/trac/wiki/How%20to%20use%20Sikuli%20Script%20in%20your%20JAVA%20programs?">http://sikuli.org/documentation.shtml#/trac/wiki/How%20to%20use%20Sikuli%20Script%20in%20your%20JAVA%20programs?</a></li>
</ul>


<p>The function type() simulates keyboard typing just as a user types text in a application. However, type() doesn't work for different keyboard layouts other than QWERTY, such as DVORAK. We provide a workaround paste() since 0.9.7 (20100127). The function paste() transfers text through system's clipboard, which is fully independent of keyboard layouts. A sample usage that paste "network" into a search box is shown as follows.</p>

<h4>Other options</h4>

<p>For completeness I provide different options I found useful</p>

<ul>
<li>pywinauto : <a href="http://pywinauto.openqa.org/">http://pywinauto.openqa.org/</a></li>
<li>autoit :  <a href="http://www.autoitscript.com/">http://www.autoitscript.com/</a></li>
<li>Using applescript: <a href="http://jehiah.cz/projects/ARD-SendUnixCommands.php">http://jehiah.cz/projects/ARD-SendUnixCommands.php
</a></li>
</ul>


<div class="UltraViolet">
<pre class="pastels_on_dark">
$ osascript -e <span class="Strings"><span class="Strings">'</span>tell application &quot;System Events&quot; to keystroke &quot;LOGIN_NAME&quot;<span class="Strings">'</span></span><span class="Operators">;</span> \
$ osascript -e <span class="Strings"><span class="Strings">'</span>tell application &quot;System Events&quot; to keystroke tab<span class="Strings">'</span></span><span class="Operators">;</span> \
$ osascript -e <span class="Strings"><span class="Strings">'</span>tell application &quot;System Events&quot; to delay 0.5<span class="Strings">'</span></span><span class="Operators">;</span> \
$ osascript -e <span class="Strings"><span class="Strings">'</span>tell application &quot;System Events&quot; to keystroke &quot;PASSWORDHERE&quot;<span class="Strings">'</span></span><span class="Operators">;</span> \
$ osascript -e <span class="Strings"><span class="Strings">'</span>tell application &quot;System Events&quot; to delay 0.5<span class="Strings">'</span></span><span class="Operators">;</span> \
$ osascript -e <span class="Strings"><span class="Strings">'</span>tell application &quot;System Events&quot; to keystroke return<span class="Strings">'</span></span>

Replace LOGIN_NAME and PASSWORD with the proper values
Run as <span class="Strings"><span class="Strings">&quot;</span>root<span class="Strings">&quot;</span></span> user
</pre>
</div>



]]></content:encoded>
			<wfw:commentRss>http://www.planetdevops.net/?feed=rss2&amp;p=6495</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DevOps and the Iteration Showcase</title>
		<link>http://evan.bottch.com/2010/08/29/devops-and-the-iteration-showcase/</link>
		<comments>http://evan.bottch.com/2010/08/29/devops-and-the-iteration-showcase/#comments</comments>
		<pubDate>Sun, 29 Aug 2010 04:31:37 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[ThoughtWorks]]></category>
		<category><![CDATA[devops]]></category>

		<guid isPermaLink="false">http://evan.bottch.com/?p=200</guid>
		<description><![CDATA[Look down. Look up again. You&#8217;re on the agile team your team could be like. It&#8217;s the end of the iteration, and there&#8217;s a showcase this afternoon (sprint demo if you prefer) demonstrating all the new functionality the team has &#8230; <a href="http://evan.bottch.com/2010/08/29/devops-and-the-iteration-showcase/">Continue reading <span>&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Look down.  Look up again.  You&#8217;re on the agile team your team could be like.</strong></p>
<p>It&#8217;s the end of the iteration, and there&#8217;s a showcase this afternoon (sprint demo if you prefer) demonstrating all the new functionality the team has built in the last two weeks.  In the room are members of the project team, the product owner, and various stakeholders and interested parties from the marketing and customer service teams who use the product every day.  Everyone&#8217;s very excited about the new features, and provide some great feedback on the spot.</p>
<p>This sounds great!  But something is missing.  <strong>Where are the &#8216;ops&#8217; features?</strong></p>
<p>Very few agile projects I&#8217;ve been on will demonstrate the &#8216;cross-functional&#8217;* or ops features they&#8217;ve completed in the same showcase, but they SHOULD.  Features like monitoring, failover testing, deployment automation, performance improvements &#8211; these are all very important to our business.  If you&#8217;ve truly got a DevOps culture, then they should be showcased and celebrated alongside the new whizzy UI features.</p>
<p>How do we make these achievements relevant to a wider audience?  Start by describing the work in a <a href="http://lizkeogh.com/2008/09/10/feature-injection-and-handling-technical-stories/">different way</a> &#8211; talk about the work that&#8217;s being done in terms of its benefit to our business.</p>
<p>A technical story would look like:</p>
<blockquote><p>Enable monitoring of JVM heap allocation.</p></blockquote>
<p>To make it more understandable to the business, highlight the business benefit in this way:</p>
<blockquote><p>In order to reduce the risk of an outage as site traffic grows<br />
The operations team need to<br />
Monitor the JVM heap memory allocation</p></blockquote>
<p>By putting the business benefit up front (and always present) this should help make the story more interesting to showcase.</p>
<p>The regular showcase presentation is also an opportunity to report to the stakeholder group on the current state of the system in production.  This can take the form of presenting some selected metrics plotted over time.  For a website you might include metrics on site traffic, response times, performance and stability over time.  The presentation should support the prioritisation of appropriate cross-functional work to improve those metrics over time.</p>
<p>Getting to the point where cross-functional work is celebrated by a wider stakeholder group requires some creativity and effort.  When it works I&#8217;ve observed it makes the conversations around proper prioritisation and collaboration on DevOps work so much easier.</p>
<p><span style="color: #808080;">* I&#8217;ve taken to using the term &#8216;cross-functional requirements&#8217; (</span><a href="http://sarahtaraporewalla.com/thoughts/agile/i-dont-believe-in-nfrs/"><span style="color: #808080;">thanks to Sarah</span></a><span style="color: #808080;">) to describe requirements that are cross-cutting and not-directly-functional &#8211; for example performance, availablity, volume, maintainability.  I think the term NFR has become a weasel-word, treated as &#8216;someone else&#8217;s problem&#8217; rather than an important priority.  It might just be a word game, but I think it&#8217;s useful.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://evan.bottch.com/2010/08/29/devops-and-the-iteration-showcase/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Effective adhoc commands in clusters</title>
		<link>http://www.devco.net/archives/2010/08/28/effective_adhoc_commands_in_clusters.php</link>
		<comments>http://www.devco.net/archives/2010/08/28/effective_adhoc_commands_in_clusters.php#comments</comments>
		<pubDate>Sat, 28 Aug 2010 20:19:12 +0000</pubDate>
		<dc:creator>R.I. Pienaar</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[mcollective]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://www.devco.net/?p=1733</guid>
		<description><![CDATA[Last night I had a bit of a mental dump on twitter about structured data and non structured data when communicating with a cluster or servers &#8211; Twitter fails at this kind of stuff so figured I&#8217;ll follow up with a blog post. I started off asking for a list of tools in the cluster [...]]]></description>
			<content:encoded><![CDATA[<p>Last night I had a bit of a mental dump on twitter about structured data and non structured data when communicating with a cluster or servers &#8211; Twitter fails at this kind of stuff so figured I&#8217;ll follow up with a blog post.  </p>
<p>I started off asking for a list of tools in the cluster admin space and got some great pointers which I am reproducing here:</p>
<p><a href="http://fabfile.org/">fabric</a>, <a href="http://www.capify.org/">cap</a>, <a href="https://fedorahosted.org/func/">func</a>, <a href="http://sourceforge.net/apps/mediawiki/clusterssh/">clusterssh</a>, <a href="http://code.google.com/p/sshpt/">sshpt</a>, <a href="http://www.theether.org/pssh/">pssh</a>, <a href="http://m.a.tt/er/massh.html">massh</a>, <a href="http://sourceforge.net/apps/trac/clustershell">clustershell</a>, <a href="http://controltier.org/">controltier</a>, <a href="http://bit.ly/deb9Ii">rash</a> (related), <a href="http://www.netfort.gr.jp/~dancer/software/dsh.html.en">dsh</a>, <a href="http://wiki.opscode.com/display/chef/Knife">chef knife ssh</a>, <a href="http://sourceforge.net/projects/pdsh/">pdsh+dshbak</a> and of course <a href="http://marionette-collective.org">mcollective</a>.  I was also sent a <a href="http://www.mynitor.com/2010/08/16/top-50-ssh-helper-tools-omg/">list of ssh related tools</a> which is awesome.</p>
<p>The point I feel needs to be made is that in general these tools just run commands on remote servers.  They are not aware of the commands output structure, what denotes pass or fail in the context of the command etc.  Basically the commands people run are commands designed for ages to be looked at by human eyes and then parsed by a human mind.  Yes they are easy to pipe and grep and chop up, but ultimately it was always designed to be run on one server at a time.</p>
<p>The parallel ssh&#8217;ers run these commands in parallel and you tend to get a mash of output.  The output is mixed STDOUT and STDERR and often output from different machines are multiplexed into each other so you get a stream of text that is hard to decipher even on 2 machines, not to mention 200 at once.</p>
<p>Take as an example a simple yum command to install a package:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">% yum install zsh
Loaded plugins: fastestmirror, priorities, protectbase, security
Loading mirror speeds from cached hostfile
372 packages excluded due to repository priority protections
0 packages excluded due to repository protections
Setting up Install Process
Package zsh-4.2.6-3.el5.i386 already installed and latest version
Nothing to do</pre></div></div>

<p></code></p>
<p>When run on one machine you pretty much immediately know whats going on, package was already there so nothing got done, now lets see cap invoke:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;"># cap invoke COMMAND=&quot;yum -y install zsh&quot;
  * executing `invoke'
  * executing &quot;yum -y install zsh&quot;
    servers: [&quot;web1&quot;, &quot;web2&quot;, &quot;web3&quot;]
    [web2] executing command
    [web1] executing command
    [web3] executing command
 ** [out :: web2] Loaded plugins: fastestmirror, priorities, protectbase, security
 ** [out :: web2] Loading mirror speeds from cached hostfile
 ** [out :: web3] Loaded plugins: fastestmirror, priorities, protectbase
 ** [out :: web3] Loading mirror speeds from cached hostfile
 ** [out :: web3] 495 packages excluded due to repository priority protections
 ** [out :: web2] 495 packages excluded due to repository priority protections
 ** [out :: web3] 0 packages excluded due to repository protections
 ** [out :: web3] Setting up Install Process
 ** [out :: web2] 0 packages excluded due to repository protections
 ** [out :: web2] Setting up Install Process
 ** [out :: web1] Loaded plugins: fastestmirror, priorities, protectbase
 ** [out :: web3] Package zsh-4.2.6-3.el5.x86_64 already installed and latest version
 ** [out :: web3] Nothing to do
 ** [out :: web1] Loading mirror speeds from cached hostfile
 ** [out :: web1] Install       1 Package(s)
 ** [out :: web2] Package zsh-4.2.6-3.el5.x86_64 already installed and latest version
 ** [out :: web2] Nothing to do
 ** [out :: web1] 548 packages excluded due to repository priority protections
 ** [out :: web1] 0 packages excluded due to repository protections
 ** [out :: web1] Setting up Install Process
 ** [out :: web1] Resolving Dependencies
 ** [out :: web1] --&gt; Running transaction check
 ** [out :: web1] ---&gt; Package zsh.x86_64 0:4.2.6-3.el5 set to be updated
 ** [out :: web1] --&gt; Finished Dependency Resolution
 ** [out :: web1]
 ** [out :: web1] Dependencies Resolved
 ** [out :: web1]
 ** [out :: web1] ================================================================================
 ** [out :: web1] Package      Arch            Version                Repository            Size
 ** [out :: web1] ================================================================================
 ** [out :: web1] Installing:
 ** [out :: web1] zsh          x86_64          4.2.6-3.el5            centos-base          1.7 M
 ** [out :: web1]
 ** [out :: web1] Transaction Summary
 ** [out :: web1] ================================================================================
 ** [out :: web1] Install       1 Package(s)
 ** [out :: web1] Upgrade       0 Package(s)
 ** [out :: web1]
 ** [out :: web1] Total download size: 1.7 M
 ** [out :: web1] Downloading Packages:
 ** [out :: web1] Running rpm_check_debug
 ** [out :: web1] Running Transaction Test
 ** [out :: web1] Finished Transaction Test
 ** [out :: web1] Transaction Test Succeeded
 ** [out :: web1] Running Transaction
 ** [out :: web1] Installing     : zsh                                                      1/1
 ** [out :: web1]
 ** [out :: web1]
 ** [out :: web1] Installed:
 ** [out :: web1] zsh.x86_64 0:4.2.6-3.el5
 ** [out :: web1]
 ** [out :: web1] Complete!
    command finished
zlib(finalizer): the stream was freed prematurely.
zlib(finalizer): the stream was freed prematurely.
zlib(finalizer): the stream was freed prematurely.</pre></div></div>

<p></code></p>
<p>Most of this stuff scrolled off my screen and at the end all I had was the last bit of output.  I could scroll up and still figure out ok what was going on &#8211; 2 of the 3 already had it installed, one got it.   Now imagine 100 or 500 of these machines output all mixed in?  Just parsing this output would be prone to human error and you&#8217;re likely to miss that something failed.</p>
<p>So here is my point, your cluster management tool need to provide an API around the every day commands like packages, process listing etc.  It should return structured data and you could use the structured data to create tools more fit for the purpose of using on large amount of machines.  Being that the output is standardized it should provide generic tools that just do the right thing out of the box for you.</p>
<p>With the package example above knowing that all 500 machines had spewed out a bunch of stuff while installing isn&#8217;t important, you just want to know the result in a nice way.  Here&#8217;s what mcollective does:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">$ mc-package install zsh
&nbsp;
 * [ ============================================================&gt; ] 3 / 3
&nbsp;
web2.my.net                      version = zsh-4.2.6-3.el5
web3.my.net                      version = zsh-4.2.6-3.el5
web1.my.net                      version = zsh-4.2.6-3.el5
&nbsp;
---- package agent summary ----
           Nodes: 3 / 3
        Versions: 3 * 4.2.6-3.el5
    Elapsed Time: 16.33 s</pre></div></div>

<p></code></p>
<p>In the case of a package you want to just know the version post the event and a summary of status.  Just by looking at the stats I know the desired result was achieved, if I had different versions listed I could very quickly identify the problem ones.</p>
<p>Here&#8217;s another example &#8211; NRPE this time:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">% mc-rpc nrpe runcommand command=check_disks
&nbsp;
 * [ ============================================================&gt; ] 47 / 47
&nbsp;
&nbsp;
dev1.my.net                      Request Aborted
   CRITICAL
          Exit Code: 2
   Performance Data:  /=4111MB;3706;3924;0;4361 /boot=26MB;83;88;0;98 /dev/shm=0MB;217;230;0;256
             Output: DISK CRITICAL - free space: / 24 MB (0% inode=86%);
&nbsp;
&nbsp;
Finished processing 47 / 47 hosts in 766.11 ms</pre></div></div>

<p></code></p>
<p>Here notice I didn&#8217;t use a NRPE specific <em>mc-</em> command, I just used the generic rpc caller and the caller knows that I am only interesting in seeing the results of machines that are in WARNING or CRITICAL state.  If you run this on your console you&#8217;d see the <em>&#8216;Request Aborted&#8217;</em> would be red and the <em>&#8216;CRITICAL&#8217;</em> would be yellow.   Immediately pulling your eye to the important information.  Also note how the result shows human friendly field names like &#8216;Performance Data&#8217;.  </p>
<p>The formatting, highlighting, knowledge to only show failing resources and human friendly headings all happen automatically, no programming of client side UI is required you get the ability to do this for free simply from the fact that mcollective focuses on putting structure around outputs.</p>
<p>Here&#8217;s the earlier package install example with the standard rpc caller not with a specialized package frontend:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="console" style="font-family:monospace;">% mc-rpc package install package=zsh
Determining the amount of hosts matching filter for 2 seconds .... 47
&nbsp;
 * [ ============================================================&gt; ] 47 / 47
&nbsp;
Finished processing 47 / 47 hosts in 2346.05 ms</pre></div></div>

<p></code></p>
<p>Everything worked, all 47 machines have the package installed and your desired action was taken.  So no point in spamming you with pages of junk, who cares to see all the Yum output?  Had an install failed you&#8217;d have had usable error message just for the host that failed.  The output would be equally usable on one or a thousand hosts with very little margin for human error in knowing the result of your request.</p>
<p>This happens because mcollective has a standard structure of responses, each response has a absolute success value that tells you if the request failed or not and by using this you can get generic CLI, Web, etc tools that displays large amounts of data from a network of hosts in a way that is appropriate and context aware.</p>
<p>For reference here&#8217;s the response as received on the client:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&#123;</span>:sender<span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#996600;">&quot;dev1.my.net&quot;</span>,
 <span style="color:#ff3333; font-weight:bold;">:statuscode</span><span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#006666;">1</span>,
 <span style="color:#ff3333; font-weight:bold;">:statusmsg</span><span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#996600;">&quot;CRITICAL&quot;</span>,
 <span style="color:#ff3333; font-weight:bold;">:data</span><span style="color:#006600; font-weight:bold;">=&gt;</span>
  <span style="color:#006600; font-weight:bold;">&#123;</span>:perfdata<span style="color:#006600; font-weight:bold;">=&gt;</span>
    <span style="color:#996600;">&quot; /=4111MB;3706;3924;0;4361 /boot=26MB;83;88;0;98 /dev/shm=0MB;217;230;0;256&quot;</span>,
   <span style="color:#ff3333; font-weight:bold;">:output</span><span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#996600;">&quot;DISK CRITICAL - free space: / 24 MB (0% inode=86%);&quot;</span>,
   <span style="color:#ff3333; font-weight:bold;">:exitcode</span><span style="color:#006600; font-weight:bold;">=&gt;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p></code></p>
<p>Only by thinking about CLI and admin tasks in this way do I believe we can take the Unix utilities that we call on remote hosts and turn them into something appropriate for large scale parallel use that doesn&#8217;t overwhelm the human at the other end with information.  Additionally since this is an API that is computer friendly it makes those tools usable in many other places like code deployers &#8211; for example to enable your continues deployment using robust use of unix tools via such an API.</p>
<p>There are many other advantages to this approach.  Requests are authorized on a very fine level, requests are audited.  API wrappers are code that&#8217;s versioned, that can be tested in development and makes the margin for error much smaller than just running random unix commands ad hoc.  Finally if you&#8217;re using the code on a CLI ad-hoc as above or in your continues deployer you share the same code that you&#8217;ve already tested and trust.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devco.net/archives/2010/08/28/effective_adhoc_commands_in_clusters.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projects are evil and must be destroyed</title>
		<link>http://evan.bottch.com/2010/08/29/projects-are-evil-and-must-be-destroyed/</link>
		<comments>http://evan.bottch.com/2010/08/29/projects-are-evil-and-must-be-destroyed/#comments</comments>
		<pubDate>Sat, 28 Aug 2010 14:07:44 +0000</pubDate>
		<dc:creator>evan</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[ThoughtWorks]]></category>
		<category><![CDATA[devops]]></category>

		<guid isPermaLink="false">http://evan.bottch.com/?p=192</guid>
		<description><![CDATA[The majority of organisations I&#8217;ve worked with deliver new system functionality as development projects.  These are funded with capex, and have a start and an end.  Even projects that are &#8216;agile&#8217;  are still expected to finish at some date in &#8230; <a href="http://evan.bottch.com/2010/08/29/projects-are-evil-and-must-be-destroyed/">Continue reading <span>&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The majority of organisations I&#8217;ve worked with deliver new system functionality as development projects.  These are funded with capex, and have a start and an end.  Even projects that are &#8216;agile&#8217;  are still expected to finish at some date in the future, then once the system has been delivered it will undergo &#8216;handover&#8217; to &#8216;BAU&#8217;.  The project team usually moves on to new projects, developing remarkable cases of mass-amnesia along the way.</p>
<p>Projects deliver exactly what they promise.  <strong>Project teams have little incentive to invest in the long term operation and maintenance of the systems that they create.</strong> I&#8217;m not saying that the team doesn&#8217;t care or are intentionally acting irresponsibly, but when delivery pressure is applied the first things to be dropped from the project schedule will be the cross-functional concerns that make the system reliable, monitorable, deployable, and maintainable ongoing.</p>
<p>The project effect:</p>
<ul>
<li>the project team do not have to live with the long term results of their own architectural and design decisions.</li>
<li>BAU support/maintenance teams are generally under-resourced, have extremely limited opportunity for handover from project teams, and have to support many different systems.  This usually leads to less than ideal development practices and deteriorating quality over time.</li>
<li>the project team never have to be involved in problem analysis for production outages.  They&#8217;re never forced to put the right kind of monitoring and logging in place to find root causes.</li>
<li>the project team only do a limited number of releases to production, so have little incentive to invest in reliable automation or production-like test environments.</li>
</ul>
<p>Therefore &#8211; I believe that many projects are the source of &#8216;instant legacy&#8217;, and a major cause of the development and operations divide.</p>
<p><strong>What&#8217;s the alternative?</strong> Form long-lived teams around applications/products, or sets of features.  A team works from a prioritised backlog of work that contains a mix of larger initiatives, minor enhancements, or BAU-style bug fixes and maintenance.  Second-level support should be handled by people in the product team.  Everyone in the team should work with common process and a clear understanding of technical design and business vision.</p>
<p>This approach is not easy &#8211; it introduces new challenges particularly around balancing priorities and budgeting.  I&#8217;ve observed that the benefits in terms of long term system health definitely outweigh the drawbacks. Like everything &#8211; hire good people who care, and give them the right incentives, good things will happen.</p>
]]></content:encoded>
			<wfw:commentRss>http://evan.bottch.com/2010/08/29/projects-are-evil-and-must-be-destroyed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ssh tricks &#8211; the usual and beyond</title>
		<link>http://feedproxy.google.com/~r/jedi/IZwx/~3/x9-q_PeQmwM/</link>
		<comments>http://feedproxy.google.com/~r/jedi/IZwx/~3/x9-q_PeQmwM/#comments</comments>
		<pubDate>Fri, 27 Aug 2010 13:16:34 +0000</pubDate>
		<dc:creator>JEDI - Just Enough Developed Infrastructure</dc:creator>
				<category><![CDATA[automation]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://www.jedi.be/blog/2010/08/27/ssh-tricks-the-usual-and-beyond/</guid>
		<description><![CDATA[
SSH is an amazing beast. I nearly use it everyday and I'm amazed every time I learn something new. The following is a list of my tricks in the bag. It starts with the usual tricks that you find all over the place, but I hope there will be some new tri...]]></description>
			<content:encoded><![CDATA[<table><tr><td>
<img src="http://feedproxy.google.com/blog/2010/08/27/ssh-tricks-the-usual-and-beyond/ssh-bank.jpg" /></td><td>SSH is an amazing beast. I nearly use it everyday and I'm amazed every time I learn something new. The following is a list of my tricks in the bag. It starts with the usual tricks that you find all over the place, but I hope there will be some new tricks for you too. <br /><br />
What's your best trick? Share it in the comments with the world. Nobody can know enough of ssh!
</td></tr></table>




<hr />


<h2>The basics:</h2>

<h3><strong>Password-less login:</strong></h3>

<p>This is usually the first thing start doing when want automation with ssh</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
<span class="Comments"><span class="Comments">#</span>Create a new keypair</span>
$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file <span class="ControlStructures">in</span> which to save the key (/Users/patrick/.ssh/id_dsa): 
Enter passphrase (empty <span class="ControlStructures">for</span> no passphrase): 
Enter same passphrase again: 
Your identification has been saved <span class="ControlStructures">in</span> /Users/patrick/.ssh/id_dsa.
Your public key has been saved <span class="ControlStructures">in</span> /Users/patrick/.ssh/id_dsa.pub.
The key fingerprint is:
87:66:b7:a0:f6:0e:6a:71:2c:5d:ee:5f:17:2a:b7:2f patrick@localhost
The key<span class="Strings"><span class="Strings">'</span>s randomart image is:</span>
<span class="Strings">+--[ DSA 1024]----+</span>
<span class="Strings">|                 |</span>
<span class="Strings">|                 |</span>
<span class="Strings">|                 |</span>
<span class="Strings">|        ..       |</span>
<span class="Strings">|     o oS o   .  |</span>
<span class="Strings">|    o ++.+ . . . |</span>
<span class="Strings">|     ++.  o + .  |</span>
<span class="Strings">|    .o o.  +Eo   |</span>
<span class="Strings">|   ..  .o.. .o.  |</span>
<span class="Strings">+-----------------+</span>
<span class="Strings">$ cat ~/.ssh/id_dsa.pub | ssh user@remotehost &quot;cat - &gt;&gt; ~/.ssh/authorized_keys&quot;</span>
<span class="Strings">$ ssh user@remotehost</span>
</pre>
</div>


<h3><strong>Install your keys on a remote server:</strong></h3>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh-copy-id -i <span class="Operators">~</span>/.ssh/id_dsa.pub user@remotehost
<span class="Comments"><span class="Comments">#</span>Alternative </span>
$ cat <span class="Operators">~</span>/.ssh/id_dsa.pub <span class="Operators">|</span> ssh user@remotehost <span class="Strings"><span class="Strings">&quot;</span>cat - &gt;&gt; ~/.ssh/authorized_keys<span class="Strings">&quot;</span></span>
</pre>
</div>


<h3><strong>Passphrase automation:</strong></h3>

<p>If you have protected your keys with a passphrase (which you should), then it is annoying to re-enter that all the time. You can avoid that by running your environment inside an <em>ssh-agent</em> and using <em>ssh-add</em> to enter the passphrase once.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh-add <span class="Operators">~</span>/.ssh/id_dsa
Need passphrase <span class="ControlStructures">for</span> /home/mah/.ssh/id_dsa (you@example.com).
Enter passphrase:
$
</pre>
</div>


<h3><strong>Pseudo Terminal</strong> :</h3>

<p>some commands like sudo require a pseudo terminal to be activated</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -t patrick@remotehost sudo cat /etc/passwd
</pre>
</div>


<h3><strong>Avoid lastlog:</strong></h3>

<p>Log in without appearing in lastlog/w and who output.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -T user@hostname.com
</pre>
</div>


<h3><strong>Piping</strong></h3>

<p>Example of using piping to backup over the network</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ufsdump 0uf - /dev/md/rdsk/d33 <span class="Operators">|</span> ssh r280n <span class="Strings"><span class="Strings">&quot;</span>dd obs=32k ibs=32k of=/dev/rmt/0n<span class="Strings">&quot;</span></span>
</pre>
</div>


<h3><strong>Rsync over ssh</strong></h3>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ rsync -avz -e <span class="Strings"><span class="Strings">&quot;</span>ssh -i /home/thisuser/cron/thishost-rsync-key<span class="Strings">&quot;</span></span> remoteuser@remotehost:/remote/dir /this/dir/ 
</pre>
</div>




<hr />


<h2>Tunnels and firewall-piercings:</h2>

<h3><strong>X-forwarding:</strong></h3>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -X patrick@remotehost
Warning: untrusted X11 forwarding setup failed: xauth key data not generated
Warning: No xauth data<span class="Operators">;</span> using fake authentication data <span class="ControlStructures">for</span> X11 forwarding.
Last login: Fri Aug 27 20:27:40 2010
</pre>
</div>


<h3><strong>Port forwarding:</strong></h3>

<p>Set up a localforward from the remote machine port 25 to a local port 9025</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -L 9025:localhost:25 patrick@remotehost
</pre>
</div>


<h3><strong>No command:</strong></h3>

<p>Sometimes you just want to setup a forward with having a shell</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -N -L 9025:localhost:25 patrick@remotehost
</pre>
</div>


<h3><strong>KeepAlive:</strong></h3>

<p>Getting tired of those timeouts by the firewall? Have ssh send a keepalive/</p>

<p>Put the following options in your $HOME/.ssh/ssh_config</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
    KeepAlive yes
    <span class="Keywords">ServerAliveInterval</span> <span class="Numbers">60</span>
</pre>
</div>


<h3><strong>Socks Daemon for proxying:</strong> (-D)</h3>

<p>Sometimes it's interesting to start a socks daemon. You can configure this in your browser to surf as it seems to come from the remote machine.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -D 9999 patrick@remotehost
</pre>
</div>


<h3><strong>Tunneling over an http proxy:</strong></h3>

<p>Corporate firewalls often only allow http to go outside. See <a href="http://www.agroman.net/corkscrew/">corkscrew</a></p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
<span class="Keywords">ProxyCommand</span> /usr/bin/corkscrew proxy-ip <span class="Numbers">8080</span> %h %p ~/.ssh/myauth
</pre>
</div>


<h3><strong>Chaining ssh hopping:</strong></h3>

<div class="UltraViolet">
<pre class="pastels_on_dark">
Host pc1.example.org pc2.example.org
<span class="Keywords">ForwardAgent</span> yes
<span class="Keywords">ProxyCommand</span> ssh -qax bastion.example.org /usr/bin/nc -w <span class="Numbers">120</span> %h %p
</pre>
</div>


<h3><strong>Netcat mode:</strong></h3>

<p>Starting from openssh 5.4: we can have ssh act as netcat. (-W) This connects stdio on the client to a single port forward on the server. This allows, for example, using ssh as a ProxyCommand to route connections via intermediate servers.”</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -p 443 -W remotehost2:23 patrick@remotehost
Trying remotehost2...
Connected to remotehost2.
Escape character is <span class="Strings"><span class="Strings">'</span>^]<span class="Strings">'</span></span>.

User Name : ^]
telnet<span class="Operators">&gt;</span> close
$

</pre>
</div>


<h3><strong>Mounting over ssh:</strong></h3>

<p>Sometimes it's nice to mount a remote directory over ssh. Fuse and sshfs are your friend</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ sshfs remote-user@remote.server:/remote/directory /mnt/remote-fs/
</pre>
</div>


<p><a href="http://fuse.sourceforge.net/sshfs.html">http://fuse.sourceforge.net/sshfs.html</a></p>

<h3><strong>VPN Tunneling:</strong></h3>

<p>Did you know that ssh can do layer 2 and 3 VPN tunneling?</p>

<p>Check out ssh -w. Example from manpage:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -f -w 0:1 192.168.1.15 true
$ ifconfig tun0 10.0.50.1 10.0.99.1 netmask 255.255.255.252
</pre>
</div>


<h3><strong>SSH http multiplexer:</strong></h3>

<p>sslh lets one accept both HTTPS and SSH connections on the same port. It makes it possible to connect to an SSH server on port 443 (e.g. from inside a corporate firewall) while still serving HTTPS on that port.
<a href="http://www.rutschle.net/tech/sslh.shtml">http://www.rutschle.net/tech/sslh.shtml</a></p>

<hr />


<h2>Speed</h2>

<h3><strong>Compression</strong></h3>

<p>If you are working on a slow link, compression (-C) and using a simple cipher (-c blowfish) saves you speed</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -C -c blowfish patrick@remotehost
</pre>
</div>


<h3><strong>Multiplexing - ControlMaster:</strong></h3>

<p>Another great way to speed up ssh is to re-use the same connection when you connect multiple times to the same host</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ mkdir –p <span class="Operators">~</span>/.ssh/connections
$ chmod 700 <span class="Operators">~</span>/.ssh/connections

Add this to your <span class="Operators">~</span>/.ssh/config file:
Host *
ControlMaster auto
ControlPath <span class="Operators">~</span>/.ssh/connections/%r_%h_%p
</pre>
</div>




<hr />


<h2>Managing keys</h2>

<h3><strong>Ignore Hostkeys:</strong></h3>

<p>When you're re-installing a machine over and over again, you often want to get rid of the hostfile key verification. This is what you need:</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh user@host -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
</pre>
</div>


<h3><strong>Check if hostkey exists:</strong></h3>

<div class="UltraViolet">
<pre class="pastels_on_dark">
k$ ssh-keygen -F 192.168.2.152
<span class="Comments"><span class="Comments">#</span> Host 192.168.2.152 found: line 31 type RSA</span>
192.168.2.152 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwHH15HpeJo21wyqpe2iFM8/0CtoYnE9DDXfCewws7iMhM+vgp7pjnaC83IgAt7G/x/VDHcbnyuI4odrGSEAE5wm7LNuT6uSfQMbXCayE+uoOIrAVhf41ZnAFQrs/+Mutk5LFEjPPNhuriq5ltBT4UwMlYQMa5z/SzmxV0ZAGXks5GMDz0o89yUwRarRfsGudASEtzUxgnxnOo5STBMZOdQ0GNEVdfJDgfJDAOi34T1FidpCqAtm8akYuB+Qsj3/hDQmIT+GsKYaGNZvz8ZNnPBAc9kWlS6VqXXNreyEeu7AmHDWXjMP3NW1tsibmZ8zeOSZdmEVEiuaYCIvERDq3MQ==
</pre>
</div>


<h3><strong>Remove a hostkey:</strong></h3>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh-keygen -R 192.168.2.152
/Users/patrick/.ssh/known_hosts updated.
Original contents retained as /Users/patrick/.ssh/known_hosts.old
</pre>
</div>


<h3><strong>Get hostkey of remote server:</strong></h3>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh-keyscan remotehost
<span class="Comments"><span class="Comments">#</span> remotehost SSH-2.0-OpenSSH_5.2</span>
remotehost ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAyREFGMBB6Qi1uoEYIk4GlqLXdS26moAxmV69UX0icQjp0Rw53xZ/2L0ZQwhsUiFV1vq4QfZNeUO142IzBgSspgsJZ7wJq213tsE7WIJGIBqvWnhU3vJuL9wgYT8f6BAvLoEfapFhLy24TDmn2DXldJAYgo8MnUbRrJlvnhQZPpd5cDWCXkzPGQE8r7REZsAWbWNlVOFRvZioPoGCGYMtsDWSBelBISGkedoNpTSpRkMmBAnsHBfvIzDPoTDYL4PZR0jJ8MaJrDhRtD4caRw4HVyhzSa3/FCpcm09PyBRabH/CyxNSOZjLc2+N9Ph9AKeTNgvmxP70wx668XaGYwCrQ==
</pre>
</div>


<h3><strong>SSH DNS Keys</strong></h3>

<p>Instead of using your local hostfile, you can store your keys in DNS. Have a look at <a href="http://freshmeat.net/projects/sshfp/">sshfp</a> to do the job. Then you can specify that ssh needs to</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh localhost -o <span class="Strings"><span class="Strings">&quot;</span>VerifyHostKeyDNS=yes<span class="Strings">&quot;</span></span>
yes authenticity of host <span class="Strings"><span class="Strings">'</span>localhost (127.0.0.1)<span class="Strings">'</span></span> can<span class="Strings"><span class="Strings">'</span>t be established.</span>
<span class="Strings">RSA key fingerprint is 2d:d3:29:bd:4d:e2:7d:a3:b0:15:96:26:d4:60:13:34.</span>
<span class="Strings">Matching host key fingerprint found in DNS.</span>
<span class="Strings">Are you sure you want to continue connecting (yes/no)?</span>
</pre>
</div>


<h3><strong>SSH Escape Sequences:</strong></h3>

<p>It often happens to me that I'm working into an ssh shell that used forwarding. I always thought there was no way to change the forwarding rules and that I had to logout. It seems not! SSh has an internal shell activated by a tilde. Seeing is believing!</p>

<p>Escape sequences are only recognized after a newline and are initiated with a tilde (~) unless you modify it with the -e flag.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
Hit ENTER ~? on a running ssh session to see a list of escapes:

Supported escape sequences:

~. – terminate connection
~B – send a BREAK to the remote system
~C – open a command line
~R – Request rekey (SSH protocol 2 only)
~^Z – suspend ssh
~# – list forwarded connections
~&amp; – background ssh (when waiting for connections to terminate)
~? – this message
~~ – send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)
~. and ~# are particularly useful.
</pre>
</div>


<h3><strong>Visualize hostkeys:</strong></h3>

<p>Every host key has it's own visual fingerprint</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ssh -o VisualHostKey=yes patrick@localhost
Host key fingerprint is 9f:a0:03:c1:63:8b:b8:c6:d6:83:cb:22:33:cb:83:cc
+--[ RSA 2048]----+
<span class="Operators">|</span>                 <span class="Operators">|</span>
<span class="Operators">|</span>   .             <span class="Operators">|</span>
<span class="Operators">|</span>    =            <span class="Operators">|</span>
<span class="Operators">|</span> . o +           <span class="Operators">|</span>
<span class="Operators">|</span>. . o   S        <span class="Operators">|</span>
<span class="Operators">|</span>..o  . . o .     <span class="Operators">|</span>
<span class="Operators">|</span>== o  o   o      <span class="Operators">|</span>
<span class="Operators">|</span>@E. .  .         <span class="Operators">|</span>
<span class="Operators">|</span>+B.              <span class="Operators">|</span>
+-----------------+
</pre>
</div>




<hr />


<h2>Security hacks</h2>

<h3><strong>Local Password sniffing:</strong></h3>

<p>If you have process that connects to your ssh and you want to see the password it's using, then strace is your friend.</p>

<div class="UltraViolet">
<pre class="pastels_on_dark">
$ ps axuww <span class="Operators">|</span> egrep <span class="Strings"><span class="Strings">'</span>PID|ssh<span class="Strings">'</span></span>
<span class="Comments"><span class="Comments">#</span>Now become root and attach to the running daemon with strace, changing the PID as appropriate:</span>

$ sudo strace -f -e <span class="Strings"><span class="Strings">'</span>read,write<span class="Strings">'</span></span> -p12345
</pre>
</div>


<h3><strong>Remote Password sniffing:</strong></h3>

<p>A more passive way of listening into ssh sessions (v1) is using dsniff
- <a href="http://www.allguru.net/security/running-network-sniffer-dsniff/">Dsniff</a></p>

<h3><strong>Fingerprint fuzzing:</strong></h3>

<p>This one is to lure a lazy administrator into accepting your certificate. It generates keys with an almost similar fingerprint.
<a href="http://freeworld.thc.org/papers/ffp.html">http://freeworld.thc.org/papers/ffp.html</a></p>

<h3><strong>SSH Honeypot:</strong></h3>

<p>And to go totally security. Launch your own ssh honeypot and capture all the remote commands (and typos) with Kippo</p>

<ul>
<li><a href="http://code.google.com/p/kippo/">http://code.google.com/p/kippo/</a></li>
<li><a href="http://www.securitytube.net/SSH-Password-Capture-using-Kippo-video.aspx">http://www.securitytube.net/SSH-Password-Capture-using-Kippo-video.aspx</a></li>
</ul>


<hr />


<h2>Need more?</h2>

<p><a href="http://www.mynitor.com/2010/08/16/top-50-ssh-helper-tools-omg/">Top 50 SSH Helper tools - OMG!</a></p>

<hr />


<h2>Share yours! I'm definitely interested</h2>
]]></content:encoded>
			<wfw:commentRss>http://www.planetdevops.net/?feed=rss2&amp;p=6342</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webby Rss feed and Syntax Highlighting</title>
		<link>http://feedproxy.google.com/~r/jedi/IZwx/~3/RLosc2d9UPg/</link>
		<comments>http://feedproxy.google.com/~r/jedi/IZwx/~3/RLosc2d9UPg/#comments</comments>
		<pubDate>Thu, 26 Aug 2010 14:37:23 +0000</pubDate>
		<dc:creator>JEDI - Just Enough Developed Infrastructure</dc:creator>
				<category><![CDATA[coderay]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[syntax highlighting]]></category>
		<category><![CDATA[webby]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.jedi.be/blog/2010/08/26/WebbyRssfeedandSyntaxHighlighting/</guid>
		<description><![CDATA[When I first started blogging I used Wordpress, while it was nice at that time, it felt rather cumbersome to use for posting technical stuff like code samples. Also having everything in the database make it difficult to use my favorite text editor to m...]]></description>
			<content:encoded><![CDATA[<p>When I first started blogging I used <a href="http://www.wordpress.org">Wordpress</a>, while it was nice at that time, it felt rather cumbersome to use for posting technical stuff like code samples. Also having everything in the database make it difficult to use my favorite text editor to manage my content. So I decided to move to <a href="http://feedproxy.google.com/~r/jedi/IZwx/~3/RLosc2d9UPg/webby.rubyforge.org/">Webby</a> : <em>it allows you to use the power of ruby erb inside you html pages without the overkill of running a rails</em> Another advantage is that it creates static html so it's both fast and secure.</p>

<p>I've been running it now for more then a year and have been happy ever since. This blogpost shares some of my scripts/enhancements I've used:</p>

<ul>
<li><p><strong>Wordpress exporter to Webby</strong> : this was my first challenge, how do I get everything from my wordpress out of that database. I wrote a little script that reads from the RSS feed of the wordpress and export everything into webby structure . It's not the most robust script (it was early stages ruby for me at that time), but you'll get the idea.</p></li>
<li><p><strong>RSS feed in Webby</strong>: I didn't find any good rss feed code, most of it didn't pass the rss validation. So here you can find my take on it. As a bonus the script tries to make your images absolute, which is important for having your images displayed in some rss feedreaders.</p></li>
<li><p><strong>Highlighting with <a href="http://coderay.rubychan.de/">Coderay</a></strong> : webby includes a way to highlight parts of the code. This works very well, but I found myself missing a way to include a file instead of pasting the code directly into the blogpost. This has many advantages: I can edit the file separate and the correct syntax  highlighting in my favorite text editor still works. And the escaping works better for ruby code as there can not be a problem with escaping special characters. After a while I switched to <a href="http://ultraviolet.rubyforge.org/">Ultraviolet</a> because it has way more syntaxes supported. The downside is that it requires the onigurama library . This isn't really a problem on Mac using Macports.</p></li>
</ul>


<div class="UltraViolet">
<pre class="pastels_on_dark">
patricks-iMac:jedi-webby patrick$ sudo port install oniguruma4
patricks-iMac:jedi-webby patrick$ gem install ultraviolet -- -I/opt/local/lib
Building native extensions.  This could take a <span class="ControlStructures">while</span>...
ERROR:  Error installing ultraviolet:
    ERROR: Failed to build gem native extension.

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby extconf.rb -I/opt/local/lib
checking <span class="ControlStructures">for</span> main() <span class="ControlStructures">in</span> -lonig... no
creating Makefile

make
gcc -I. -I. -I/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE   -fno-common -Wall  -c oregexp.c
oregexp.c:2:23: error: oniguruma.h: No such file or directory

<span class="Comments"><span class="Comments">#</span>Solution</span>
patricks-iMac:jedi-webby patrick$ gem install ultraviolet -- --with-opt-dir=/opt/local
</pre>
</div>


<p>This is all for now.</p>

<p><em>Codify helper (with Ultraviolet): put inside your webby-root/lib</em></p>

<div class="UltraViolet">
<pre class="pastels_on_dark"><span class="Comments"><span class="Comments">#</span> require uv</span>
<span class="ControlStructures">if</span> try_require <span class="Strings"><span class="Strings">'</span>uv<span class="Strings">'</span></span>
<span class="Keywords">require</span> <span class="Strings"><span class="Strings">'</span>enumerator<span class="Strings">'</span></span>

Loquacious.configuration_for(<span class="Constants"><span class="Constants">:</span>webby</span>) {
  desc <span class="Strings"><span class="Strings">&lt;&lt;-__</span></span>
<span class="Strings">    Options for CodeRay syntax highlighting. See the CodeRay home page</span>
<span class="Strings">    (http://coderay.rubychan.de/) for more information about the available</span>
<span class="Strings">    options.</span>
<span class="Strings"><span class="Strings">  __</span></span>
  codify {
    desc <span class="Strings"><span class="Strings">'</span>The language being highlighted (given as a symbol).<span class="Strings">'</span></span>
    lang <span class="Constants"><span class="Constants">:</span>ruby</span>

    desc <span class="Strings"><span class="Strings">'</span>The file you want to read instead of a string<span class="Strings">'</span></span>
    lang <span class="Constants"><span class="Constants">:</span>file</span>

    desc <span class="Strings"><span class="Strings">'</span>Include line numbers in :table, :inline, :list or nil (no line numbers).<span class="Strings">'</span></span>
    line_numbers <span class="LanguageConstants">nil</span>

    desc <span class="Strings"><span class="Strings">'</span>Where to start line number counting.<span class="Strings">'</span></span>
    line_number_start <span class="Numbers">1</span>

    desc <span class="Strings"><span class="Strings">'</span>Make every N-th number appear bold.<span class="Strings">'</span></span>
    bold_every <span class="Numbers">10</span>

    desc <span class="Strings"><span class="Strings">'</span>Tabs will be converted into this number of space characters.<span class="Strings">'</span></span>
    tab_width <span class="Numbers">8</span>
  }
}

<span class="ControlStructures">module</span> Webby::Helpers
<span class="ControlStructures">module</span> CodifyHelper

<span class="Comments">  <span class="Comments">#</span> The +codify+ method applies syntax highlighting to source code embedded</span>
<span class="Comments">  <span class="Comments">#</span> in a webpage. The CodeRay highlighting engine is used for the HTML</span>
<span class="Comments">  <span class="Comments">#</span> markup of the source code. The page sections to be highlighted are given</span>
<span class="Comments">  <span class="Comments">#</span> as blocks of text to the +coderay+ method.</span>
<span class="Comments">  <span class="Comments">#</span></span>
<span class="Comments">  <span class="Comments">#</span> Options can be passed to the CodeRay engine via attributes in the</span>
<span class="Comments">  <span class="Comments">#</span> +codify+ method.</span>
<span class="Comments">  <span class="Comments">#</span></span>
<span class="Comments">  <span class="Comments">#</span>    &lt;% codify( :lang =&gt; &quot;ruby&quot;, :line_numbers =&gt; &quot;inline&quot; ) do -%&gt;</span>
<span class="Comments">  <span class="Comments">#</span>    # Initializer for the class.</span>
<span class="Comments">  <span class="Comments">#</span>    def initialize( string )</span>
<span class="Comments">  <span class="Comments">#</span>      @str = stirng</span>
<span class="Comments">  <span class="Comments">#</span>    end</span>
<span class="Comments">  <span class="Comments">#</span>    &lt;% end -%&gt;</span>
<span class="Comments">  <span class="Comments">#</span>    </span>
<span class="Comments">  <span class="Comments">#</span> The supported Codify options are the following:</span>
<span class="Comments">  <span class="Comments">#</span></span>
<span class="Comments">  <span class="Comments">#</span>    :lang               : the language to highlight (ruby, c, html, ...)</span>
<span class="Comments">  <span class="Comments">#</span>    :file               : the file to highlight</span>
<span class="Comments">  <span class="Comments">#</span>    :line_numbers       : include line numbers in 'table', 'inline',</span>
<span class="Comments">  <span class="Comments">#</span>                          or 'list'</span>
<span class="Comments">  <span class="Comments">#</span>    :line_number_start  : where to start with line number counting</span>
<span class="Comments">  <span class="Comments">#</span>    :bold_every         : make every n-th number appear bold</span>
<span class="Comments">  <span class="Comments">#</span>    :tab_width          : convert tab characters to n spaces</span>
<span class="Comments">  <span class="Comments">#</span></span>
  
  <span class="ControlStructures">def</span> codify(<span class="Variables"> <span class="Operators">*</span>args<span class="Variables">,</span> <span class="Operators">&amp;</span>block </span>)
    opts <span class="Operators">=</span> args.last.instance_of?(<span class="Variables">Hash</span>) <span class="Operators">?</span> args.pop : {}

    parent<span class="Operators">=</span>File.dirname(<span class="Variables"><span class="Variables">@</span>page</span>.path)
     file<span class="Operators">=</span>opts[<span class="Constants"><span class="Constants">:</span>file</span>]
    text<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span><span class="Strings">&quot;</span></span>
    <span class="ControlStructures">if</span> (!file.nil?) 
      <span class="ControlStructures">begin</span>
        filename<span class="Operators">=</span>parent<span class="Operators">+</span>File::SEPARATOR<span class="Operators">+</span>file
        file<span class="Operators">=</span>File.open(filename,<span class="Strings"><span class="Strings">&quot;</span>rb<span class="Strings">&quot;</span></span>)
        text<span class="Operators">=</span>file.read
        syntax<span class="Operators">=</span>guess_syntax(filename)
        <span class="ControlStructures">if</span> <span class="Operators">!</span>syntax.nil? <span class="Operators">&amp;&amp;</span> opts[<span class="Constants"><span class="Constants">:</span>lang</span>].nil? <span class="ControlStructures">then</span>
          opts[<span class="Constants"><span class="Constants">:</span>lang</span>]<span class="Operators">=</span>syntax
       <span class="ControlStructures">end</span>
      <span class="ControlStructures">rescue</span>
        puts <span class="Strings"><span class="Strings">&quot;</span>Error reading code file<span class="Strings">&quot;</span></span><span class="Operators">+</span>filename
      <span class="ControlStructures">end</span>
    <span class="ControlStructures">else</span>
      text <span class="Operators">=</span> capture_erb(<span class="Operators">&amp;</span>block)
    <span class="ControlStructures">end</span>
    
    <span class="ControlStructures">return</span> <span class="ControlStructures">if</span> text.empty?

   defaults <span class="Operators">=</span> { <span class="Constants"><span class="Constants">:</span>lang</span> =&gt; <span class="Strings"><span class="Strings">&quot;</span>ruby<span class="Strings">&quot;</span></span>, <span class="Constants"><span class="Constants">:</span>line_numbers</span> =&gt; <span class="LanguageConstants">false</span> , <span class="Constants"><span class="Constants">:</span>theme</span> =&gt; <span class="Strings"><span class="Strings">&quot;</span>mac_classic<span class="Strings">&quot;</span></span>}
   lang <span class="Operators">=</span> opts.getopt(<span class="Constants"><span class="Constants">:</span>lang</span>, defaults[<span class="Constants"><span class="Constants">:</span>lang</span>]).to_s
   line_numbers <span class="Operators">=</span> opts.getopt(<span class="Constants"><span class="Constants">:</span>line_numbers</span>, defaults[<span class="Constants"><span class="Constants">:</span>line_numbers</span>])
   theme <span class="Operators">=</span> opts.getopt(<span class="Constants"><span class="Constants">:</span>theme</span>, defaults[<span class="Constants"><span class="Constants">:</span>theme</span>])

    lang<span class="Operators">=</span><span class="ControlStructures">case</span> lang
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>shell<span class="Strings">&quot;</span></span>,<span class="Strings"><span class="Strings">&quot;</span>sh<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Strings"><span class="Strings">&quot;</span>shell-unix-generic<span class="Strings">&quot;</span></span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>text<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>plain_text</span>
      <span class="ControlStructures">else</span>
        lang
      <span class="ControlStructures">end</span>
    out <span class="Operators">=</span> <span class="Strings"><span class="Strings">%Q{</span>&lt;div class=&quot;UltraViolet&quot;&gt;<span class="CharacterConstants">\n</span><span class="Strings">}</span></span>
    out <span class="Operators">&lt;&lt;</span> Uv.parse(text, <span class="Strings"><span class="Strings">&quot;</span>xhtml<span class="Strings">&quot;</span></span>, lang.to_s, <span class="LanguageConstants">false</span>,<span class="Strings"><span class="Strings">&quot;</span>pastels_on_dark<span class="Strings">&quot;</span></span>)
    out <span class="Operators">&lt;&lt;</span> <span class="Strings"><span class="Strings">%Q{</span><span class="CharacterConstants">\n</span>&lt;/div&gt;<span class="Strings">}</span></span>

<span class="Comments">    <span class="Comments">#</span> put some guards around the output (specifically for textile)</span>
    out <span class="Operators">=</span> _guard(out)

    concat_erb(out, block.binding)
    <span class="ControlStructures">return</span>
  <span class="ControlStructures">end</span>

  <span class="ControlStructures">def</span> guess_syntax(<span class="Variables">filename</span>)
    filetype<span class="Operators">=</span>Uv.syntax_for_file(filename)[<span class="Numbers">0</span>][<span class="Numbers">0</span>]
    <span class="ControlStructures">return</span> filetype

  <span class="ControlStructures">end</span>

<span class="ControlStructures">end</span>  <span class="Comments"><span class="Comments">#</span> module CodefyHelper</span>

register(<span class="Variables">CodifyHelper</span>)

<span class="ControlStructures">end</span>  <span class="Comments"><span class="Comments">#</span> module Webby::Helpers</span>
<span class="ControlStructures">end</span>  <span class="Comments"><span class="Comments">#</span> try_require</span>

<span class="Comments"><span class="Comments">#</span> EOF</span>
</pre>
</div>


<p><em>Codify helper (with Coderay): put inside your webby-root/lib</em></p>

<div class="UltraViolet">
<pre class="pastels_on_dark"><span class="ControlStructures">if</span> try_require <span class="Strings"><span class="Strings">'</span>coderay<span class="Strings">'</span></span>
<span class="Keywords">require</span> <span class="Strings"><span class="Strings">'</span>enumerator<span class="Strings">'</span></span>

Loquacious.configuration_for(<span class="Constants"><span class="Constants">:</span>webby</span>) {
  desc <span class="Strings"><span class="Strings">&lt;&lt;-__</span></span>
<span class="Strings">    Options for CodeRay syntax highlighting. See the CodeRay home page</span>
<span class="Strings">    (http://coderay.rubychan.de/) for more information about the available</span>
<span class="Strings">    options.</span>
<span class="Strings"><span class="Strings">  __</span></span>
  codify {
    desc <span class="Strings"><span class="Strings">'</span>The language being highlighted (given as a symbol).<span class="Strings">'</span></span>
    lang <span class="Constants"><span class="Constants">:</span>ruby</span>

    desc <span class="Strings"><span class="Strings">'</span>The file you want to read instead of a string<span class="Strings">'</span></span>
    lang <span class="Constants"><span class="Constants">:</span>file</span>

    desc <span class="Strings"><span class="Strings">'</span>Include line numbers in :table, :inline, :list or nil (no line numbers).<span class="Strings">'</span></span>
    line_numbers <span class="LanguageConstants">nil</span>

    desc <span class="Strings"><span class="Strings">'</span>Where to start line number counting.<span class="Strings">'</span></span>
    line_number_start <span class="Numbers">1</span>

    desc <span class="Strings"><span class="Strings">'</span>Make every N-th number appear bold.<span class="Strings">'</span></span>
    bold_every <span class="Numbers">10</span>

    desc <span class="Strings"><span class="Strings">'</span>Tabs will be converted into this number of space characters.<span class="Strings">'</span></span>
    tab_width <span class="Numbers">8</span>
  }
}

<span class="ControlStructures">module</span> Webby::Helpers
<span class="ControlStructures">module</span> CodifyHelper

<span class="Comments">  <span class="Comments">#</span> The +codify+ method applies syntax highlighting to source code embedded</span>
<span class="Comments">  <span class="Comments">#</span> in a webpage. The CodeRay highlighting engine is used for the HTML</span>
<span class="Comments">  <span class="Comments">#</span> markup of the source code. The page sections to be highlighted are given</span>
<span class="Comments">  <span class="Comments">#</span> as blocks of text to the +coderay+ method.</span>
<span class="Comments">  <span class="Comments">#</span></span>
<span class="Comments">  <span class="Comments">#</span> Options can be passed to the CodeRay engine via attributes in the</span>
<span class="Comments">  <span class="Comments">#</span> +codify+ method.</span>
<span class="Comments">  <span class="Comments">#</span></span>
<span class="Comments">  <span class="Comments">#</span>    &lt;% codify( :lang =&gt; &quot;ruby&quot;, :line_numbers =&gt; &quot;inline&quot; ) do -%&gt;</span>
<span class="Comments">  <span class="Comments">#</span>    # Initializer for the class.</span>
<span class="Comments">  <span class="Comments">#</span>    def initialize( string )</span>
<span class="Comments">  <span class="Comments">#</span>      @str = stirng</span>
<span class="Comments">  <span class="Comments">#</span>    end</span>
<span class="Comments">  <span class="Comments">#</span>    &lt;% end -%&gt;</span>
<span class="Comments">  <span class="Comments">#</span>    </span>
<span class="Comments">  <span class="Comments">#</span> The supported Codify options are the following:</span>
<span class="Comments">  <span class="Comments">#</span></span>
<span class="Comments">  <span class="Comments">#</span>    :lang               : the language to highlight (ruby, c, html, ...)</span>
<span class="Comments">  <span class="Comments">#</span>    :file               : the file to highlight</span>
<span class="Comments">  <span class="Comments">#</span>    :line_numbers       : include line numbers in 'table', 'inline',</span>
<span class="Comments">  <span class="Comments">#</span>                          or 'list'</span>
<span class="Comments">  <span class="Comments">#</span>    :line_number_start  : where to start with line number counting</span>
<span class="Comments">  <span class="Comments">#</span>    :bold_every         : make every n-th number appear bold</span>
<span class="Comments">  <span class="Comments">#</span>    :tab_width          : convert tab characters to n spaces</span>
<span class="Comments">  <span class="Comments">#</span></span>
  
  <span class="ControlStructures">def</span> codify(<span class="Variables"> <span class="Operators">*</span>args<span class="Variables">,</span> <span class="Operators">&amp;</span>block </span>)
    opts <span class="Operators">=</span> args.last.instance_of?(<span class="Variables">Hash</span>) <span class="Operators">?</span> args.pop : {}

    parent<span class="Operators">=</span>File.dirname(<span class="Variables"><span class="Variables">@</span>page</span>.path)
     file<span class="Operators">=</span>opts[<span class="Constants"><span class="Constants">:</span>file</span>]
    text<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span><span class="Strings">&quot;</span></span>
    <span class="ControlStructures">if</span> (!file.nil?) 
      <span class="ControlStructures">begin</span>
        filename<span class="Operators">=</span>parent<span class="Operators">+</span>File::SEPARATOR<span class="Operators">+</span>file
        file<span class="Operators">=</span>File.open(filename,<span class="Strings"><span class="Strings">&quot;</span>rb<span class="Strings">&quot;</span></span>)
        text<span class="Operators">=</span>file.read
        syntax<span class="Operators">=</span>guess_syntax(filename)
        <span class="ControlStructures">if</span> <span class="Operators">!</span>syntax.nil? <span class="Operators">&amp;&amp;</span> opts[<span class="Constants"><span class="Constants">:</span>lang</span>].nil? <span class="ControlStructures">then</span>
          opts[<span class="Constants"><span class="Constants">:</span>lang</span>]<span class="Operators">=</span>syntax
       <span class="ControlStructures">end</span>
      <span class="ControlStructures">rescue</span>
        puts <span class="Strings"><span class="Strings">&quot;</span>Error reading code file<span class="Strings">&quot;</span></span><span class="Operators">+</span>filename
      <span class="ControlStructures">end</span>
    <span class="ControlStructures">else</span>
      text <span class="Operators">=</span> capture_erb(<span class="Operators">&amp;</span>block)
    <span class="ControlStructures">end</span>
    
    <span class="ControlStructures">return</span> <span class="ControlStructures">if</span> text.empty?

    defaults <span class="Operators">=</span> ::Webby.site.coderay
    lang <span class="Operators">=</span> opts.getopt(<span class="Constants"><span class="Constants">:</span>lang</span>, defaults.lang).to_sym

    cr_opts <span class="Operators">=</span> {}
    <span class="Strings"><span class="Strings">%w(</span>line_numbers       to_sym</span>
<span class="Strings">       line_number_start  to_i</span>
<span class="Strings">       bold_every         to_i</span>
<span class="Strings">       tab_width          to_i<span class="Strings">)</span></span>.each_slice(<span class="Numbers">2</span>) <span class="ControlStructures">do </span>|<span class="Variables">key</span>,<span class="Variables">convert</span>|
      key <span class="Operators">=</span> key.to_sym
      val <span class="Operators">=</span> opts.getopt(key, defaults[key])
      <span class="ControlStructures">next</span> <span class="ControlStructures">if</span> val.nil?
      cr_opts[key] <span class="Operators">=</span> val.send(convert)
    <span class="ControlStructures">end</span>

<span class="Comments">    <span class="Comments">#</span>cr.swap(CodeRay.scan(text, lang).html(opts).div)</span>
    out <span class="Operators">=</span> <span class="Strings"><span class="Strings">%Q{</span>&lt;div class=&quot;CodeRay&quot;&gt;<span class="CharacterConstants">\n</span>&lt;pre&gt;<span class="Strings">}</span></span>
    out <span class="Operators">&lt;&lt;</span> ::CodeRay.scan(text, lang).html(cr_opts)
    out <span class="Operators">&lt;&lt;</span> <span class="Strings"><span class="Strings">%Q{</span>&lt;/pre&gt;<span class="CharacterConstants">\n</span>&lt;/div&gt;<span class="Strings">}</span></span>

<span class="Comments">    <span class="Comments">#</span> put some guards around the output (specifically for textile)</span>
    out <span class="Operators">=</span> _guard(out)

    concat_erb(out, block.binding)
    <span class="ControlStructures">return</span>
  <span class="ControlStructures">end</span>

  <span class="ControlStructures">def</span> guess_syntax(<span class="Variables">filename</span>)
    extension<span class="Operators">=</span><span class="ControlStructures">case</span> File.extname(filename).downcase
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.rb<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>ruby</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.html<span class="Strings">&quot;</span></span>,<span class="Strings"><span class="Strings">&quot;</span>.html<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>html</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.sh<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>sh</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.css<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>css</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.js<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>java_script</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.diff<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>diff</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.yaml<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>yaml</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.json<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>json</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.java<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>java</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.xml<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>xml</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.txt<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>plaintext</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.py<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>python</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.xml<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>xml</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.c<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>c</span>
      <span class="ControlStructures">when</span> <span class="Strings"><span class="Strings">&quot;</span>.sql<span class="Strings">&quot;</span></span> <span class="ControlStructures">then</span> <span class="Constants"><span class="Constants">:</span>sql</span>
      <span class="ControlStructures">else</span> <span class="LanguageConstants">nil</span>
    <span class="ControlStructures">end</span>
    <span class="ControlStructures">return</span> extension

  <span class="ControlStructures">end</span>

<span class="ControlStructures">end</span>  <span class="Comments"><span class="Comments">#</span> module CodefyHelper</span>

register(<span class="Variables">CodifyHelper</span>)

<span class="ControlStructures">end</span>  <span class="Comments"><span class="Comments">#</span> module Webby::Helpers</span>
<span class="ControlStructures">end</span>  <span class="Comments"><span class="Comments">#</span> try_require</span>

<span class="Comments"><span class="Comments">#</span> EOF</span>
</pre>
</div>


<p><em>Rss feed file</em></p>

<div class="UltraViolet">
<pre class="pastels_on_dark"><span class="Operators">-</span><span class="Operators">-</span><span class="Operators">-</span>
title:     <span class="Variables">JEDI</span> <span class="Operators">-</span> <span class="Variables">Just</span> <span class="Variables">Enough</span> <span class="Variables">Developed</span> <span class="Variables">Infrastructure</span>
subtitle:  www.jedi.be
description: development, infrastructure <span class="Operators">and</span> other stuff
site:      www.jedi.be
author:    <span class="Variables">Patrick</span> <span class="Variables">Debois</span>
email:     Patrick.Debois<span class="Variables"><span class="Variables">@</span>jedi</span>.be
extension: xml
layout:    <span class="LanguageConstants">nil</span>
dirty:     <span class="LanguageConstants">true</span>
filter:    
<span class="Operators">-</span> erb
<span class="Comments"><span class="Comments">#</span> &lt;?xml-stylesheet type=&quot;text/css&quot; media=&quot;screen&quot; href=&quot;http://www.jedi.be/css/blueprint/screen.css&quot;?&gt;</span>
<span class="Operators">-</span><span class="Operators">-</span><span class="Operators">-</span>
<span class="Operators">&lt;</span><span class="Strings"><span class="Strings">%-</span> require 'rexml/document' <span class="Strings">-</span></span><span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?<span class="Strings">&gt;</span></span>
<span class="Operators">&lt;</span>rss version<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span>2.0<span class="Strings">&quot;</span></span> xmlns<span class="Constants"><span class="Constants">:</span>atom=</span><span class="Strings"><span class="Strings">&quot;</span>http://www.w3.org/2005/Atom<span class="Strings">&quot;</span></span> xmlns<span class="Constants"><span class="Constants">:</span>content=</span><span class="Strings"><span class="Strings">&quot;</span>http://purl.org/rss/1.0/modules/content/<span class="Strings">&quot;</span></span> xmlns<span class="Constants"><span class="Constants">:</span>wfw=</span><span class="Strings"><span class="Strings">&quot;</span>http://wellformedweb.org/CommentAPI/<span class="Strings">&quot;</span></span> xmlns<span class="Constants"><span class="Constants">:</span>dc=</span><span class="Strings"><span class="Strings">&quot;</span>http://purl.org/dc/elements/1.1/<span class="Strings">&quot;</span></span><span class="Operators">&gt;</span>
    <span class="Operators">&lt;</span>channel<span class="Operators">&gt;</span>
        <span class="Operators">&lt;</span>atom<span class="Constants"><span class="Constants">:</span>link</span> href<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span>http://www.jedi.be/blog/feed/<span class="Strings">&quot;</span></span> rel<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span>self<span class="Strings">&quot;</span></span> type<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span>application/rss+xml<span class="Strings">&quot;</span></span> <span class="Operators">/</span><span class="Operators">&gt;</span>
        <span class="Operators">&lt;</span>title&gt;<span class="Operators">&lt;</span><span class="Operators">%=</span> h(<span class="Variables"><span class="Variables">@</span>page</span>.title) <span class="Strings"><span class="Strings">%&gt;</span>&lt;/title<span class="Strings">&gt;</span></span>
        <span class="Operators">&lt;</span>description&gt;<span class="Operators">&lt;</span><span class="Operators">%=</span> h(<span class="Variables"><span class="Variables">@</span>page</span>.description) <span class="Strings"><span class="Strings">%&gt;</span> &lt;/description<span class="Strings">&gt;</span></span>
        <span class="Operators">&lt;</span>link<span class="Operators">&gt;</span>http<span class="Constants"><span class="Constants">:</span>/</span><span class="Operators">/</span><span class="Operators">&lt;</span><span class="Operators">%=</span> <span class="Variables"><span class="Variables">@</span>page</span>.site <span class="Strings"><span class="Strings">%&gt;</span>/blog&lt;/link<span class="Strings">&gt;</span></span>
        <span class="Operators">&lt;</span>pubDate&gt;<span class="Operators">&lt;</span><span class="Operators">%=</span> Time.now.gmtime.rfc822 <span class="Strings"><span class="Strings">%&gt;</span>&lt;/pubDate<span class="Strings">&gt;</span></span>
        <span class="Operators">&lt;</span>generator<span class="Operators">&gt;</span>webby rss script<span class="Operators">&lt;</span><span class="Operators">/</span>generator<span class="Operators">&gt;</span>
        <span class="Operators">&lt;</span>lastBuildDate&gt;<span class="Operators">&lt;</span><span class="Operators">%=</span> Time.now.gmtime.rfc822 <span class="Strings"><span class="Strings">%&gt;</span>&lt;/lastBuildDate<span class="Strings">&gt;</span></span>
        <span class="Operators">&lt;</span>managingEditor&gt;<span class="Operators">&lt;</span><span class="Operators">%=</span> <span class="Variables"><span class="Variables">@</span>page</span>.email <span class="Strings"><span class="Strings">%&gt;</span> (&lt;%= @page.author %<span class="Strings">&gt;</span></span>)<span class="Operators">&lt;</span><span class="Operators">/</span>managingEditor<span class="Operators">&gt;</span>
        <span class="Operators">&lt;</span>webMaster&gt;<span class="Operators">&lt;</span><span class="Operators">%=</span> <span class="Variables"><span class="Variables">@</span>page</span>.email <span class="Strings"><span class="Strings">%&gt;</span> (&lt;%= @page.author %<span class="Strings">&gt;</span></span>)<span class="Operators">&lt;</span><span class="Operators">/</span>webMaster<span class="Operators">&gt;</span>
        <span class="Operators">&lt;</span>language<span class="Operators">&gt;</span>en<span class="Operators">&lt;</span><span class="Operators">/</span>language<span class="Operators">&gt;</span>
     <span class="Operators">&lt;</span><span class="Strings"><span class="Strings">%-</span> @pages.find( :limit =&gt; 10,</span>
<span class="Strings">       :in_directory =&gt; 'blog',</span>
<span class="Strings">       :recursive =&gt; true,</span>
<span class="Strings">       :sort_by =&gt; 'created_at',</span>
<span class="Strings">       :reverse =&gt; true).each do |article|</span>
<span class="Strings"></span>
<span class="Strings">       next if article.blog_post.nil?</span>
<span class="Strings">   <span class="Strings">-</span></span><span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">      &lt;item<span class="Strings">&gt;</span></span>
            <span class="Operators">&lt;</span>title&gt;<span class="Operators">&lt;</span><span class="Operators">%=</span> h(article.title) <span class="Strings"><span class="Strings">%&gt;</span>&lt;/title<span class="Strings">&gt;</span></span>
            <span class="Operators">&lt;</span>link<span class="Operators">&gt;</span>http<span class="Constants"><span class="Constants">:</span>/</span><span class="Operators">/</span><span class="Operators">&lt;</span><span class="Operators">%=</span> <span class="Variables"><span class="Variables">@</span>page</span>.site <span class="Strings"><span class="Strings">%&gt;</span>&lt;%= article.url %<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span><span class="Operators">/</span>link<span class="Operators">&gt;</span>
            <span class="Operators">&lt;</span><span class="Operators">%</span> <span class="ControlStructures">if</span> article.guid.nil? <span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">          &lt;guid isPermaLink=&quot;false&quot;<span class="Strings">&gt;</span></span>http<span class="Constants"><span class="Constants">:</span>/</span><span class="Operators">/</span><span class="Operators">&lt;</span><span class="Operators">%=</span> <span class="Variables"><span class="Variables">@</span>page</span>.site <span class="Strings"><span class="Strings">%&gt;</span>&lt;%= article.url%<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span><span class="Operators">/</span>guid<span class="Operators">&gt;</span>
            <span class="Operators">&lt;</span><span class="Operators">%</span> <span class="ControlStructures">else</span> <span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">          &lt;guid isPermaLink=&quot;false&quot;<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span><span class="Operators">%=</span> article.guid <span class="Strings"><span class="Strings">%&gt;</span>&lt;/guid<span class="Strings">&gt;</span></span>
            <span class="Operators">&lt;</span><span class="Operators">%</span> <span class="ControlStructures">end</span> <span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">          &lt;pubDate<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span><span class="Operators">%=</span> article.created_at.gmtime.rfc822 <span class="Strings"><span class="Strings">%&gt;</span>&lt;/pubDate<span class="Strings">&gt;</span></span>
            <span class="Operators">&lt;</span>comments<span class="Operators">&gt;</span>http<span class="Constants"><span class="Constants">:</span>/</span><span class="Operators">/</span><span class="Operators">&lt;</span><span class="Operators">%=</span> <span class="Variables"><span class="Variables">@</span>page</span>.site <span class="Strings"><span class="Strings">%&gt;</span>&lt;%= article.url %<span class="Strings">&gt;</span></span><span class="Comments"><span class="Comments">#</span>comments&lt;/comments&gt;</span>
            <span class="Operators">&lt;</span>description&gt;<span class="Operators">&lt;</span><span class="Operators">%=</span> normaltext<span class="Operators">=</span>render(article); 
            normaltext.gsub!(<span class="Strings"><span class="Strings">'</span>&lt;img src=&quot;/<span class="Strings">'</span></span>, <span class="Strings"><span class="Strings">'</span>&lt;img src=&quot;http://<span class="Strings">'</span></span><span class="Operators">+@</span>page.site<span class="Operators">+</span><span class="Strings"><span class="Strings">'</span>/<span class="Strings">'</span></span>)
            normaltext.gsub!(<span class="Strings"><span class="Strings">&quot;</span>&lt;img src='/<span class="Strings">&quot;</span></span>, <span class="Strings"><span class="Strings">&quot;</span>&lt;img src='http://<span class="Strings">&quot;</span></span><span class="Operators">+@</span>page.site<span class="Operators">+</span><span class="Strings"><span class="Strings">'</span>/<span class="Strings">'</span></span>)

             h(normaltext) <span class="Strings"><span class="Strings">%&gt;</span>&lt;/description<span class="Strings">&gt;</span></span>
        
            <span class="Operators">&lt;</span><span class="Strings"><span class="Strings">%-</span> if !article.keywords.nil? %&gt;</span>
<span class="Strings">              &lt;%<span class="Strings">-</span></span> article.keywords.each <span class="ControlStructures">do </span>|<span class="Variables">keyword</span>| <span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">                  &lt;category<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span>![<span class="Variables">CDATA</span>[<span class="Operators">&lt;</span><span class="Operators">%=</span> keyword <span class="Strings"><span class="Strings">%&gt;</span>]]<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span><span class="Operators">/</span>category<span class="Operators">&gt;</span>
                <span class="Operators">&lt;</span><span class="Strings"><span class="Strings">%-</span> end %&gt;</span>
<span class="Strings">         &lt;% else %&gt;</span>
<span class="Strings">                  &lt;% if !article.tags.nil? %&gt;</span>
<span class="Strings">                  &lt;%<span class="Strings">-</span></span> article.tags.each <span class="ControlStructures">do </span>|<span class="Variables">tag</span>| <span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">                          &lt;category<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span>![<span class="Variables">CDATA</span>[<span class="Operators">&lt;</span><span class="Operators">%=</span> tag <span class="Strings"><span class="Strings">%&gt;</span>]]<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span><span class="Operators">/</span>category<span class="Operators">&gt;</span>
                    <span class="Operators">&lt;</span><span class="Operators">%</span> <span class="ControlStructures">end</span> <span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">              &lt;% end %<span class="Strings">&gt;</span></span>
           <span class="Operators">&lt;</span><span class="Operators">%</span> <span class="ControlStructures">end</span> <span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">          &lt;content:encoded<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span>![<span class="Variables">CDATA</span>[<span class="Operators">&lt;</span><span class="Operators">%=</span> <span class="Variables">REXML</span>::CData.new(render(article)) <span class="Strings"><span class="Strings">%&gt;</span>]]<span class="Strings">&gt;</span></span><span class="Operators">&lt;</span><span class="Operators">/</span>content<span class="Constants"><span class="Constants">:</span>encoded</span><span class="Operators">&gt;</span>
        <span class="Operators">&lt;</span><span class="Operators">/</span>item<span class="Operators">&gt;</span>
    <span class="Operators">&lt;</span><span class="Operators">%</span> <span class="ControlStructures">end</span> <span class="Strings"><span class="Strings">%&gt;</span></span>
<span class="Strings">  &lt;/channel<span class="Strings">&gt;</span></span>
<span class="Operators">&lt;</span><span class="Operators">/</span>rss<span class="Operators">&gt;</span>
</pre>
</div>


<p><em>Wordpress to webby conversion script</em></p>

<div class="UltraViolet">
<pre class="pastels_on_dark"><span class="Comments"><span class="Comments">#</span>!/usr/bin/env ruby</span>
<span class="Keywords">require</span> <span class="Strings"><span class="Strings">'</span>rubygems<span class="Strings">'</span></span>
<span class="Keywords">require</span> <span class="Strings"><span class="Strings">'</span>rfeedparser<span class="Strings">'</span></span>
<span class="Keywords">require</span> <span class="Strings"><span class="Strings">'</span>pp<span class="Strings">'</span></span>
<span class="Keywords">require</span> <span class="Strings"><span class="Strings">'</span>net/http<span class="Strings">'</span></span>
<span class="Keywords">require</span> <span class="Strings"><span class="Strings">'</span>uri<span class="Strings">'</span></span>

<span class="ControlStructures">def</span> write_feed(<span class="Variables">feed</span>)
  pp feed.title
  pp feed.subtitle
  pp feed.links[<span class="Numbers">0</span>].href

  <span class="Variables"><span class="Variables">@</span>site_url</span><span class="Operators">=</span>feed.wp_base_blog_url
<span class="Comments">  <span class="Comments">#</span>feed.wp_base_site_url</span>
<span class="Comments">  <span class="Comments">#</span>feed.updated</span>
<span class="Comments">  <span class="Comments">#</span>feed.generator</span>
<span class="Comments">  <span class="Comments">#</span>feed.updated_time</span>
<span class="Comments">  <span class="Comments">#</span>feed.updated_parsed</span>
<span class="Comments">  <span class="Comments">#</span>feed.wp_tag_name</span>
<span class="Comments">  <span class="Comments">#</span>feed.wp_tag_slug</span>
<span class="Comments">  <span class="Comments">#</span>feed.wp_cat_name</span>
<span class="Comments">  <span class="Comments">#</span>feed.wp_category_parent</span>
<span class="Comments">  <span class="Comments">#</span>feed.wp_category</span>
<span class="Comments">  <span class="Comments">#</span>feed.wp_wxr_version</span>
<span class="ControlStructures">end</span>

<span class="ControlStructures">def</span> write_entry(<span class="Variables">e</span>)
<span class="Comments">  <span class="Comments">#</span>File.open(local_filename, 'w') {|f| f.write(doc) }</span>
  
  base<span class="Operators">=</span>e.link.gsub(<span class="Variables"><span class="Variables">@</span>site_url</span><span class="Operators">+</span><span class="Strings"><span class="Strings">'</span>/<span class="Strings">'</span></span>,<span class="Strings"><span class="Strings">'</span><span class="Strings">'</span></span>).gsub(e.wp_post_name<span class="Operators">+</span><span class="Strings"><span class="Strings">'</span>/<span class="Strings">'</span></span>, <span class="Strings"><span class="Strings">'</span><span class="Strings">'</span></span>)
  path<span class="Operators">=</span><span class="Variables"><span class="Variables">@</span>webby_dir</span><span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span>/<span class="Strings">&quot;</span></span><span class="Operators">+</span>base<span class="Operators">+</span><span class="Strings"><span class="Strings">'</span>/<span class="Strings">'</span></span><span class="Operators">+</span>e.wp_post_name
  FileUtils.mkdir_p path
  filename<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span>index.html<span class="Strings">&quot;</span></span>
  <span class="Variables"><span class="Variables">@</span>counter</span><span class="Operators">=</span><span class="Variables"><span class="Variables">@</span>counter</span><span class="Operators">+</span><span class="Numbers">1</span>
  
<span class="Comments">  <span class="Comments">#</span>write entries</span>
  puts <span class="Strings"><span class="Strings">&quot;</span>[<span class="Strings"><span class="Strings">#{</span><span class="Variables"><span class="Variables">@</span>counter</span><span class="Strings">}</span></span>]creating <span class="Strings">&quot;</span></span><span class="Operators">+</span>path<span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span>/<span class="Strings">&quot;</span></span><span class="Operators">+</span>filename
  File.open(path<span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span>/<span class="Strings">&quot;</span></span><span class="Operators">+</span>filename, <span class="Strings"><span class="Strings">'</span>w<span class="Strings">'</span></span>) { |<span class="Variables">f</span>| 
    f.write(<span class="Strings"><span class="Strings">&quot;</span>---<span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>) 
    f.write(<span class="Strings"><span class="Strings">&quot;</span>title: <span class="Strings">&quot;</span></span><span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span><span class="CharacterConstants">\&quot;</span><span class="Strings">&quot;</span></span><span class="Operators">+</span>e.title<span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span><span class="CharacterConstants">\&quot;</span><span class="Strings">&quot;</span></span><span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span><span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    f.write(<span class="Strings"><span class="Strings">&quot;</span>author: <span class="Strings">&quot;</span></span><span class="Operators">+</span>e.author<span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span><span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    f.write(<span class="Strings"><span class="Strings">&quot;</span>guid: <span class="Strings">&quot;</span></span><span class="Operators">+</span>e.guid<span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span><span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    format<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span>%Y-%m-%d %H:%M:%S.0 +00:00<span class="Strings">&quot;</span></span>
<span class="Comments">    <span class="Comments">#</span>created_at: 2009-09-10 22:16:41.382708 +02:00</span>
    f.write(<span class="Strings"><span class="Strings">&quot;</span>created_at: <span class="Strings">&quot;</span></span><span class="Operators">+</span> Time.parse(e.wp_post_date).strftime(format)<span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span><span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    f.write(<span class="Strings"><span class="Strings">&quot;</span>blog_post: <span class="Strings">&quot;</span></span><span class="Operators">+</span> <span class="Strings"><span class="Strings">&quot;</span>true<span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    f.write(<span class="Strings"><span class="Strings">&quot;</span>filter:<span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    f.write(<span class="Strings"><span class="Strings">&quot;</span>  - erb<span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    f.write(<span class="Strings"><span class="Strings">&quot;</span>  - basepath<span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
<span class="Comments"><span class="Comments">#</span>    f.write(&quot;  - tidy\n&quot;)</span>

    tags<span class="Operators">=</span>Hash.new
    categories<span class="Operators">=</span>Hash.new
    rssterms<span class="Operators">=</span>e.tags
    rssterms.each { |<span class="Variables">t</span>|
      scheme<span class="Operators">=</span>t[<span class="Strings"><span class="Strings">'</span>scheme<span class="Strings">'</span></span>]
      term<span class="Operators">=</span>t[<span class="Strings"><span class="Strings">'</span>term<span class="Strings">'</span></span>]
      <span class="ControlStructures">if</span> scheme<span class="Operators">==</span><span class="Strings"><span class="Strings">'</span>tag<span class="Strings">'</span></span>
        tags[term]<span class="Operators">=</span><span class="Strings"><span class="Strings">'</span><span class="Strings">'</span></span>   
      <span class="ControlStructures">end</span>
      <span class="ControlStructures">if</span> scheme<span class="Operators">==</span><span class="Strings"><span class="Strings">'</span>category<span class="Strings">'</span></span>
        categories[term]<span class="Operators">=</span><span class="Strings"><span class="Strings">'</span><span class="Strings">'</span></span>   
      <span class="ControlStructures">end</span>
    }
    f.write(<span class="Strings"><span class="Strings">&quot;</span>categories:<span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    categories.keys.each { |<span class="Variables">c</span>| 
      f.write(<span class="Strings"><span class="Strings">&quot;</span>   - <span class="Strings"><span class="Strings">#{</span>c<span class="Strings">}</span></span><span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    }
    f.write(<span class="Strings"><span class="Strings">&quot;</span>tags:<span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    tags.keys.each { |<span class="Variables">c</span>| 
      f.write(<span class="Strings"><span class="Strings">&quot;</span>   - <span class="Strings"><span class="Strings">#{</span>c<span class="Strings">}</span></span><span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
    }

<span class="Comments">    <span class="Comments">#</span>f.write(&quot;  - maruku\n&quot;)</span>
    f.write(<span class="Strings"><span class="Strings">&quot;</span>---<span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)
<span class="Comments">    <span class="Comments">#</span>fixing empty lines to be a hard break</span>
    f.write(e.content[<span class="Numbers">0</span>].value.gsub(<span class="RegularExpressions"><span class="RegularExpressions">/</span></span><span class="RegularExpressions"><span class="CharacterConstants">\n</span><span class="CharacterConstants">\n</span></span><span class="RegularExpressions"><span class="RegularExpressions">/</span></span>,<span class="Strings"><span class="Strings">&quot;</span><span class="CharacterConstants">\n</span>&lt;br&gt;<span class="CharacterConstants">\n</span><span class="Strings">&quot;</span></span>)) 
    
<span class="Comments">    <span class="Comments">#</span>fixing URL's for the images and relative paths</span>
  }
<span class="Comments">  <span class="Comments">#</span>fixing directory urls</span>
  
<span class="Comments">  <span class="Comments">#</span>browsing subdirectories index.html?</span>


  puts <span class="Strings"><span class="Strings">&quot;</span>---------------------------<span class="Strings">&quot;</span></span>
  
  
  <span class="ControlStructures">return</span>
  
  puts e.link

  puts counter.to_s<span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span>:<span class="Strings">&quot;</span></span>
<span class="Comments">  <span class="Comments">#</span>e.wp_post_date</span>
  pp e.wp_post_type
  pp e.title
<span class="Comments">  <span class="Comments">#</span>e.summary_detail[0]</span>
<span class="Comments">  <span class="Comments">#</span>e.post_meta</span>
<span class="Comments">  <span class="Comments">#</span>e.wp_meta_key</span>
  pp e.wp_post_name
<span class="Comments">  <span class="Comments">#</span>e.wp_post_date_gmt</span>
  pp e.author
  pp e.wp_post_id
  pp e.wp_status
<span class="Comments">  <span class="Comments">#</span>e.wp_comment_status</span>
<span class="Comments">  <span class="Comments">#</span>e.summary</span>
<span class="Comments">  <span class="Comments">#</span>e.guidislink</span>
<span class="Comments">  <span class="Comments">#</span>e.title_detail[0]</span>
<span class="Comments">  <span class="Comments">#</span>e.wp_meta_value</span>
  pp e.wp_post_parent
<span class="Comments">  <span class="Comments">#</span>e.wp_ping_status</span>
<span class="Comments">  <span class="Comments">#</span>pp e.content[0].value</span>
  pp e.content[<span class="Numbers">0</span>].type
  pp e.content[<span class="Numbers">0</span>].language
  pp e.links[<span class="Numbers">0</span>].href
<span class="Comments">  <span class="Comments">#</span>e.links[0].rel</span>
<span class="Comments">  <span class="Comments">#</span>e.links[0].type</span>
  pp e.link
<span class="Comments">  <span class="Comments">#</span>e.wp_post_password</span>
<span class="Comments">  <span class="Comments">#</span>e.wp_menu_order</span>
<span class="Comments">  <span class="Comments">#</span>e.wp_post_id</span>
<span class="Comments">  <span class="Comments">#</span>e.excerpt_encoded</span>
  pp e.updated
<span class="Comments">  <span class="Comments">#</span>e.updated_time</span>
  e.updated_parsed
  
<span class="ControlStructures">end</span>

<span class="ControlStructures">def</span> download_attachment(<span class="Variables">e</span>)
  url<span class="Operators">=</span>e.wp_attachment_url
  puts url
  base<span class="Operators">=</span><span class="Variables"><span class="Variables">@</span>webby_dir</span><span class="Operators">+</span><span class="Strings"><span class="Strings">&quot;</span>/<span class="Strings">&quot;</span></span><span class="Operators">+</span>url.gsub(<span class="Variables"><span class="Variables">@</span>site_url</span><span class="Operators">+</span><span class="Strings"><span class="Strings">'</span>/<span class="Strings">'</span></span>,<span class="Strings"><span class="Strings">'</span><span class="Strings">'</span></span>).gsub(e.wp_post_name<span class="Operators">+</span><span class="Strings"><span class="Strings">'</span>/<span class="Strings">'</span></span>, <span class="Strings"><span class="Strings">'</span><span class="Strings">'</span></span>)
  directory<span class="Operators">=</span>File.dirname(base)
  filename<span class="Operators">=</span>File.basename(base)
  puts directory
  puts filename
  FileUtils.mkdir_p directory
  
  myURI <span class="Operators">=</span> <span class="Variables">URI</span>.parse(url)
  pp myURI
  Net::HTTP.start(myURI.host) { |<span class="Variables">http</span>|
    resp <span class="Operators">=</span> http.get(myURI.path)
    open(directory<span class="Operators">+</span><span class="Strings"><span class="Strings">'</span>/<span class="Strings">'</span></span><span class="Operators">+</span>filename, <span class="Strings"><span class="Strings">&quot;</span>wb<span class="Strings">&quot;</span></span>) { |<span class="Variables">file</span>|
      file.write(resp.body)
     }
  }
<span class="ControlStructures">end</span>

<span class="ControlStructures">def</span> write_entries(<span class="Variables">entries</span>)
  <span class="Variables"><span class="Variables">@</span>counter</span><span class="Operators">=</span><span class="Numbers">0</span>
  entries.each { |<span class="Variables">e</span>|
    
    <span class="ControlStructures">if</span> e.wp_post_type <span class="Operators">==</span> <span class="Strings"><span class="Strings">'</span>post<span class="Strings">'</span></span> <span class="Operators">&amp;&amp;</span> e.wp_status <span class="Operators">==</span> <span class="Strings"><span class="Strings">'</span>publish<span class="Strings">'</span></span>

      write_entry(e)
  <span class="ControlStructures">end</span>

    <span class="ControlStructures">if</span> e.wp_post_type <span class="Operators">==</span> <span class="Strings"><span class="Strings">'</span>attachment<span class="Strings">'</span></span>
<span class="Comments">      <span class="Comments">#</span>we should download it      </span>
      download_attachment(e)
  <span class="ControlStructures">end</span>

  }
<span class="ControlStructures">end</span>

<span class="ControlStructures">if</span> <span class="Variables">ARGV</span>.length <span class="Operators">&lt;</span> <span class="Numbers">2</span>
  puts <span class="Strings"><span class="Strings">&quot;</span>Usage: wp2ruby &lt;feed_url&gt; &lt;webby_dir&gt;<span class="Strings">&quot;</span></span>
  exit
<span class="ControlStructures">end</span>

<span class="Variables"><span class="Variables">@</span>feed_url</span><span class="Operators">=</span><span class="Variables">ARGV</span>[<span class="Numbers">0</span>]
<span class="Variables"><span class="Variables">@</span>webby_dir</span><span class="Operators">=</span><span class="Variables">ARGV</span>[<span class="Numbers">1</span>]
<span class="Variables"><span class="Variables">@</span>site_url</span><span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span><span class="Strings">&quot;</span></span>

wpr<span class="Operators">=</span><span class="Strings"><span class="Strings">&quot;</span><span class="Strings">&quot;</span></span>
<span class="ControlStructures">begin</span>
  wpr<span class="Operators">=</span>FeedParser.parse(<span class="Variables"><span class="Variables">@</span>feed_url</span>)
<span class="ControlStructures">rescue</span>
  puts <span class="Strings"><span class="Strings">&quot;</span>Error parsing feed<span class="Strings">&quot;</span></span><span class="Operators">+</span><span class="Variables"><span class="Variables">$</span>!</span>
  exit
<span class="ControlStructures">end</span>

write_feed(wpr.feed)
write_entries(wpr.entries)
</pre>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.planetdevops.net/?feed=rss2&amp;p=6319</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Videos from DevOps Day 2010 panels!</title>
		<link>http://feedproxy.google.com/~r/Dev2ops/~3/WTafBnx3LSw/videos-from-devops-day-2010-panels.html</link>
		<comments>http://feedproxy.google.com/~r/Dev2ops/~3/WTafBnx3LSw/videos-from-devops-day-2010-panels.html#comments</comments>
		<pubDate>Mon, 23 Aug 2010 07:34:48 +0000</pubDate>
		<dc:creator>Damon Edwards</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[DevOps Days]]></category>
		<category><![CDATA[Presentation]]></category>
		<category><![CDATA[Q&A]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[devops]]></category>

		<guid isPermaLink="false">http://dev2ops.org/blog/2010/8/23/videos-from-devops-day-2010-panels.html</guid>
		<description><![CDATA[&#160;

InfoQ.com has posted the videos they recorded at DevOps Day USA 2010. You can watch six of the seven panels now on the InfoQ.com site. There was a production problem with the seventh panel ("DevOps outside of WebOps") that, if it can be fixed, ...]]></description>
			<content:encoded><![CDATA[<p><span class="full-image-block ssNonEditable"><span>&nbsp;</span></span></p>
<p style="text-align: center;"><img src="http://dev2ops.org/storage/devopsday_infoq.jpg?__SQUARESPACE_CACHEVERSION=1282550710266" alt="" /></p>
<p>InfoQ.com has posted the videos they recorded at DevOps Day USA 2010. You can watch six of the seven panels now on the InfoQ.com site. There was a production problem with the seventh panel ("DevOps outside of WebOps") that, if it can be fixed, will be posted as well. InfoQ decided that the lightening talks didn't fit into their format so they have sent my co-organizer, Andrew Shafer the raw video and he's going to look into posting them himself.</p>
<p>You can also download audio only versions (.mp3)</p>
<p>Here are the links to the 6 panels...</p>
<div id="_mcePaste">
<div id="_mcePaste"><strong>Your mileage may vary:</strong> Experiences and lessons learned facing DevOps problems in the IT trenches (even if they weren&rsquo;t calling it DevOps!). The good, the bad, the surprises, and ideas for the future.</div>
<div id="_mcePaste">Stefan Apitz &ndash; LinkedIn</div>
<div id="_mcePaste">Ernest Muller &ndash; National Instruments</div>
<div id="_mcePaste">Dan Nemec &ndash; SilverPop</div>
<div id="_mcePaste">Burzin Engineer &ndash; Shopzilla</div>
<div id="_mcePaste">Kevin Rae &ndash; PowerReviews</div>
<div id="_mcePaste">moderator: Andrew Shafer</div>
</div>
<div><a class="offsite-link-inline" href="http://www.infoq.com/presentations/your-mileage-may-vary" ><strong>http://www.infoq.com/presentations/your-mileage-may-vary</strong></a></div>
<div></div>
<div>
<div></div>
<div></div>
<br />
<div><strong>Infrastructure as code:</strong> Automation is essential to DevOps. The infrastructure as code concept drives many of today&rsquo;s cutting edge automaton techniques. What is it all about? Where are its limitations?</div>
<div>Theo Schlossnagle &ndash; OmniTI</div>
<div>Luke Kanies &ndash; Puppet Labs</div>
<div>Adam Jacob &ndash; Opscode</div>
<div>Erik Troan &ndash; rPath</div>
<div>moderator: Patrick Debois</div>
</div>
<div id="_mcePaste"><a class="offsite-link-inline" href="http://www.infoq.com/presentations/infrastructure-as-code%20" ><strong>http://www.infoq.com/presentations/infrastructure-as-code</strong></a></div>
<div><strong><br /></strong></div>
<div></div>
<div id="_mcePaste">
<div id="_mcePaste"><strong>Changing culture to enable DevOps:</strong> Changing tools is easy when compared to changing people and processes. How can we cultivate an organization&rsquo;s culture to identify and solve DevOps problems?</div>
<div id="_mcePaste">John Allspaw &ndash; Etsy</div>
<div id="_mcePaste">Lee Thompson &ndash; DTO Solutions</div>
<div id="_mcePaste">Israel Gat &ndash; The Agile Executive</div>
<div id="_mcePaste">Lloyd Taylor &ndash; Netelder Associates</div>
<div id="_mcePaste">moderator: Andrew Shafer</div>
</div>
<div><a class="offsite-link-inline" href="http://www.infoq.com/presentations/changing-culture-to-enable-DevOps" ><strong>http://www.infoq.com/presentations/changing-culture-to-enable-DevOps</strong></a></div>
<div><strong><br /></strong></div>
<div id="_mcePaste"></div>
<div>
<div><strong>Does the Cloud needs DevOps? Does DevOps need the Cloud?:</strong> Examining the role that cloud technologies can play in solving DevOps problems and the role that DevOps solutions can play in getting the most out of cloud technologies.</div>
<div>James Urquhart &ndash; Cisco</div>
<div>Adrian Cole &ndash; Jclouds</div>
<div>Justin Dean &ndash; Shopzilla</div>
<div>Joe Arnold &ndash; Cloudscaling</div>
<div>moderator: John Willis</div>
</div>
<div><a class="offsite-link-inline" href="http://www.infoq.com/presentations/does-Cloud-need-DevOps" ><strong>http://www.infoq.com/presentations/does-Cloud-need-DevOps</strong></a></div>
<div><strong><br /></strong></div>
<div></div>
<div id="_mcePaste">
<div id="_mcePaste"><strong>DevOps requires visibility: monitoring, testing, and performance:</strong> Examining the (often overlooked) role of monitoring and testing techniques in solving DevOps problems.</div>
<div id="_mcePaste">Jyoti Bansal &ndash; AppDynamics</div>
<div id="_mcePaste">Gareth Bowles &ndash; Appscio</div>
<div id="_mcePaste">Matt Ray &ndash; Zenoss</div>
<div id="_mcePaste">Eishay Smith &ndash; kaChing</div>
<div id="_mcePaste">Javier Soltero &ndash; SpringSource</div>
<div id="_mcePaste">moderator: Damon Edwards</div>
</div>
<div><a class="offsite-link-inline" href="http://www.infoq.com/presentations/DevOps-requires-visibility" ><strong>http://www.infoq.com/presentations/DevOps-requires-visibility</strong></a></div>
<div><strong><br /></strong></div>
<div></div>
<div id="_mcePaste">
<div id="_mcePaste"><strong>Making the business case:</strong> We know that solving DevOps problems improves your business operations and improves the bottom line, but how do you do you explain that to your CEO or CFO? How do you get the executives to buy in and invest in DevOps solutions?</div>
<div id="_mcePaste">Kurt Milne &ndash; IT Process Institute</div>
<div id="_mcePaste">Jay Lyman &ndash; The 451 Group</div>
<div id="_mcePaste">Rolf Andrew Russell &ndash; ThoughtWorks</div>
<div id="_mcePaste">Jody Mulkey &ndash; Shopzilla</div>
<div id="_mcePaste">moderator: Damon Edwards</div>
</div>
<div><a class="offsite-link-inline" href="http://www.infoq.com/presentations/Making-the-business-case%20" ><strong>http://www.infoq.com/presentations/Making-the-business-case</strong></a></div>
<p>&nbsp;</p>
<p><em><strong>EDIT: The recording for seventh panel was rescued from technical&nbsp;oblivion and is now live!...</strong></em></p>
<p><strong>DevOps outside of Web Operations:</strong> Much of the public discussion about DevOps focuses on Web Operations. This panel is about taking the lessons of DevOps to other types of IT.<br />Adam Fletcher - ITA Software<br />Gene Kim &ndash; Tripwire<br />Michael Stahnke -<br />James Turnbull &ndash; Puppet Labs<br />moderator: Patrick Debois&nbsp;<br /><strong><a class="offsite-link-inline" href="http://www.infoq.com/presentations/DevOps-outside-Web-Operations" >http://www.infoq.com/presentations/DevOps-outside-Web-Operations</a></strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p><img src="http://feeds.feedburner.com/~r/Dev2ops/~4/WTafBnx3LSw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.planetdevops.net/?feed=rss2&amp;p=6100</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Marionette Collective version 0.4.8</title>
		<link>http://www.devco.net/archives/2010/08/20/marionette_collective_version_048.php</link>
		<comments>http://www.devco.net/archives/2010/08/20/marionette_collective_version_048.php#comments</comments>
		<pubDate>Fri, 20 Aug 2010 20:55:44 +0000</pubDate>
		<dc:creator>R.I. Pienaar</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[mcollective]]></category>

		<guid isPermaLink="false">http://www.devco.net/?p=1726</guid>
		<description><![CDATA[I just released version 0.4.8 of mcollective. It&#8217;s a small maintenance release fixing a few bugs and adding a few features. I wasn&#8217;t planning on another 0.4.x release before the big 1.0.0 but want to keep 1.0.0 close as possible to something that&#8217;s been out there for a while. The only major feature it introduces [...]]]></description>
			<content:encoded><![CDATA[<p>I just released <a href="http://srt.ly/mcollective048">version 0.4.8 of mcollective</a>.  It&#8217;s a small maintenance release fixing a few bugs and adding a few features.  I wasn&#8217;t planning on another 0.4.x release before the big 1.0.0 but want to keep 1.0.0 close as possible to something that&#8217;s been out there for a while.</p>
<p>The only major feature it introduces is <a href="http://marionette-collective.org/reference/ui/nodereports.html">custom reports</a> of your infrastructure.</p>
<p>It supports two types of scriptlet for building reports.  The first is a little DSL that uses <em>printf</em> style format strings:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">inventory <span style="color:#9966CC; font-weight:bold;">do</span>
    <span style="color:#CC0066; font-weight:bold;">format</span> <span style="color:#996600;">&quot;%s:<span style="color:#000099;">\t</span><span style="color:#000099;">\t</span>%s<span style="color:#000099;">\t</span><span style="color:#000099;">\t</span>%s&quot;</span>
&nbsp;
    fields <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> identity, facts<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;serialnumber&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>, facts<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;productname&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p></code></p>
<p>Which does something like this:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ mc-inventory --script hardware.mc
web1:           KKxxx1H         IBM eServer BladeCenter HS20 -[8832M1X]-
rep1:           KKxxx5Z         IBM eServer BladeCenter HS20 -[8832M1X]-
db4:            KDxxxZY         IBM System x3655 -[794334G]-
man2:           KDxxxR0         eserver xSeries 336 -[88372CY]-
db2:            KDxxxGD         IBM System x3655 -[79855AG]-</pre></div></div>

<p></code></p>
<p>The other &#8211; perhaps more ugly &#8211; is using a Perl like format method.  To use this you need the <em>formatr</em> gem installed, and a report might look like this:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">formatted_inventory <span style="color:#9966CC; font-weight:bold;">do</span>
    page_length <span style="color:#006666;">20</span>
&nbsp;
    page_heading <span style="color:#006600; font-weight:bold;">&lt;&lt;</span>TOP
&nbsp;
            Node Report @<span style="color:#006600; font-weight:bold;">&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;</span>
                        time
&nbsp;
Hostname:         Customer:     Distribution:
<span style="color:#006600; font-weight:bold;">-------------------------------------------------------------------------</span>
TOP
&nbsp;
    page_body <span style="color:#006600; font-weight:bold;">&lt;&lt;</span>BODY
&nbsp;
@<span style="color:#006600; font-weight:bold;">&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;</span> @<span style="color:#006600; font-weight:bold;">&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;</span> @<span style="color:#006600; font-weight:bold;">&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;</span>
identity,    facts<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;customer&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>, facts<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;lsbdistdescription&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
                                @<span style="color:#006600; font-weight:bold;">&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;</span>
                                facts<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;processor0&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
BODY
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p></code></p>
<p>And the resulting report is something like this:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ mc-inventory --script hardware.mc
            Node Report Fri Aug 20 21:49:39 +0100
&nbsp;
Hostname:         Customer:     Distribution:
-------------------------------------------------------------------------
&nbsp;
web1              rip           CentOS release 5.5 (Final)
                                Intel(R) Xeon(R) CPU           L5420  
&nbsp;
web2              xxxxxxx       CentOS release 5.5 (Final)
                                Intel(R) Xeon(R) CPU           X3430</pre></div></div>

<p></code></p>
<p>The report will be paged 20 nodes per page.  The result is very pleasing even if the report format is a bit grim, but it would be much worse to write yet another reporting DSL!</p>
<p>See the <a href="http://srt.ly/mcollective048">full release notes</a> for details on bug fixes and other features.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devco.net/archives/2010/08/20/marionette_collective_version_048.php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
