<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;D0INR305fCp7ImA9WxBbFkg.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622</id><updated>2010-03-15T08:19:56.324-04:00</updated><title>Mark Feeney</title><subtitle type="html">Remember: you chose to read this</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.markfeeney.com/" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/MarkFeeney" /><feedburner:info uri="markfeeney" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DEIFRX8yeyp7ImA9WxBXEEw.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-669879090458238415</id><published>2010-01-20T14:19:00.003-05:00</published><updated>2010-01-20T14:41:54.193-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-20T14:41:54.193-05:00</app:edited><title>Samba: permission denied on nested directory creation</title><content type="html">&lt;p&gt;I have a network setup where there is a Unbuntu (9.04, Jaunty) Samba/CIFS file server with Ubuntu and Windows clients.  I had this annoying issue where, from Linux clients, recursive directory creation -- like &lt;tt&gt;mkdir -p /share/a/b/c&lt;/tt&gt; would not work.  In order to get &lt;tt&gt;/share/a/b/c&lt;/tt&gt; you'd have to create each directory in turn: &lt;tt&gt;mkdir /share/a &amp;&amp; mkdir /share/a/b &amp;&amp; mkdir /share/a/b/c&lt;/tt&gt;.  This prevents handy commands like &lt;tt&gt;mkdir -p&lt;/tt&gt; and &lt;tt&gt;rsync&lt;/tt&gt; from working.  Fortuantely, I finally found a work-around: turn off Samba's &lt;a href="http://wiki.samba.org/index.php/UNIX_Extensions"&gt;Unix extensions&lt;/a&gt; on the server.  i.e. &lt;pre&gt;[global]
...
unix extensions = no
...
&lt;/pre&gt;  Obviously this only helps if you don't need the Unix extensions (symlinks, hardlinks, etc on the share), but I didn't.  This sounds like a bug in the CIFS client for Linux, but who knows.  I'm pleased to have any work-around.&lt;/p&gt;

&lt;p&gt;References&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://patchwork.kernel.org/patch/9046/"&gt;Report of this issue from Feb-2009&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://bugs.gentoo.org/279074"&gt;Gentoo bug about this&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-669879090458238415?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/yKSlEYPpkPQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/669879090458238415/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2010/01/samba-permission-denied-on-nested.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/669879090458238415?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/669879090458238415?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/yKSlEYPpkPQ/samba-permission-denied-on-nested.html" title="Samba: permission denied on nested directory creation" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2010/01/samba-permission-denied-on-nested.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4NR38_fSp7ImA9WxBQGEo.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-5617065870276554346</id><published>2010-01-18T23:39:00.004-05:00</published><updated>2010-01-19T00:13:16.145-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-19T00:13:16.145-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="hexBinary" /><category scheme="http://www.blogger.com/atom/ns#" term="Hudson" /><category scheme="http://www.blogger.com/atom/ns#" term="sysadmin" /><category scheme="http://www.blogger.com/atom/ns#" term="hexdump" /><title>hexBinary Encoding</title><content type="html">&lt;p&gt;Recently, I hacked together a &lt;a href="http://blog.markfeeney.com/2010/01/hudson-external-jobs-wrapper-script.html"&gt;wrapper script&lt;/a&gt; for reporting job statuses to &lt;a href="http://www.hudson-ci.org/"&gt;Hudson&lt;/a&gt;.  The XML API in Hudson called for "hexBinary" encoded data.  I hadn't heard of this before, and couldn't find much in the way of decent examples on Teh Interwebs.  From &lt;a href="http://www.w3.org/TR/xmlschema-2/#hexBinary"&gt;the spec&lt;/a&gt;, it seems to be pretty simple: for each byte in your data, write out its two character hex value.  So if your byte has decimal value 223, write out its hex string: "DF".  (&lt;i&gt;Aside&lt;/i&gt;: this seems like a silly encoding, at least space-wise: why not the ubiquitous &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;base64&lt;/a&gt;?)  I wanted a simple shell script, so the issue was how to do this encoding without pulling in a full-out scripting language.  Fortunately, &lt;a href="http://manpages.ubuntu.com/manpages/karmic/en/man1/hexdump.1.html"&gt;hexdump&lt;/a&gt; has format strings.  Unfortunately, its docs aren't great.&lt;/p&gt;

&lt;p&gt;Example of hexBinary encoding using &lt;tt&gt;hexdump&lt;/tt&gt;:&lt;/p&gt;
&lt;pre&gt;echo "Hello world" | hexdump -v -e '1/1 "%02x"'
48656c6c6f20776f726c640a
&lt;/pre&gt;

&lt;p&gt;So what the hell is that?  &lt;tt&gt;-v&lt;/tt&gt; means don't suppress any duplicate data in the output, and &lt;tt&gt;-e&lt;/tt&gt; is the format string.  &lt;tt&gt;hexdump&lt;/tt&gt;'s &lt;i&gt;very&lt;/i&gt; particular about the formatting of the &lt;tt&gt;-e&lt;/tt&gt; argument; so careful with the quotes.  The &lt;tt&gt;1/1&lt;/tt&gt; means for every 1 byte encountered in the input, apply the following formatting pattern 1 time.  Despite this sounding like the default behaviour in the man page, the &lt;tt&gt;1/1&lt;/tt&gt; is &lt;i&gt;not&lt;/i&gt; optional.  &lt;tt&gt;/1&lt;/tt&gt; also works, but the &lt;tt&gt;1/1&lt;/tt&gt; is very very slightly more readable, IMO.  The &lt;tt&gt;"%02x"&lt;/tt&gt; is just a standard-issue printf-style format code.&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.w3.org/TR/xmlschema-2/#hexBinary"&gt;XMLSchema spec&lt;/a&gt; that defines hexBinary&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/660038/using-ruby-how-to-create-hexbinary-data-required-by-hudsons-postbuildresult"&gt;How to hexBinary encoding in Ruby&lt;/a&gt; (Stack Overflow)
&lt;li&gt;&lt;a href="http://256.com/gray/docs/misc/hexdump_manual_how_to.html"&gt;Good details on &lt;tt&gt;hexdump&lt;/tt&gt;'s format strings&lt;/a&gt; (This finally made it clear to me)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.technovelty.org/linux/tips/hexdump.html"&gt;Another example&lt;/a&gt; of using &lt;tt&gt;hexdump&lt;/tt&gt;'s format strings&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-5617065870276554346?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/Jlp95xXDtKw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/5617065870276554346/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2010/01/hexbinary-encoding.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/5617065870276554346?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/5617065870276554346?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/Jlp95xXDtKw/hexbinary-encoding.html" title="hexBinary Encoding" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2010/01/hexbinary-encoding.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUMQnY9eCp7ImA9WxBXF0o.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-3412294184559621213</id><published>2010-01-18T14:11:00.023-05:00</published><updated>2010-01-29T09:44:43.860-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-29T09:44:43.860-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Hudson" /><category scheme="http://www.blogger.com/atom/ns#" term="sysadmin" /><title>Hudson External Jobs: Wrapper Script</title><content type="html">&lt;p&gt;Lately, I've been using &lt;a href="http://hudson-ci.org/"&gt;Hudson&lt;/a&gt; for a variety of tasks.  Hudson is billed primarily as a &lt;a href="http://en.wikipedia.org/wiki/Continuous_integration"&gt;continuous integration&lt;/a&gt; server, but one general-purpose cool feature it has is the ability to monitor "external" jobs.  What this means is you can have some arbitrary process report status to Hudson periodically.&lt;/p&gt;

&lt;p&gt;My first thought was to get important &lt;tt&gt;cron&lt;/tt&gt; jobs to report status -- beats the automated emails that I tend to ignore.  If you happen to have a full Hudson install on the server running the &lt;tt&gt;cron&lt;/tt&gt; job, Hudson provides a simple Java-based wrapper you can use.  I didn't want to have to have various .jar files copied to every machine that needed to post status, so instead I opted to use Hudson's XML over HTTP interface.  Both the Java-based and HTTP approaches are documented to some extent &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Monitoring+external+jobs"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I wanted to make it as easy as possible to integrate any old script with Hudson, so I came up with the wrapper below.  (It seems to work for me, but use at your own risk; no guarantees!)&lt;/p&gt;

&lt;pre class="brush: bash"&gt;#!/bin/sh
# Wrapper for sending the results of an arbitrary script to Hudson for
# monitoring. 
#
# Usage: 
#   hudson_wrapper &amp;lt;hudson_url&amp;gt; &amp;lt;job&amp;gt; &amp;lt;script&amp;gt;
#
#   e.g. hudson_wrapper http://hudson.myco.com:8080 testjob /path/to/script.sh
#        hudson_wrapper http://hudson.myco.com:8080 testjob 'sleep 2 &amp;amp;&amp;amp; ls -la'
#
# Requires:
#   - curl
#   - bc
#
# Runs &amp;lt;script&amp;gt;, capturing its stdout, stderr, and return code, then sends all
# that info to Hudson under a Hudson job named &amp;lt;job&amp;gt;.
if [ $# -lt 3 ]; then
    echo &amp;quot;Not enough args!&amp;quot;
    echo &amp;quot;Usage: $0 HUDSON_URL HUDSON_JOB_NAME SCRIPT&amp;quot;
    exit 1
fi

HUDSON_URL=$1; shift
JOB_NAME=$1; shift
SCRIPT=&amp;quot;$@&amp;quot;

OUTFILE=$(mktemp -t hudson_wrapper.XXXXXXXX)
echo &amp;quot;Temp file is:     $OUTFILE&amp;quot; &amp;gt;&amp;gt; $OUTFILE
echo &amp;quot;Hudson job name:  $JOB_NAME&amp;quot; &amp;gt;&amp;gt; $OUTFILE
echo &amp;quot;Script being run: $SCRIPT&amp;quot; &amp;gt;&amp;gt; $OUTFILE
echo &amp;quot;&amp;quot; &amp;gt;&amp;gt; $OUTFILE

### Execute the given script, capturing the result and how long it takes.

START_TIME=$(date +%s.%N)
eval $SCRIPT &amp;gt;&amp;gt; $OUTFILE 2&amp;gt;&amp;amp;1
RESULT=$?
END_TIME=$(date +%s.%N)
ELAPSED_MS=$(echo &amp;quot;($END_TIME - $START_TIME) * 1000 / 1&amp;quot; | bc)
echo &amp;quot;Start time: $START_TIME&amp;quot; &amp;gt;&amp;gt; $OUTFILE
echo &amp;quot;End time:   $END_TIME&amp;quot; &amp;gt;&amp;gt; $OUTFILE
echo &amp;quot;Elapsed ms: $ELAPSED_MS&amp;quot; &amp;gt;&amp;gt; $OUTFILE

### Post the results of the command to Hudson.

# We build up our XML payload in a temp file -- this helps avoid 'argument list
# too long' issues.
CURLTEMP=$(mktemp -t hudson_wrapper_curl.XXXXXXXX)
echo &amp;quot;&amp;lt;run&amp;gt;&amp;lt;log encoding=\&amp;quot;hexBinary\&amp;quot;&amp;gt;$(hexdump -v -e '1/1 &amp;quot;%02x&amp;quot;' $OUTFILE)&amp;lt;/log&amp;gt;&amp;lt;result&amp;gt;${RESULT}&amp;lt;/result&amp;gt;&amp;lt;duration&amp;gt;${ELAPSED_MS}&amp;lt;/duration&amp;gt;&amp;lt;/run&amp;gt;&amp;quot; &amp;gt; $CURLTEMP
curl -s -X POST -d @${CURLTEMP} ${HUDSON_URL}/job/${JOB_NAME}/postBuildResult

### Clean up our temp files and we're done.

rm $CURLTEMP
rm $OUTFILE
&lt;/pre&gt;

&lt;p&gt;If you have, for example, a &lt;tt&gt;crontab&lt;/tt&gt; entry that looks like this: &lt;pre&gt;00 02 * * * myscript.sh&lt;/pre&gt; you can have it report status to Hudson under a job called "test_job" by changing your crontab to look like this instead: &lt;pre&gt;00 02 * * * hudson_wrapper http://hudson.myco.com test_job myscript.sh&lt;/pre&gt;  The job "test_job" must be created as an "external job" in Hudson ahead of time for this to work.&lt;/p&gt;

&lt;p&gt;One thing of interest here is the "hexBinary" encoding in the XML that is sent to Hudson.  There is precious little info out there about "hexBinary", so hopefully I got that part right.  From &lt;a href="http://www.w3.org/TR/xmlschema-2/#hexBinary"&gt;the spec&lt;/a&gt;, it seems simple enough, and the script does work for all the inputs I've thrown at it so far.  Update: I wrote a &lt;a href="http://blog.markfeeney.com/2010/01/hexbinary-encoding.html"&gt;more detailed post on hexBinary&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update 2010-01-29:&lt;/b&gt; Added &lt;tt&gt;-s&lt;/tt&gt; to curl to avoid transfer stats showing up on stderr.  Also improved the wrapper to be able to handle any size output from the wrapped command.  Before you were at the mercy of &lt;tt&gt;ARG_MAX&lt;/tt&gt;, getting &lt;tt&gt;Argument list too long&lt;/tt&gt; errors if your script output too much stuff.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-3412294184559621213?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/Qs8vESV2i-M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/3412294184559621213/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2010/01/hudson-external-jobs-wrapper-script.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/3412294184559621213?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/3412294184559621213?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/Qs8vESV2i-M/hudson-external-jobs-wrapper-script.html" title="Hudson External Jobs: Wrapper Script" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2010/01/hudson-external-jobs-wrapper-script.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04EQ3o5fCp7ImA9WxBQFko.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-429051175050874695</id><published>2010-01-16T15:38:00.003-05:00</published><updated>2010-01-16T16:05:02.424-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T16:05:02.424-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jungle Disk" /><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="sysadmin" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>Jungle Disk 3 Linux: Automatically start on reboot</title><content type="html">&lt;p&gt;I've been a long time user of &lt;a href="http://www.jungledisk.com"&gt;Jungle Disk&lt;/a&gt;, and it's historically been pretty good software.  Recently, version 3 was released, and among various features and fixes, they also removed the command line version for Linux for "Jungle Disk Desktop", which I use.  I wanted to run Jungle Disk on a simple file server that didn't have X, but that isn't possible with version 3.  The &lt;a href="http://support.jungledisk.com/forums/50996/entries/88916"&gt;issue&lt;/a&gt; has been raised with Jungle Disk by some other people, and it sounds like there's a chance they will do something about it... maybe/eventually.&lt;/p&gt;

&lt;p&gt;In the mean time, I opted to just install a full desktop version of Ubuntu 9.10 on my file server so I could use Jungle Disk 3's GUI.  But that brought to light another problem: you can't auto-start Jungle Disk 3 after a reboot because it requires a valid X display...  A user must actually log in and start it!  Instead of that nonsense, I run &lt;tt&gt;vncserver&lt;/tt&gt; after a reboot using &lt;a href="http://jeremy.zawodny.com/blog/archives/001021.html"&gt;&lt;tt&gt;@reboot&lt;/tt&gt;&lt;/a&gt; in a &lt;tt&gt;crontab&lt;/tt&gt;, and get &lt;tt&gt;vncserver&lt;/tt&gt; to run &lt;tt&gt;junglediskdesktop&lt;/tt&gt; via it's &lt;tt&gt;xstartup&lt;/tt&gt; file.  A hack, but it seems to work well enough.&lt;/p&gt;

&lt;p&gt;Here's a basic overview of what's needed to make this work.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;tt&gt;vnc4server&lt;/tt&gt; and set it up for gnome-session, as described nicely &lt;a href="http://www.uluga.ubuntuforums.org/showpost.php?p=8528228&amp;postcount=14"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Add the following line to the crontab for the user who should run Jungle Disk: &lt;pre&gt;@reboot   /usr/bin/vncserver :1&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Make sure &lt;tt&gt;~/.vnc/xstartup&lt;/tt&gt; looks something like the following for the user that should run Jungle Disk: &lt;pre&gt;#!/bin/sh

# Uncomment the following two lines for normal desktop:
# unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc

[ -x /etc/vnc/xstartup ] &amp;&amp; exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] &amp;&amp; xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &amp;
#xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &amp;
gnome-session &amp;
junglediskdesktop &amp;
&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To test that this is working, reboot the box and then use a VNC viewer ("Remote Desktop Viewer" in Ubuntu) to connect to the server on port 5901.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-429051175050874695?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/HsFbvdoUGNg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/429051175050874695/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2010/01/jungle-disk-3-linux-automatically-start.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/429051175050874695?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/429051175050874695?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/HsFbvdoUGNg/jungle-disk-3-linux-automatically-start.html" title="Jungle Disk 3 Linux: Automatically start on reboot" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2010/01/jungle-disk-3-linux-automatically-start.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIBRXwyeCp7ImA9WxBXEEw.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-3115124403107060944</id><published>2010-01-15T21:51:00.005-05:00</published><updated>2010-01-20T14:42:34.290-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-20T14:42:34.290-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Samba" /><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="sysadmin" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>Simple Samba/CIFS Configuration</title><content type="html">&lt;p&gt;Any time I have to do something with Samba, I run into stupid configuration and permissions issues.  I just set up a dead simple Samba config and am documenting it here for next time.  Possibly someone else might get some use out of it too.&lt;/p&gt;
&lt;p&gt;Some reading I based this on: &lt;a href="http://beginlinux.com/blog/2010/01/create-a-public-share-on-samba/"&gt;creating a public share in Samba&lt;/a&gt;, and &lt;a href="https://help.ubuntu.com/community/SettingUpSamba"&gt;some Samba on Ubuntu&lt;/a&gt; docs.&lt;/p&gt;

&lt;p&gt;Overview:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu 9.10 Karmic as the smb server&lt;/li&gt;
&lt;li&gt;Whatever Samba 3.x it comes with&lt;/li&gt;
&lt;li&gt;Windows and Linux client machines&lt;/li&gt;
&lt;li&gt;Anyone on 192.168.1.0/24 has access: not secure, but convenient&lt;/li&gt;
&lt;li&gt;Machine called &lt;tt&gt;myhostname&lt;/tt&gt; is the file server, at IP 192.168.1.4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Config:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the file server, &lt;tt&gt;myhostname&lt;/tt&gt; in this example, create a user &lt;tt&gt;smbuser&lt;/tt&gt; to act as the 'guest' in Samba.  Client machines that don't authenticate will act as this user: &lt;pre&gt;sudo adduser smbuser&lt;/pre&gt;  Then make sure &lt;tt&gt;/etc/passwd&lt;/tt&gt; and &lt;tt&gt;/etc/group&lt;/tt&gt; have lines something like this: &lt;pre&gt;# /etc/passwd
smbuser:x:1001:1001:Samba user,,,:/home/smbuser:/usr/sbin/nologin

# /etc/group
smbuser:x:1001:
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Edit &lt;tt&gt;/etc/samba/smb.conf&lt;/tt&gt;: &lt;pre&gt;[global]
netbios name = myhostname
workgroup = WORKGROUP
server string = File Server
security = user
map to guest = bad user
guest account = smbuser
create mask = 0644
directory mask = 0755
hosts allow = 192.168.1.0/24
hosts deny = 0.0.0.0/0
unix extensions = no  # unless you REALLY need them

# Simple share that anyone can read/write to
[photos]
path = /data/photos
browsable = yes
guest ok = yes
read only = no
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Client linux machine's &lt;tt&gt;/etc/fstab&lt;/tt&gt; (Make sure &lt;tt&gt;smbfs&lt;/tt&gt; is installed: &lt;tt&gt;sudo apt-get install smbfs&lt;/tt&gt;): &lt;pre&gt;
//192.168.1.4/data /data cifs username=smbuser,password=,uid=bob,gid=bob 0 0
&lt;li&gt;Client Windows machine: just browse to &lt;tt&gt;\\192.168.1.4&lt;/tt&gt; or &lt;tt&gt;\\myhostname&lt;/tt&gt;
&lt;/pre&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-3115124403107060944?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/uAlzQsmfDSA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/3115124403107060944/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2010/01/simple-sambacifs-configuration.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/3115124403107060944?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/3115124403107060944?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/uAlzQsmfDSA/simple-sambacifs-configuration.html" title="Simple Samba/CIFS Configuration" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2010/01/simple-sambacifs-configuration.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQMRXc8fip7ImA9WxBRGE0.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-1177486526478063802</id><published>2010-01-06T14:32:00.000-05:00</published><updated>2010-01-06T14:33:04.976-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-06T14:33:04.976-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="snapsort" /><title>Snapsort: feature #1</title><content type="html">&lt;p&gt;First post for normal humans!&lt;/p&gt;
&lt;p&gt;Yesterday we launched the first &lt;a href="http://www.snapsort.com"&gt;Snapsort&lt;/a&gt; feature: compare any two digital cameras (in a sane way).  Here's an &lt;a href="http://www.snapsort.com/compare/Canon_PowerShot_SD1200_IS-vs-Panasonic_Lumix_DMC-ZS3"&gt;example comparison&lt;/a&gt;.  This is a relatively simple feature, but we think it's interesting. (...And possibly even useful already?)  Alex gives a better description &lt;a href="http://blog.alexblack.ca/snapsortcom-is-live-compare-cameras"&gt;here&lt;/a&gt;.  This is only the beginning, but it's nice to have something "live".&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-1177486526478063802?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/w0A8Ri_IAbw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/1177486526478063802/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2010/01/snapsort-feature-1.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/1177486526478063802?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/1177486526478063802?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/w0A8Ri_IAbw/snapsort-feature-1.html" title="Snapsort: feature #1" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2010/01/snapsort-feature-1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkICR3oyeSp7ImA9WxBRFkk.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-2413880387287770716</id><published>2010-01-04T16:17:00.002-05:00</published><updated>2010-01-04T16:29:26.491-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-04T16:29:26.491-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jaunty Jackalope" /><category scheme="http://www.blogger.com/atom/ns#" term="sysadmin" /><category scheme="http://www.blogger.com/atom/ns#" term="s3" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>s3cmd 0.9.9 on Ubuntu 9.04/Jaunty</title><content type="html">&lt;p&gt;The version of s3cmd that comes with Ubuntu Jaunty is quite old (0.9.8; from late 2008).  It seems that numerous issues have been fixed in 0.9.9, which is part of Karmic.  Fortunately, there is a backport to Jaunty.  Here's how to install:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uninstall s3cmd if you've already installed it: &lt;pre&gt;sudo apt-get remove s3cmd&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Add the following lines to &lt;tt&gt;/etc/apt/sources.list&lt;/tt&gt;: &lt;pre&gt;# s3cmd backports
deb http://ppa.launchpad.net/loic-martin3/ppa/ubuntu jaunty main 
deb-src http://ppa.launchpad.net/loic-martin3/ppa/ubuntu jaunty main 
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Run these commands: &lt;pre&gt;sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 78822001
sudo apt-get update
sudo apt-get install s3cmd&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Check that you've got 0.9.9: &lt;pre&gt;$ s3cmd --version
s3cmd version 0.9.9&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thanks to &lt;a href="https://launchpad.net/~loic-martin3/+archive/ppa/"&gt;Loïc Martin&lt;/a&gt;, from whom these packages originate.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-2413880387287770716?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/UwIf8URDI8E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/2413880387287770716/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2010/01/s3cmd-099-on-ubuntu-904jaunty.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/2413880387287770716?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/2413880387287770716?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/UwIf8URDI8E/s3cmd-099-on-ubuntu-904jaunty.html" title="s3cmd 0.9.9 on Ubuntu 9.04/Jaunty" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2010/01/s3cmd-099-on-ubuntu-904jaunty.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEDRHw8fyp7ImA9WxBREUU.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-2841903838440881100</id><published>2009-12-30T08:56:00.004-05:00</published><updated>2009-12-30T09:17:55.277-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-30T09:17:55.277-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jaunty Jackalope" /><category scheme="http://www.blogger.com/atom/ns#" term="sysadmin" /><category scheme="http://www.blogger.com/atom/ns#" term="Karmic Koala" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>Ubuntu 9.10 and GeForce 7800 GT</title><content type="html">&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; This issue seems to affect Ubuntu 9.04 Jaunty, and Ubuntu 9.10 Karmic, in both 32-bit and 64-bit versions.  I've seen some anecdotal evidence that it affects earlier releases too.&lt;/p&gt;

&lt;p&gt;I recently set out to install Ubuntu 9.10 on my aging old home PC: an Athlon64 3800+, 2 GB RAM, decent (at the time) Asus board.  Most importantly, this machine has an NVidia GeForce 7800 GT video card.  To my surprise (having installed Ubuntu on numerous other machines of various age), I had a myriad of problems with the install.  The symptoms were as follows:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Installer would freeze with corrupt looking graphics if I tried to change certain options&lt;/li&gt;
    &lt;li&gt;If I took all defaults in the installer, I could get the OS installed, but it would lock up (again with corrupt looking graphics on screen) when selecting my user name in gdm when X started up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Googling around at length revealed others with similar problems, and the common element was the GeForce 7800 GT video card.  Related links:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://www.linuxquestions.org/questions/ubuntu-63/ubuntu-9.10-freezes-after-installation-777737/"&gt;Recent linuxquestions.org thread that I'm on&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://ubuntuforums.org/showthread.php?p=1680357#post1680357"&gt;Three year old thread talking about similar-sounding issue in Edgy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-nv/+bug/62230"&gt;Bug report that finally clued me in on how to "fix" it&lt;/a&gt; (post #20; Michael Curran)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I don't really know what the root cause is here, but using the above info, here's a work-around: (This assumes you got the OS installed somehow, and are now at the point where you want to login, but cannot due to X locking up.)&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;Get to a terminal either by recovery booting to the shell (netboot), or by hitting &lt;tt&gt;ctrl-alt-f1&lt;/tt&gt; at the graphical login screen.&lt;/li&gt;
    &lt;li&gt;Add the NVidia ppa to get access to their newest drivers:&lt;pre&gt;
sudo add-apt-repository ppa:nvidia-vdpau/ppa
sudo apt-get update&lt;/pre&gt;&lt;/li&gt;
    &lt;li&gt;Remove any existing NVidia driver:&lt;pre&gt;sudo apt-get purge nvidia-glx-*&lt;/pre&gt;&lt;/li&gt;
    &lt;li&gt;Install the newest driver: &lt;pre&gt;sudo apt-get install nvidia-glx-195&lt;/pre&gt;&lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Configure&lt;/em&gt; the newly installed driver:&lt;pre&gt;sudo nvidia-xconfig&lt;/pre&gt;&lt;/li&gt;
    &lt;li&gt;Reboot and you should be good to go.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-2841903838440881100?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/SMbrgUbcUR4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/2841903838440881100/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2009/12/ubuntu-910-and-geforce-7800-gt.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/2841903838440881100?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/2841903838440881100?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/SMbrgUbcUR4/ubuntu-910-and-geforce-7800-gt.html" title="Ubuntu 9.10 and GeForce 7800 GT" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.markfeeney.com/2009/12/ubuntu-910-and-geforce-7800-gt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MHRHY9fyp7ImA9WxBSEEo.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-8901520518431018278</id><published>2009-12-17T12:18:00.007-05:00</published><updated>2009-12-17T12:37:15.867-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-17T12:37:15.867-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="fabric" /><category scheme="http://www.blogger.com/atom/ns#" term="sysadmin" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><category scheme="http://www.blogger.com/atom/ns#" term="EC2" /><title>EC2, fabric, and "err: stdin: is not a tty"</title><content type="html">&lt;p&gt;Recently, I've been using &lt;a href="http://docs.fabfile.org/0.9.0/"&gt;fabric&lt;/a&gt; to script up some deployments to EC2.  My EC2 server is running the &lt;a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1952&amp;categoryID=101"&gt;32-bit Ubuntu Jaunty 9.04 server image provided by Alestic&lt;/a&gt;, but I suspect this issue applies across lots of different OS variants.  Fabric seems to work well, but I was getting a nuisance message when running commands on my EC2 instance: &lt;tt&gt;&lt;b&gt;err: stdin: is not a tty&lt;/b&gt;&lt;/tt&gt;.  You can even see the message in action in the output of this (very useful) &lt;a href="http://www.saltycrane.com/blog/2009/10/notes-python-fabric-09b1/"&gt;intro to fabric&lt;/a&gt; that happens to show an EC2 example.&lt;/p&gt;

&lt;p&gt;Some &lt;a href="http://www.mail-archive.com/fab-user@nongnu.org/msg00608.html"&gt;searching&lt;/a&gt; turned up that this is a result of a command in a &lt;tt&gt;.profile&lt;/tt&gt; or &lt;tt&gt;.bashrc&lt;/tt&gt; on the remove host expecting the shell to be interactive, which it is not with fabric.&lt;/p&gt;

In my case, the culprit was &lt;tt&gt;/root/.profile&lt;/tt&gt;, in particular the command &lt;tt&gt;mesg n&lt;/tt&gt;.  To fix the message, I wrapped the &lt;tt&gt;mesg&lt;/tt&gt; call in a check for an interactive tty:

&lt;pre&gt;if `tty -s`; then
    mesg n
fi
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-8901520518431018278?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/toj5eCoUY-E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/8901520518431018278/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2009/12/ec2-fabric-and-err-stdin-is-not-tty.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/8901520518431018278?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/8901520518431018278?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/toj5eCoUY-E/ec2-fabric-and-err-stdin-is-not-tty.html" title="EC2, fabric, and &quot;err: stdin: is not a tty&quot;" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.markfeeney.com/2009/12/ec2-fabric-and-err-stdin-is-not-tty.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQCQXc7eSp7ImA9WxBTGEg.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-2056426945811204624</id><published>2009-12-14T17:33:00.014-05:00</published><updated>2009-12-14T23:12:40.901-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-14T23:12:40.901-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="lift" /><category scheme="http://www.blogger.com/atom/ns#" term="jetty" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="scala" /><title>Scala Lift, Jetty 6, static content, and Virtual Directories</title><content type="html">&lt;p&gt;I have a simple web application written using the &lt;a href="http://www.liftweb.net/"&gt;Lift&lt;/a&gt; framework.  I am using Maven to build and test with, in the way recommended by various Lift docs (i.e. I use &lt;tt&gt;mvn jetty:run&lt;/tt&gt; to launch the app).  I ran into an issue when it came to serving static image content, however.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;The app is called &lt;tt&gt;webapp&lt;/tt&gt;&lt;/li&gt;
    &lt;li&gt;The app deploys to &lt;tt&gt;/webapp&lt;/tt&gt;&lt;/li&gt;
    &lt;li&gt;Images are on local disk at &lt;tt&gt;/hdd/data/images&lt;/tt&gt; (i.e. not in the .war)&lt;/li&gt;
    &lt;li&gt;Want to access images from &lt;tt&gt;/images&lt;/tt&gt; (i.e. outside of the context root of the Lift app)&lt;/li&gt;
    &lt;li&gt;Needs to work when developing and running with Maven's &lt;tt&gt;jetty:run&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main issue was simply "how do I setup a virtual directory from &lt;tt&gt;http://server/images&lt;/tt&gt; to &lt;tt&gt;/hdd/data/images&lt;/tt&gt; on disk?"  This seems trivial, but I had a really difficult time finding any straightforward docs on how to do it.  My complicating requirement was that it had to work when developing with &lt;tt&gt;jetty:run&lt;/tt&gt;.  For "real" deployment, the images location will be manually configured, so whether this makes sense in production is not a factor here.&lt;/p&gt;

&lt;p&gt;Long story short: you can configure the &lt;a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin"&gt;maven-jetty-plugin&lt;/a&gt; to load up additional "context handlers" at startup.  Some decent info on this &lt;a href="http://jsimonelis.blogspot.com/2008/07/multiple-web-applications-with-maven.html"&gt;here&lt;/a&gt;. A context handler of type &lt;a href="http://jetty.mortbay.org/apidocs/org/mortbay/jetty/webapp/WebAppContext.html"&gt;WebAppContext&lt;/a&gt; will do the job as far as acting like a virtual directory.  Here's the config from &lt;tt&gt;pom.xml&lt;/tt&gt; for the project:&lt;/p&gt;

&lt;pre class="brush: xml"&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;contextPath&amp;gt;/webapp&amp;lt;/contextPath&amp;gt;
        &amp;lt;scanIntervalSeconds&amp;gt;0&amp;lt;/scanIntervalSeconds&amp;gt;
        &amp;lt;contextHandlers&amp;gt;
            &amp;lt;!-- setup a simple webapp to serve our images --&amp;gt;
            &amp;lt;contextHandler implementation=&amp;quot;org.mortbay.jetty.webapp.WebAppContext&amp;quot;&amp;gt;
                &amp;lt;contextPath&amp;gt;/images&amp;lt;/contextPath&amp;gt;
                &amp;lt;resourceBase&amp;gt;/hdd/data/images&amp;lt;/resourceBase&amp;gt;
            &amp;lt;/contextHandler&amp;gt;
        &amp;lt;/contextHandlers&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;

&lt;p&gt;I make no claims about this being secure or the best way to do things, but after a lot of trial and error it does at least work.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-2056426945811204624?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/1mi4mJ2a-_8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/2056426945811204624/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2009/12/scala-lift-jetty-6-static-content-and.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/2056426945811204624?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/2056426945811204624?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/1mi4mJ2a-_8/scala-lift-jetty-6-static-content-and.html" title="Scala Lift, Jetty 6, static content, and Virtual Directories" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2009/12/scala-lift-jetty-6-static-content-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UERHo5eyp7ImA9WxNUE0U.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-3796011563954873636</id><published>2009-11-04T15:53:00.008-05:00</published><updated>2009-11-04T21:46:45.423-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-04T21:46:45.423-05:00</app:edited><title>Python: lambda, partial, and scopes</title><content type="html">&lt;p&gt;Python rarely surprises me, which is a good thing.  Unfortunately, today I was surprised by how lambda works.  It made me worry that I had no idea what I was doing at all.  (And I guess I didn't!)  A &lt;tt&gt;lambda&lt;/tt&gt; captures a &lt;i&gt;reference&lt;/i&gt; to any variables it closes over (vs. captuiring the value of those variables), so in a loop context you can get some bizarre effects.&lt;/p&gt;

&lt;p&gt;It turns out this is &lt;a href="http://stackoverflow.com/questions/938429/scope-of-python-lambda-functions-and-their-parameters"&gt;well&lt;/a&gt; &lt;a href="http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/"&gt;documented&lt;/a&gt;, but I'm writing this as a note to myself if nothing else.&lt;/p&gt;

&lt;pre class="brush: python"&gt;
def adder(x, y):
    return x + y

# make a list of functions with lambda that close over i and call adder()
fns = [lambda x: adder(x, i) for i in range(10)]

# call each of our new functions with a constant value
# expected output: [13, 14, 15, 16, 17, 18, 19, 20, 21, 22]

[f(13) for f in fns]
# output: [22, 22, 22, 22, 22, 22, 22, 22, 22, 22]

# buh!?
&lt;/pre&gt;

&lt;p&gt;The functions that are created in the list &lt;tt&gt;fns&lt;/tt&gt; each capture a &lt;i&gt;reference&lt;/i&gt; to the local variable &lt;tt&gt;i&lt;/tt&gt;, but that reference is constantly being rebound to different values as we iterate through &lt;tt&gt;range(10)&lt;/tt&gt;.  The last value &lt;tt&gt;i&lt;/tt&gt; takes in &lt;tt&gt;range(10)&lt;/tt&gt; is &lt;tt&gt;9&lt;/tt&gt;, so all of the functions end up being &lt;tt&gt;lambda x: adder(x, 9)&lt;/tt&gt;.  Below are two "fixes".&lt;p&gt;

&lt;p&gt;&lt;span style="font-weight:bold;"&gt;Fix 1&lt;/span&gt;: capture the value of i as a default argument to the lambda.  Hacky, but supposedly idiomatic for this sort of issue.&lt;/p&gt;
&lt;pre class="brush: python"&gt;
fns = [lambda x1, x2=i: adder(x1, x2) for i in range(10)]
[f(13) for f in fns]
# output: [13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
&lt;/pre&gt;

&lt;p&gt;&lt;span style="font-weight:bold;"&gt;Fix 2&lt;/span&gt;: use &lt;tt&gt;functools.partial&lt;/tt&gt;.  I prefer this.&lt;/p&gt;
&lt;pre class="brush: python"&gt;
from functools import partial
fns = [partial(adder, i) for i in range(10)]
[f(13) for f in fns]
# output: [13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
&lt;/pre&gt;

&lt;p&gt;In retrospect, this really shouldn't be surprising.  I think the main issue here is that in these examples &lt;tt&gt;i&lt;/tt&gt; is just a plain old integer, which, due to my Java background, I tend to think of as a primitive Java int that can only be passed by value.  In Python, everything is just references until interpretation time. e.g.&lt;/p&gt;

&lt;pre class="brush: python"&gt;
foo = 42
def test():
    print foo
test() # outputs: 42

foo = 100
test() # outputs: 100 (!)
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-3796011563954873636?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/6Tax20Q7298" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/3796011563954873636/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2009/11/python-lambda-partial-and-scopes.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/3796011563954873636?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/3796011563954873636?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/6Tax20Q7298/python-lambda-partial-and-scopes.html" title="Python: lambda, partial, and scopes" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2009/11/python-lambda-partial-and-scopes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUAGRXYyfyp7ImA9WxBREEg.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-565033732745760897</id><published>2009-10-19T22:57:00.009-04:00</published><updated>2009-12-28T22:35:24.897-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-28T22:35:24.897-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Jaunty Jackalope" /><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="VirtualBox" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>Installing VirtualBox Guest Additions on Ubuntu 9.04/9.10 Guest, Vista Host</title><content type="html">&lt;p&gt;Here are some notes on how I installed the VirtualBox 3.0.8 Guest Additions on a 32-bit Unbuntu Server (9.04 Jaunty Jackalope) guest running on a 32-bit Windows Vista host.&lt;/p&gt;
&lt;p&gt;The Ubuntu server is a very bare-bones server install running only sshd, so as you'll see below, we have to install gcc and friends.&lt;/p&gt;
&lt;p&gt;This info is adapted from a &lt;a href="http://forums.virtualbox.org/viewtopic.php?p=29316"&gt;post in the VirtualBox forums&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;Mount VirtualBoxGuestAdditons.iso via &lt;strong&gt;Devices &gt; Mount CD/DVD ROM &gt; CD/DVD ROM Image...&lt;/strong&gt;&lt;/li&gt;
    &lt;li&gt;The .iso file should be located on the Windows host here: C:\PROGRA~1\Sun\VIRTUA~1\VBoxGuestAdditions.iso&lt;/li&gt;
    &lt;li&gt;Install the Guest Additions on the Ubuntu guest (adapted from http://forums.virtualbox.org/viewtopic.php?p=29316): &lt;pre class="shell"&gt;
mount /cdrom; cd /cdrom
sudo apt-get update
sudo apt-get install build-essential linux-headers-`uname -r`
sudo ./VBoxLinuxAdditions-x86.run
cd ~; umount /cdrom
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Optional cleanup (I didn't bother since I'm using this box as a development server, and will need gcc et al.)&lt;pre class="shell"&gt;
sudo apt-get remove build-essential linux-headers-`uname -r`
sudo apt-get autoremove
sudo apt-get autoclean
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;reboot the guest (possibly not necessary, but I did it)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The guest additions are now installed and running.  Next step would be to actually do something with them.  In my case, I wanted to mount the &lt;tt&gt;c:\&lt;/tt&gt; drive of the host (Vista) machine.&lt;/p&gt;

To share the entire Vista &lt;tt&gt;c:\&lt;/tt&gt; in the directory &lt;tt&gt;/mnt/c&lt;/tt&gt; on the Ubuntu guest:
&lt;ol&gt;
&lt;li&gt;On the host window, go to &lt;strong&gt;Devices &gt; Shared folders...&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Add new shared folder: Folder Path = &lt;strong&gt;c:\&lt;/strong&gt;, Folder Name = &lt;strong&gt;c&lt;/strong&gt;, &lt;strong&gt;not&lt;/strong&gt; Read-only, check &lt;strong&gt;Make Permanent&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Add the following line to /etc/fstab:&lt;pre class="shell"&gt;
c    /mnt/c    vboxsf    rw,gid=1000,uid=1000,auto    0    0
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Note&lt;/strong&gt;: I've mounted this as my main user.  If you've only created one user on your Ubuntu server, this should work.  If in doubt, run &lt;tt&gt;id&lt;/tt&gt; as the user you want to mount the Windows share as.&lt;/li&gt;
&lt;li&gt;Create the mountpoint: &lt;tt&gt;sudo mkdir /mnt/c&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Mount the share (this will happen automatically in the future): &lt;tt&gt;sudo mount /mnt/c&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;Update 28-Dec-2009:&lt;/b&gt; I just used this same procedure on Karmic 9.10 and it also seems to work fine there.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-565033732745760897?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/bsCdjj-e9IE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/565033732745760897/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2009/10/installing-virtualbox-guest-additions.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/565033732745760897?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/565033732745760897?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/bsCdjj-e9IE/installing-virtualbox-guest-additions.html" title="Installing VirtualBox Guest Additions on Ubuntu 9.04/9.10 Guest, Vista Host" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.markfeeney.com/2009/10/installing-virtualbox-guest-additions.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8CRXwyeip7ImA9WxNWEEQ.&quot;"><id>tag:blogger.com,1999:blog-6200103171537433622.post-6277881041211670983</id><published>2009-10-09T09:17:00.013-04:00</published><updated>2009-10-09T10:34:24.292-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-09T10:34:24.292-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="sysadmin" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>Installing PostgreSQL 8.4 on Ubuntu Jaunty (9.04)</title><content type="html">&lt;p&gt;&lt;i&gt;Inaugural post!&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.ubuntu.com/"&gt;Ubuntu&lt;/a&gt; 9.04 (Jaunty Jackalope) includes &lt;a href="http://www.postgresql.org/"&gt;PostgreSQL&lt;/a&gt; 8.3 via the expected &lt;tt&gt;apt-get install postgresql&lt;/tt&gt;. This is great, but PostgreSQL 8.4.1 has a number of nice features that I want (&lt;a href="http://www.postgresql.org/docs/8.4/static/queries-with.html"&gt;WITH queries&lt;/a&gt;, for example). At first I was just going to wait for Ubuntu 9.10, which is coming very shortly, but I am impatient. It turns out there is a pretty easy "Ubuntu way" to get PostgreSQL 8.4 installed on 9.04 without a lot of headaches (like building from source). The solution is using &lt;a href="https://help.launchpad.net/Packaging/PPA"&gt;Ubuntu PPA&lt;/a&gt;s.&lt;/p&gt;

&lt;p&gt;Add the custom PPA for PostgreSQL to &lt;tt&gt;/etc/apt/sources.list&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="shell"&gt;deb http://ppa.launchpad.net/pitti/postgresql/ubuntu jaunty main
deb-src http://ppa.launchpad.net/pitti/postgresql/ubuntu jaunty main&lt;/pre&gt;

&lt;p&gt;Get the key for these new sources:&lt;/p&gt;
&lt;pre class="shell"&gt;sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8683D8A2&lt;/pre&gt;

&lt;p&gt;Update the package list:&lt;/p&gt;
&lt;pre class="shell"&gt;sudo apt-get update&lt;/pre&gt;

&lt;p&gt;Install!&lt;/p&gt;
&lt;pre class="shell"&gt;sudo apt-get install postgresql-8.4&lt;/pre&gt;

&lt;p&gt;PostgreSQL 8.4.1 will now be running, but on port 5433, not the standard 5432.  I assume this was done so you can run 8.3 and 8.4 at the same time on Ubuntu 9.04.  I only want 8.4.1, so I changed the port and restarted:&lt;/p&gt;

&lt;pre class="shell"&gt;sudo sed -i.bak -e 's/port = 5433/port = 5432/' \
    /etc/postgresql/8.4/main/postgresql.conf

sudo /etc/init.d/postgresql-8.4 stop
sudo /etc/init.d/postgresql-8.4 start&lt;/pre&gt;

&lt;p&gt;These PPAs for PostgreSQL only exist because of &lt;a href="https://launchpad.net/%7Epitti"&gt;Martin Pitt&lt;/a&gt;, who appears to be responsible for PostgreSQL on Ubuntu, so many thanks to him!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6200103171537433622-6277881041211670983?l=blog.markfeeney.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MarkFeeney/~4/nnuE2GAPwSY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.markfeeney.com/feeds/6277881041211670983/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.markfeeney.com/2009/10/installing-postgresql-84-on-ubuntu.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/6277881041211670983?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6200103171537433622/posts/default/6277881041211670983?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarkFeeney/~3/nnuE2GAPwSY/installing-postgresql-84-on-ubuntu.html" title="Installing PostgreSQL 8.4 on Ubuntu Jaunty (9.04)" /><author><name>Mark Feeney</name><uri>http://www.blogger.com/profile/14609764005552907582</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09404029044113758754" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://blog.markfeeney.com/2009/10/installing-postgresql-84-on-ubuntu.html</feedburner:origLink></entry></feed>
