<?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:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title type="text">Tuxcoder Blog Posts</title>
  <id>http://blog.tuxcoder.com/feed.atom</id>
  <updated>2013-01-15T00:00:00Z</updated>
  <link href="http://blog.tuxcoder.com/" />
  
  <subtitle type="text">Recent blog posts</subtitle>
  <generator>Werkzeug</generator>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/tuxcoder" /><feedburner:info uri="tuxcoder" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">Ubuntu 12.04 Breaks XBox DVD IR Remote Dongle in LIRC</title>
    <id>http://blog.tuxcoder.com/2013/1/15/ubuntu_breaks_xbox_dongle_in_lirc</id>
    <updated>2013-01-15T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/dlpZTQFaDO0/ubuntu_breaks_xbox_dongle_in_lirc" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;p&gt;I'm not sure why Ubuntu continues to break devices after every release, but
it's something that seems to happen with increasing frequency. Because of this
I try not to change my MythTV setup very often. However with Ubuntu 12.04 out,
I decided it was time to upgrade. I then had the fun of working through two
non-trivial bugs, this being one of them.&lt;/p&gt;
&lt;p&gt;My understanding is that LIRC went through some type of driver re-architecture,
and the ubiquitous XBOX IR dongle support got dropped along the way. Eventually
I stumbled upon &lt;a class="reference external" href="http://ubuntuforums.org/showthread.php?t=1743470&amp;amp;page=2#post11422009"&gt;this awesome post by MrPlow&lt;/a&gt; that targeted the Natty release.
Luckily it is still functioning in 12.04 Precise Pangolin. I'm going to
reproduce all of the commands here for completeness.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sudo apt-get build-dep lirc
sudo apt-get install git dialog automake autoconf libtool
git clone git://lirc.git.sourceforge.net/gitroot/lirc/lirc
wget http://old.nabble.com/attachment/31787507/0/lirc_0.9.1_lirc_xbox_driver.patch
cd lirc/
patch -p1 &amp;lt;../lirc_0.9.1_lirc_xbox_driver.patch
vi drivers/lirc_xbox/lirc_xbox.c
&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Remove, or comment out the line &lt;tt class="docutils literal"&gt;#include &amp;lt;linux/smp_lock.h&amp;gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Finally build the driver and install:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
./autogen.sh
./configure -with-driver=userspace
cd drivers/lirc_xbox/
make
sudo make install
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Then verify that your &lt;tt class="docutils literal"&gt;/etc/lircd/hardware.conf&lt;/tt&gt; has the following line:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
REMOTE_MODULES=&amp;quot;lirc_dev lirc_xbox&amp;quot;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Reboot&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's all the steps I needed to perform. Just remember that if you ever
install a new kernel, you'll likely have to re-run the compilation and install
steps over again.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/dlpZTQFaDO0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2013/1/15/ubuntu_breaks_xbox_dongle_in_lirc</feedburner:origLink></entry>
  <entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">Firefox 17 Mousewheel Scroll Rate Fix</title>
    <id>http://blog.tuxcoder.com/2012/12/4/firefox-17-scroll-speed-fix</id>
    <updated>2012-12-04T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/ZGzuPSFA0mw/firefox-17-scroll-speed-fix" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;p&gt;It appears that the last update of of Firefox v17 on Ubuntu 12.10 changed the
internal mousewheel scroll rate &lt;a class="reference external" href="about:config"&gt;about:config&lt;/a&gt; names. This has
the nice effect of breaking any custom scroll rate values.&lt;/p&gt;
&lt;p&gt;Like me, you probably made this changes years ago, and are now struggling with
a scroll rate designed for you grandmother.&lt;/p&gt;
&lt;p&gt;The two values you want to adjust in &lt;a class="reference external" href="about:config"&gt;about:config&lt;/a&gt; now are:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
mousewheel.min_line_scroll_amount
general.smoothScroll.mouseWheel
&lt;/pre&gt;
&lt;p&gt;Try setting &lt;tt class="docutils literal"&gt;min_line_scroll_amount&lt;/tt&gt; between &lt;strong&gt;60&lt;/strong&gt; and &lt;strong&gt;70&lt;/strong&gt;. At least on
my system this gives me a reasonable scroll rate.&lt;/p&gt;
&lt;p&gt;Finally, the &lt;tt class="docutils literal"&gt;smoothScroll.mouseWheel&lt;/tt&gt; should allow for quick scrolling when
either &lt;strong&gt;True&lt;/strong&gt; or &lt;strong&gt;False&lt;/strong&gt;. The effect is really a personal preference, so
try both.&lt;/p&gt;
&lt;p&gt;And a final tip, &lt;strong&gt;all of these changes should take effect in real time&lt;/strong&gt;, so
you don't need to restart Firefox.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/ZGzuPSFA0mw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2012/12/4/firefox-17-scroll-speed-fix</feedburner:origLink></entry>
  <entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">Working with Time and Dates in Python</title>
    <id>http://blog.tuxcoder.com/2011/9/14/python_date_calculations</id>
    <updated>2011-09-14T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/UX9CxMWvl-U/python_date_calculations" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;p&gt;When working with time and date values, Python provides more than one
interface.&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="13%" /&gt;
&lt;col width="87%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Module&lt;/th&gt;
&lt;th class="head"&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;&lt;a class="reference external" href="http://docs.python.org/library/time.html"&gt;time&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Low-level time methods.  Supports &lt;tt class="docutils literal"&gt;struct_time&lt;/tt&gt; format, simple
date string IO, conversion to UNIX epoch time.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a class="reference external" href="http://docs.python.org/library/datetime.html"&gt;datetime&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;High-level date and time methods. This provides a proper interface
for adding or subtracting time and dates. Many of the same methods
from the &lt;a class="reference external" href="http://docs.python.org/library/time.html"&gt;time&lt;/a&gt; module are supported, but objects are not compatible
between the two.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Until you spend some time with both modules, it will be a little unclear how to
make the best use of each feature set. Here are a few examples that will
demonstrate some of the available techniques.&lt;/p&gt;
&lt;div class="section" id="convert-naive-datetime-to-unix-epoch"&gt;
&lt;h2&gt;Convert 'Naive' Datetime to Unix Epoch&lt;/h2&gt;
&lt;p&gt;This conversion works if you are working in your local time zone.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mf"&gt;1316032256.260053&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mktime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timetuple&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;1316032260&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="convert-aware-datetime-to-unix-epoch"&gt;
&lt;h2&gt;Convert 'Aware' Datetime to Unix Epoch&lt;/h2&gt;
&lt;p&gt;In a more advanced case, you might want to compute a Unix time value of a
&lt;tt class="docutils literal"&gt;datetime&lt;/tt&gt; that is outside of your local timezone. For this example
'US/Eastern' is not my local timezone.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;calendar&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timegm&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pytz&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mf"&gt;1317696751.797751&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;est&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;US/Eastern&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c"&gt;# non-local time zone&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;now_naive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;now_aware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;est&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mktime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now_aware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timetuple&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;      &lt;span class="c"&gt;# wrong, ignores TZ info&lt;/span&gt;
&lt;span class="mf"&gt;1317718351.0&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mktime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now_aware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utctimetuple&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;   &lt;span class="c"&gt;# wrong, ignores TZ info&lt;/span&gt;
&lt;span class="mf"&gt;1317732751.0&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;timegm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timetuple&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;                 &lt;span class="c"&gt;# wrong, no TZ info set&lt;/span&gt;
&lt;span class="mi"&gt;1317660506&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;timegm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utctimetuple&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;              &lt;span class="c"&gt;# wrong, no TZ info set&lt;/span&gt;
&lt;span class="mi"&gt;1317660506&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;timegm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now_aware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timetuple&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;           &lt;span class="c"&gt;# wrong, expects UTC time&lt;/span&gt;
&lt;span class="mi"&gt;1317682351&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;timegm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now_aware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utctimetuple&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;        &lt;span class="c"&gt;# correct&lt;/span&gt;
&lt;span class="mi"&gt;1317696751&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The results show that even though &lt;tt class="docutils literal"&gt;now_naive&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;now_aware&lt;/tt&gt; are created
at the same time, there is only one valid method to convert &lt;tt class="docutils literal"&gt;now_aware&lt;/tt&gt; back
to the correct Unix time value.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="find-last-occurrence-of-a-specific-day"&gt;
&lt;h2&gt;Find Last Occurrence of a Specific Day&lt;/h2&gt;
&lt;p&gt;This examples demonstrates how to get the date of &amp;quot;Last Sunday&amp;quot; or &amp;quot;Last
Tuesday&amp;quot;. This could be easily modified to other relative dates.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;last_day&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="n"&gt;days_of_week&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;sunday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;monday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;tuesday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;wednesday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="s"&gt;&amp;#39;thursday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;friday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;saturday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="n"&gt;target_day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;days_of_week&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
   &lt;span class="n"&gt;delta_day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_day&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isoweekday&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;delta_day&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;delta_day&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="c"&gt;# go back 7 days&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;delta_day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Output of the above method is shown when current date was Wednesday, 9/14/2011:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;958258&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;sunday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;monday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;tuesday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;wednesday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;           &lt;span class="s"&gt;&amp;#39;thursday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;friday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;saturday&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;last_day&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;851355&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;851425&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;851446&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;851466&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;851486&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;851506&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;851526&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/UX9CxMWvl-U" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2011/9/14/python_date_calculations</feedburner:origLink></entry>
  <entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">Hosting Python WSGI Apps Using Dreamhost</title>
    <id>http://blog.tuxcoder.com/2011/9/8/dreamhost_python_wsgi</id>
    <updated>2011-09-08T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/PliaKNhr7oM/dreamhost_python_wsgi" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;p&gt;This article is a setup guide for creating a working &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface"&gt;Python WSGI&lt;/a&gt; container
inside of the standard &lt;a class="reference external" href="http://www.dreamhost.com"&gt;Dreamhost&lt;/a&gt; environment. This should be very helpful to
anyone trying to build a Python webapp using one of the &lt;a class="reference external" href="http://wiki.python.org/moin/WebFrameworks"&gt;many WSGI
frameworks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First thing to know, is that Dreamhost is not going to support this config for
you, and they don't make any guarantee that it work work in the long term.
Therefore, if you want a bullet proof system, your best bet is to get a &lt;a class="reference external" href="http://wiki.python.org/moin/WebProgramming"&gt;virtual
server&lt;/a&gt; on which you can fully control the OS stack.&lt;/p&gt;
&lt;p&gt;In my case, I experimented with the &lt;a class="reference external" href="http://flask.pocoo.org"&gt;Flask&lt;/a&gt; framework, which is considered
pretty basic. This is not a bad thing, since it is easy to get something
working quickly, and has some great documentation.&lt;/p&gt;
&lt;div class="section" id="dreamhost-documentation"&gt;
&lt;h2&gt;Dreamhost Documentation&lt;/h2&gt;
&lt;p&gt;Dreamhost has setup a &lt;a class="reference external" href="http://wiki.dreamhost.com/Passenger_WSGI"&gt;Passenger WSGI wiki page&lt;/a&gt; that describes the overall
process. You should read over this to get some additional background on how all
the various pieces fit together. After you read/skim that, come back here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="virtualenv-setup-optional"&gt;
&lt;h2&gt;Virtualenv Setup (Optional)&lt;/h2&gt;
&lt;p&gt;Before you begin, make sure to log into your Dreamhost SSH account.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;ssh user@machine.dreamhost.com
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Your first step should be to create a Python &lt;a class="reference external" href="http://www.virtualenv.org"&gt;virtualenv&lt;/a&gt; environment. This
creates a local Python environment that will allow to install and upgrade
modules that are not currently installed on the hosted machine.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;virtualenv ~/env
. ~/env/bin/activate    &lt;span class="c"&gt;# activate the new &amp;#39;env&amp;#39; environment&lt;/span&gt;
pip install virtualenv --upgrade
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;After this step, every time you need to use or modify the environment, you
have to source the &lt;cite&gt;. ~/env/bin/active&lt;/cite&gt; script to configure your shell.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="domain-setup"&gt;
&lt;h2&gt;Domain Setup&lt;/h2&gt;
&lt;p&gt;You'll need a registered domain name to run this configuration on. I don't
recommend testing this out on a production domain, however it should be OK to
create a new sub-domain for testing.&lt;/p&gt;
&lt;p&gt;Using the web interface, go to the &lt;strong&gt;Domains → Manage Domains&lt;/strong&gt;. From the &lt;strong&gt;Web
Hosting&lt;/strong&gt; column, select &lt;strong&gt;Edit&lt;/strong&gt;.&lt;/p&gt;
&lt;a class="reference external image-reference" href="/static/posts/008.dreamhost/panel.png"&gt;&lt;img alt="/static/posts/008.dreamhost/panel.png" class="align-center" src="/static/posts/008.dreamhost/panel.png" style="width: 550px;" /&gt;&lt;/a&gt;
&lt;p&gt;The image above shows the necessary changes:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Append &lt;tt class="docutils literal"&gt;/public&lt;/tt&gt; to the default &lt;strong&gt;Web Directory&lt;/strong&gt;. This is where static
files can be served from.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Passenger&lt;/strong&gt;, by checking the box.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Don't forget to click &lt;strong&gt;Save&lt;/strong&gt; when you are finished.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="python-wsgi-setup"&gt;
&lt;h2&gt;Python WSGI Setup&lt;/h2&gt;
&lt;p&gt;Now the final step is to add a script into your domain root directory.  These
will be executed on each HTTP request by the server. This is where we will
delegate our Python app to handle the request and return the necessary
response data.&lt;/p&gt;
&lt;p&gt;The name of the script &lt;strong&gt;must&lt;/strong&gt; be &lt;tt class="docutils literal"&gt;passenger_wsgi.py&lt;/tt&gt;. It does not have to
be executable. Depending on your WSGI framework, you might need to update a few
things, as mine is currently targeted at the Flask framework.&lt;/p&gt;
&lt;div class="note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;The job of this script is to import and create a Python variable to your
WSGI app named &lt;tt class="docutils literal"&gt;application&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="file container"&gt;
&lt;p&gt;passenger_wsgi.py&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;DEBUG&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="n"&gt;ROOT&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;INTERP&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;/home/USERNAME/env/bin/python&amp;#39;&lt;/span&gt;  &lt;span class="c"&gt;# fix &amp;#39;USERNAME&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ROOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executable&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;INTERP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INTERP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;INTERP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;myapp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
   &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;werkzeug_debugger_appengine&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_debugged_app&lt;/span&gt;
   &lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_debugged_app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Let me go over a few of the details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The first main code block updates your &lt;tt class="docutils literal"&gt;sys.path&lt;/tt&gt; define. This allows the
execution environment make use of any virtualenv packages you have installed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The next block pulls in your WSGI application. In this case, it's called
&lt;tt class="docutils literal"&gt;myapp&lt;/tt&gt; and sitting in the domain root directory. As long as its somewhere
in your Python path, it should be fine. Notice that it imports the app as
&lt;tt class="docutils literal"&gt;application&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The final block is a trick for people using Flask and/or &lt;a class="reference external" href="http://werkzeug.pocoo.org/"&gt;Werkzeug&lt;/a&gt;. This
provides a work-around for the runtime debugger on Dreamhost. See the next
section for additional setup.&lt;/p&gt;
&lt;div class="warning"&gt;
&lt;p class="first admonition-title"&gt;Warning&lt;/p&gt;
&lt;p class="last"&gt;Do not run a production system in debug mode. It very likely will not be
secure.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="important"&gt;
&lt;p class="first admonition-title"&gt;Important&lt;/p&gt;
&lt;p class="last"&gt;The WSGI application container is not restarted for every request. When you
make changes to your app, you should &lt;a class="reference external" href="http://wiki.dreamhost.com/Passenger#Configuration_Steps"&gt;reset the session&lt;/a&gt; by running
&lt;tt class="docutils literal"&gt;touch tmp/restart.txt&lt;/tt&gt;. This will work in most cases, but if not, the
other option is to run &lt;tt class="docutils literal"&gt;pkill python&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="enabling-the-werkzeug-debugger"&gt;
&lt;h2&gt;Enabling the Werkzeug Debugger&lt;/h2&gt;
&lt;p&gt;If you plan to do any active development on the Dreamhost side, this step will
simplify your efforts. Werkzeug comes with a really nice &lt;a class="reference external" href="http://werkzeug.pocoo.org/docs/debug/"&gt;debugging engine&lt;/a&gt;,
but it does not work with the Dreamhost configuration by default.&lt;/p&gt;
&lt;p&gt;For example, if you have a simple Python coding error in your app, it will
result in the following:&lt;/p&gt;
&lt;div class="figure align-center"&gt;
&lt;a class="reference external image-reference" href="/static/posts/008.dreamhost/werkzeug_default.png"&gt;&lt;img alt="/static/posts/008.dreamhost/werkzeug_default.png" src="/static/posts/008.dreamhost/werkzeug_default.png" style="width: 550px;" /&gt;&lt;/a&gt;
&lt;p class="caption"&gt;Default Dreamhost WSGI HTTP response on Python error.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In this mode, you're out of luck. The only option is to startup a local server
where you can go back and test the app. In some cases it might be a big effort
just to replicate the bug.&lt;/p&gt;
&lt;p&gt;With the Werkzeug Debugger enabled and patched, you'll get a much nicer output:&lt;/p&gt;
&lt;div class="figure align-center"&gt;
&lt;a class="reference external image-reference" href="/static/posts/008.dreamhost/werkzeug_patch.png"&gt;&lt;img alt="/static/posts/008.dreamhost/werkzeug_patch.png" src="/static/posts/008.dreamhost/werkzeug_patch.png" style="width: 550px;" /&gt;&lt;/a&gt;
&lt;p class="caption"&gt;Patched Dreamhost WSGI HTTP response on Python error.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The patched version will not give you any interactive UI, but you get a pretty
nice stack trace, file name and line number where the error occurred.&lt;/p&gt;
&lt;p&gt;There are few steps for enabling this:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Download and install the &lt;a class="reference external" href="https://github.com/nshah/werkzeug-debugger-appengine"&gt;patch source code&lt;/a&gt; from github.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;mkdir ~/src
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/src
git clone https://github.com/nshah/werkzeug-debugger-appengine.git
&lt;span class="nb"&gt;cd &lt;/span&gt;werkzeug-debugger-appengine
python setup.py install
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If you followed all the &lt;a class="reference internal" href="#python-wsgi-setup"&gt;previous steps&lt;/a&gt;, thats it.  If not, you have to go
back and edit your &lt;tt class="docutils literal"&gt;passenger_wsgi.py&lt;/tt&gt; script to enable the patch. At the
end of the file, modify the &lt;tt class="docutils literal"&gt;application&lt;/tt&gt; reference:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;werkzeug_debugger_appengine&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_debugged_app&lt;/span&gt;
&lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_debugged_app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/PliaKNhr7oM" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2011/9/8/dreamhost_python_wsgi</feedburner:origLink></entry>
  <entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">Ubuntu 11.04 Adobe Flash Player Display Errors</title>
    <id>http://blog.tuxcoder.com/2011/5/26/ubuntu-11.04-adobe-flash-player-display-error</id>
    <updated>2011-05-26T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/CrjV710Hr7U/ubuntu-11.04-adobe-flash-player-display-error" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;p&gt;If your Flash Player is glitching in Firefox and displaying annoying solid
blocks that hide the flash media, try this fix:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
add-apt-repository ppa:sevenmachines/flash
apt-get update
apt-get install flashplugin64-installer
&lt;/pre&gt;
&lt;p&gt;via &lt;a class="reference external" href="http://www.brooksview.com/2011/05/12/ubuntu-11-04-x64-and-flickering-flash-fix/"&gt;Ubuntu 11.04 x64 and flickering Flash fix&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/CrjV710Hr7U" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2011/5/26/ubuntu-11.04-adobe-flash-player-display-error</feedburner:origLink></entry>
  <entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">Reclaim Wasted Hard Disk Space on Ext Volumes</title>
    <id>http://blog.tuxcoder.com/2011/5/11/reclaim-wasted-hard-disk-space-on-ext-volumes</id>
    <updated>2011-05-11T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/R4AsPX-qork/reclaim-wasted-hard-disk-space-on-ext-volumes" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;p&gt;If you're running any of the Ext file systems, you can get back a lot of
free space by running a simple command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;sudo tune2fs -m 0 /dev/sdX
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By default, Ext systems reserve 5% of space on the file system in case it is
need by the OS. This command will set the reserved system space to 0%.&lt;/p&gt;
&lt;p&gt;For non-root volumes, keeping this reserved space around is not necessary.
For a 1TB volume, this could account for up to 50GB of wasted space.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/R4AsPX-qork" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2011/5/11/reclaim-wasted-hard-disk-space-on-ext-volumes</feedburner:origLink></entry>
  <entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">How To Install a Minimal Ubuntu Server OS on a VirtualBox Instance</title>
    <id>http://blog.tuxcoder.com/2010/3/27/how-to-install-a-minimal-ubuntu-server-os-to-virtualbox</id>
    <updated>2010-03-27T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/_0hj0zwgl2g/how-to-install-a-minimal-ubuntu-server-os-to-virtualbox" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;img alt="/static/posts/007.min-ubuntu/alix.jpg" class="align-right" src="/static/posts/007.min-ubuntu/alix.jpg" style="width: 250px;" /&gt;
&lt;p&gt;Most people are not aware that you can install a baseline Ubuntu system in
under 1GB of space. This makes it great for a headless system, such as an
embedded &lt;a class="reference external" href="http://www.mini-itx.com/"&gt;mini-ITX&lt;/a&gt; board. Even for a desktop, you might want to start with a
bare-minimum Ubuntu package set and then customize the rest. All this can be
accomplished very quickly, and easily using a few tips. For this post, I'll
explain how to use &lt;a class="reference external" href="http://releases.ubuntu.com/karmic/"&gt;Ubuntu Karmic 9.10&lt;/a&gt; and &lt;a class="reference external" href="http://www.virtualbox.org/"&gt;VirtualBox&lt;/a&gt; to create a small
virtual Linux server.&lt;/p&gt;
&lt;p&gt;To start off this tutorial, make sure you have a Ubuntu (or similar) desktop
system with VirtualBox configured and installed correctly.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Download one of the &lt;a class="reference external" href="https://help.ubuntu.com/community/Installation/MinimalCD"&gt;Ubuntu mini.iso Installer Image&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;[Optional]&lt;/strong&gt; Configure &lt;a class="reference external" href="http://www.unix-ag.uni-kl.de/%7Ebloch/acng/"&gt;apt-cacher-ng&lt;/a&gt; on your local system. This will
speed up the installation process, if you want to start over at any point.&lt;/li&gt;
&lt;li&gt;Create a new VirtualBox machine with the following configuration:&lt;ul&gt;
&lt;li&gt;Hard Disk: 1GB or larger&lt;/li&gt;
&lt;li&gt;Base memory: 256MB to 512MB&lt;/li&gt;
&lt;li&gt;Network Mode: Bridged Adapter&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;After creating the system, assign the &lt;a class="reference external" href="http://archive.ubuntu.com/ubuntu/dists/karmic/main/installer-i386/current/images/netboot/mini.iso"&gt;mini.iso&lt;/a&gt; image you downloaded as the
media for the emulated CD drive.&lt;/li&gt;
&lt;li&gt;Now start the virtual machine. It should boot the Ubuntu install boot
prompt. Select the &lt;tt class="docutils literal"&gt;Command Line&lt;/tt&gt; option to continue to the
installer.&lt;/li&gt;
&lt;li&gt;From the installer, continue following the default options:&lt;ul&gt;
&lt;li&gt;Set the system host name.&lt;/li&gt;
&lt;li&gt;Choose your local Ubuntu mirror.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;[Optional]&lt;/strong&gt; Set HTTP Proxy (when running &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;apt-cacher-ng&lt;/span&gt;&lt;/tt&gt;): &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://installer-host:3142/&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When you reach the disk partition step, use the following options:&lt;ul&gt;
&lt;li&gt;Choose the &lt;tt class="docutils literal"&gt;Manual&lt;/tt&gt; method.&lt;/li&gt;
&lt;li&gt;Verify there is a single root partition filling the entire virtual disk.&lt;/li&gt;
&lt;li&gt;Optionally, choose to enable &lt;tt class="docutils literal"&gt;noatime&lt;/tt&gt; on the partitions.&lt;/li&gt;
&lt;li&gt;Ignore any warnings about missing swap space, and confirm you wish to
erase the entire device. After this the base system will continue to
install.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The software package will finish and the grub boot loader should install.
Before restarting the system, make sure to unmount the ISO file in the
virtual drive.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From this point forward, the virtual machine can now boot and allow you to log
in as the user you configured during the install process.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/_0hj0zwgl2g" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2010/3/27/how-to-install-a-minimal-ubuntu-server-os-to-virtualbox</feedburner:origLink></entry>
  <entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">Share Files Over BitTorrent Using a Local Tracker and Client in Linux</title>
    <id>http://blog.tuxcoder.com/2009/5/24/share-files-over-bittorrent-using-a-local-tracker-and-client-in-linux</id>
    <updated>2009-05-24T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/TxuvV20sHjU/share-files-over-bittorrent-using-a-local-tracker-and-client-in-linux" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;img alt="/static/posts/006.bittorrent/bt_logo.png" class="align-right" src="/static/posts/006.bittorrent/bt_logo.png" style="width: 175px;" /&gt;
&lt;p&gt;Everyone has heard of the &lt;a class="reference external" href="http://en.wikipedia.org/wiki/BitTorrent_(protocol)"&gt;BitTorrent&lt;/a&gt; protocol. It's widely used to quickly
distribute large files with a low-bandwidth connection. There are also a lot of
other features in BitTorrent that make it superior to either HTTP or FTP. For
example, pseudo archives, built-in checksums, partial-download resumes, and
send/receive bandwidth capping.&lt;/p&gt;
&lt;p&gt;This post will show you how to share your personal files using BitTorrent
tools that come standard with Ubuntu Linux (Jaunty 9.04). This article will
cover the following steps:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Configuring and running a local &amp;quot;tracker&amp;quot; server.&lt;/li&gt;
&lt;li&gt;Building torrent files from your personal file(s) you wish to share.&lt;/li&gt;
&lt;li&gt;Auto-seed and share your active torrent files.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="section" id="configure-a-local-bittorrent-tracker-server"&gt;
&lt;h2&gt;Configure a Local BitTorrent Tracker Server&lt;/h2&gt;
&lt;p&gt;Before creating a torrent file, you should have an active tracker server
configured and running. It is perfectly acceptable to use a public tracker, but
running a personal tracker lets your clients connect over a private network
(192.168.*). Also, if your torrent files are for commercial use, you likely do
not want trust the reliability of your service to a third party.&lt;/p&gt;
&lt;p&gt;The BitTorrent tracker server must be accessible to all your clients. Also, it
must have either a static DNS or IP address so your clients can always contact
it.&lt;/p&gt;
&lt;p&gt;From the command line, install Bittornado, start the tracker, and verify it is
running:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo apt-get install bittornado
$ bttrack --port 6969 --dfile ~/.bttrack/dstate --logfile ~/.bttrack/tracker.log --nat_check 0 --scrape_allowed full
$ firefox http://localhost:6969
&lt;/pre&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;bttrack&lt;/tt&gt; command will start a tracker that allows clients behind NAT
connections. Connecting to the tracker port in FireFox will display a page with
known torrents and status of each one.&lt;/p&gt;
&lt;p&gt;Finally, be aware that with this configuration, the server will register all
torrent files it is notified of. So, potentially someone could use this tracker
for their own torrents. If you are on private network this may not be an issue,
or you can use additional options to restrict the torrents allowed on the
tracker:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
--allowed_dir $HOME/btfiles --parse_dir_interval 10 --allow_get 1
&lt;/pre&gt;
&lt;p&gt;These additional arguments to &lt;tt class="docutils literal"&gt;bttrack&lt;/tt&gt; will force the tracker to only use
files located the the &lt;tt class="docutils literal"&gt;~HOME/btfiles&lt;/tt&gt; directory. Remember, if you use these
options, your torrents must be manually copied into this directory before the
tracker will accept seeding requests.&lt;/p&gt;
&lt;div class="section" id="advanced-bttrack-config-and-settings"&gt;
&lt;h3&gt;Advanced Bttrack Config and Settings&lt;/h3&gt;
&lt;p&gt;Simplify the tracker startup with a simple shell script:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF &amp;gt; bin/bttrack.sh&lt;/span&gt;
&lt;span class="s"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="s"&gt;PORT=6969&lt;/span&gt;
&lt;span class="s"&gt;DFILE=&amp;quot;$HOME/.bttrack/dstate&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;LFILE=&amp;quot;$HOME/.bttrack/tracker.log&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;# GET=&amp;quot;--allowed_dir $HOME/btfiles --allow_get 1 --parse_dir_interval 10&amp;quot;&lt;/span&gt;
&lt;span class="s"&gt;OPTS=&amp;quot;--nat_check 0 --scrape_allowed full&amp;quot;&lt;/span&gt;

&lt;span class="s"&gt;mkdir -p $HOME/.bttrack&lt;/span&gt;
&lt;span class="s"&gt;bttrack --port $PORT --dfile $DFILE --logfile $LFILE $GET $OPTS&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;chmod 755 bin/bttrack.sh
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You may want to add &lt;tt class="docutils literal"&gt;bttrack&lt;/tt&gt; to your systems &lt;tt class="docutils literal"&gt;init.d&lt;/tt&gt; startup scripts.
Start with a copy of the default service skeleton file from
&lt;tt class="docutils literal"&gt;/etc/init.d/skeleton&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo cp /etc/init.d/skeleton /etc/init.d/bttrack
$ sudo vi /etc/init.d/bttrack
&lt;/pre&gt;
&lt;p&gt;Replace the top section of the &lt;tt class="docutils literal"&gt;/etc/init.d/bttrack&lt;/tt&gt; file using the
example code below. Notice that the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--dstate&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--logfile&lt;/span&gt;&lt;/tt&gt; values have
been changed to a more standard location.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/sbin:/usr/bin:/sbin:/bin
&lt;span class="nv"&gt;DESC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;BitTorrent protocol tracker&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bttrack
&lt;span class="nv"&gt;DAEMON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/bin/&lt;span class="nv"&gt;$NAME&lt;/span&gt;
&lt;span class="nv"&gt;DAEMON_ARGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;--dfile /var/run/$NAME/dstate --logfile /var/log/$NAME.log&lt;/span&gt;
&lt;span class="s2"&gt;   --port 6969 --nat_check 0 --scrape_allowed full&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;PIDFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/run/&lt;span class="nv"&gt;$NAME&lt;/span&gt;.pid
&lt;span class="nv"&gt;SCRIPTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/init.d/&lt;span class="nv"&gt;$NAME&lt;/span&gt;

do_start&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
 start-stop-daemon --start --quiet --pidfile &lt;span class="nv"&gt;$PIDFILE&lt;/span&gt; --exec &lt;span class="nv"&gt;$DAEMON&lt;/span&gt; --test &amp;gt; /dev/null &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;1
 start-stop-daemon --start --background --make-pidfile --quiet --pidfile &lt;span class="nv"&gt;$PIDFILE&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      --exec &lt;span class="nv"&gt;$DAEMON&lt;/span&gt; -- &lt;span class="nv"&gt;$DAEMON_ARGS&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;2
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="create-a-torrent-file"&gt;
&lt;h2&gt;Create a Torrent File&lt;/h2&gt;
&lt;p&gt;The next step is to create one or more torrents files to provide the necessary
information to begin seeding files inside of a &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Bittorrent_client"&gt;BitTorrent Client&lt;/a&gt;.  The
following command is not the only method you can use. The other options for
creating torrents is using a graphical client, such as &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Deluge_(software)"&gt;Deluge&lt;/a&gt; or
&lt;a class="reference external" href="http://en.wikipedia.org/wiki/Transmission_(BitTorrent_client)"&gt;Transmission&lt;/a&gt;.  I prefer the command line, since it is more concise:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo apt-get install bittornado
$ btmakemetafile --piece_size_pow2 SIZE http://URL.COM:PORT/announce SOURCE --target OUTPUT.torrent
&lt;/pre&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;SIZE [OPTIONAL]&lt;/dt&gt;
&lt;dd&gt;The torrent's &amp;quot;piece&amp;quot; size as a power of 2, where a &amp;quot;piece&amp;quot; is the smallest
transferable unit of data. For example, 512KB (19) and 1MB (20). If not
defined, this value is selected automatically. For fast connections, use a
larger value such as 4MB (22).&lt;/dd&gt;
&lt;dt&gt;http://URL.COM:PORT/announce&lt;/dt&gt;
&lt;dd&gt;The address of the tracker and port number. The address can either be a DNS
name or IP number.&lt;/dd&gt;
&lt;dt&gt;SOURCE&lt;/dt&gt;
&lt;dd&gt;The location of source directory or list of file(s) to add to the torrent.&lt;/dd&gt;
&lt;dt&gt;OUTPUT.torrent [OPTIONAL]&lt;/dt&gt;
&lt;dd&gt;The output name of the torrent file. Changing the name after creating the
torrent file will break some BitTorrent clients, so set the name hear. If
you leave this value empty, the torrent file will be named using the
&amp;lt;strong&amp;gt;SOURCE&amp;lt;/strong&amp;gt; name.&lt;/dd&gt;
&lt;dt&gt;--announce_list LIST [OPTIONAL]&lt;/dt&gt;
&lt;dd&gt;If your tracker has more than one DNS or IP, use this optional argument to
set all tracker addresses. Make sure to duplicate the primary announce
address, &lt;strong&gt;http://URL.COM:PORT/announce&lt;/strong&gt;, in this list as
well. The list can be &amp;quot;&lt;tt class="docutils literal"&gt;,&lt;/tt&gt;&amp;quot; separated for equal tiered trackers, or use
&amp;quot;&lt;tt class="docutils literal"&gt;|&lt;/tt&gt;&amp;quot; separator to indicate secondary trackers. See the &lt;a class="reference external" href="http://www.linux.gr/cgi-bin/man/man2html?btmakemetafile+1"&gt;man page&lt;/a&gt; for
more details.&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="section" id="seeding-and-sharing-torrent-files"&gt;
&lt;h2&gt;Seeding and Sharing Torrent Files&lt;/h2&gt;
&lt;p&gt;After you've created the torrent files for seeding, the final step is to start
them from any BitTorrent client. If you need to seed files for an extended
period of time, I recommend using &lt;a class="reference external" href="http://libtorrent.rakshasa.no/"&gt;rTorrent&lt;/a&gt; inside of a &lt;a class="reference external" href="http://www.gnu.org/software/screen/"&gt;screen&lt;/a&gt; session. This
allows you to run the client in the background, and pull-up the text-based GUI
at any time.&lt;/p&gt;
&lt;p&gt;The following steps will create an rTorrent configuration file that will
automatically load torrents from a target directory and begin seeding:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF &amp;gt; ~/.rtorrent.rc&lt;/span&gt;
&lt;span class="s"&gt;check_hash = no&lt;/span&gt;
&lt;span class="s"&gt;session = ~/.rtorrent&lt;/span&gt;
&lt;span class="s"&gt;directory = /data/torrents&lt;/span&gt;
&lt;span class="s"&gt;schedule = watch_directory,5,5,load_start=/data/torrents/autostart/*.torrent&lt;/span&gt;
&lt;span class="s"&gt;schedule = untied_directory,5,5,stop_untied=&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sudo apt-get install rtorrent screen
&lt;span class="nv"&gt;$ &lt;/span&gt;screen rtorrent
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;rTorrent should be running in the current terminal. If you are not familiar
with &lt;tt class="docutils literal"&gt;screen&lt;/tt&gt;, here are a few keyboard shortcuts for navigation:&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&amp;lt;Ctrl-a&amp;gt; ?&lt;/dt&gt;
&lt;dd&gt;Show screen's help&lt;/dd&gt;
&lt;dt&gt;&amp;lt;Ctrl-a&amp;gt; d&lt;/dt&gt;
&lt;dd&gt;Detach the screen session&lt;/dd&gt;
&lt;dt&gt;&amp;lt;Ctrl-a&amp;gt; k&lt;/dt&gt;
&lt;dd&gt;Kill current screen session&lt;/dd&gt;
&lt;dt&gt;&amp;lt;Ctrl-a&amp;gt; c&lt;/dt&gt;
&lt;dd&gt;Create a new shell window in screen&lt;/dd&gt;
&lt;dt&gt;&amp;lt;Ctrl-a&amp;gt; n&lt;/dt&gt;
&lt;dd&gt;Show next window&lt;/dd&gt;
&lt;dt&gt;&amp;lt;Ctrl-a&amp;gt; p&lt;/dt&gt;
&lt;dd&gt;Show previous window&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;If you close the screen session, you can reconnect with the command &amp;quot;&lt;tt class="docutils literal"&gt;screen
&lt;span class="pre"&gt;-r&lt;/span&gt;&lt;/tt&gt;&amp;quot;.&lt;/p&gt;
&lt;p&gt;After launching rTorrent, it is now possible to start seeding the torrents.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Move (or create a symbolic link to) the torrent data into rTorrent's
&amp;quot;download&amp;quot; directory. The default download directory is defined in the
&lt;tt class="docutils literal"&gt;rtorrent.rc&lt;/tt&gt; file.&lt;/li&gt;
&lt;li&gt;Notice that in the &lt;tt class="docutils literal"&gt;rtorrent.rc&lt;/tt&gt; file, it also specified the &amp;quot;watch&amp;quot;
directory. &lt;strong&gt;Place the new torrent files in the &amp;quot;watch&amp;quot; directory, and
they will be picked-up by rTorrent&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Go back to the rTorrent GUI, and verify that the torrent is being re-hashed
and seeded properly.&lt;/li&gt;
&lt;li&gt;Copy or e-mail the &lt;tt class="docutils literal"&gt;*.torrent&lt;/tt&gt; files you have created to anyone that you
want to share your files with.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="section" id="advanced-torrent-file-sharing"&gt;
&lt;h3&gt;Advanced Torrent File Sharing&lt;/h3&gt;
&lt;p&gt;Instead of manually sending &lt;tt class="docutils literal"&gt;*.torrent&lt;/tt&gt; files to your family and friends, a
better option is to run a public web server where the torrents can be made
available 24/7:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sudo apt install lighttpd
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/lighttpd
&lt;span class="nv"&gt;$ &lt;/span&gt;sudo bash -c &lt;span class="s1"&gt;&amp;#39;cat &amp;lt;&amp;lt;EOF &amp;gt; conf-available/40-site-torrent.conf&lt;/span&gt;
&lt;span class="s1"&gt;SERVER[&amp;quot;socket&amp;quot;] == &amp;quot;:88&amp;quot; {&lt;/span&gt;
&lt;span class="s1"&gt;   server.document-root    = &amp;quot;/data/torrents/autostart&amp;quot;&lt;/span&gt;
&lt;span class="s1"&gt;}&lt;/span&gt;
&lt;span class="s1"&gt;EOF&amp;#39;&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;sudo /etc/init.d/lighttpd restart
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This command creates a local web server running on port 88. The source
directory can be mapped directly to the &amp;quot;watch&amp;quot; directory of your BitTorrent
client. This is where all the active torrent files are stored while the
torrents are active. Once enabled, the torrent files can be accessed from
&lt;a class="reference external" href="http://localhost:88/"&gt;http://localhost:88/&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/TxuvV20sHjU" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2009/5/24/share-files-over-bittorrent-using-a-local-tracker-and-client-in-linux</feedburner:origLink></entry>
  <entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">Mounting Unknown RAID+LVM Volumes Step-by-Step</title>
    <id>http://blog.tuxcoder.com/2009/5/2/mounting-unknown-raid-lvm-volumes-step-by-step</id>
    <updated>2009-05-02T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/2FS-0DrKkgI/mounting-unknown-raid-lvm-volumes-step-by-step" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;p&gt;Every time your system boots, startup scripts will handle all disk mounting
tasks. This is good, yet unfortunate if you ever run in to problems, because
you're going to need to know how to get things up without the help of the
scripts. On my systems, I run a combination of &lt;a class="reference external" href="http://http://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)"&gt;LVM&lt;/a&gt; volumes on top of multiple
&lt;a class="reference external" href="http://en.wikipedia.org/wiki/RAID"&gt;RAID&lt;/a&gt; arrays. This provides data integrity and future flexibility to add more
space as needed, and makes recovery very complicated.&lt;/p&gt;
&lt;p&gt;There are two cases where you will eventually need to know how this all works.
The most likely case is recovering from a boot failure, in which you are
relatively familiar with the configuration. An even more difficult case is
mounting a set of unknown drives with a RAID/LVM configuration. Keep reading
and I'll explain how you can handle even the hardest case like a pro.&lt;/p&gt;
&lt;div class="warning"&gt;
&lt;p class="first admonition-title"&gt;Warning&lt;/p&gt;
&lt;p class="last"&gt;If there is a chance you will be mounting two or more &lt;strong&gt;LVM Volume Groups
with identical names&lt;/strong&gt;, then read the warning at end before continuing.&lt;/p&gt;
&lt;/div&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;After installing all the drives into the system, verify they are detected in
&lt;tt class="docutils literal"&gt;/dev/sd*&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ls /dev/sd*
/dev/sda   /dev/sdb   /dev/sdc   /dev/sdd   /dev/sde   /dev/sdf   /dev/sdf3
/dev/sda1  /dev/sdb1  /dev/sdc1  /dev/sdd1  /dev/sde1  /dev/sdf1  /dev/sdf4
/dev/sda2  /dev/sdb2  /dev/sdc2  /dev/sdd2  /dev/sde2  /dev/sdf2
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Find out which partitions of those are mounted:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ df -lhx tmpfs
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/lvm_vg0-root
                       10G  3.7G  6.4G  37% /
/dev/mapper/lvm_vg0-home
                      160G   83G   78G  52% /home
/dev/md0               99M   16M   79M  17% /boot
&lt;/pre&gt;
&lt;p&gt;This output doesn't directly indicate what partitions are being used.
Instead it indicates two LVM volumes; &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/dev/mapper/lvm_vg0-root&lt;/span&gt;&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/dev/mapper/lvm_vg0-home&lt;/span&gt;&lt;/tt&gt; and one RAID array; &lt;tt class="docutils literal"&gt;/dev/md0&lt;/tt&gt;. The next
steps will reduce this info to the physical partitions.&lt;/p&gt;
&lt;ol class="loweralpha"&gt;
&lt;li&gt;&lt;p class="first"&gt;Lookup the two LVM volumes &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;lvm_vg0-root&lt;/span&gt;&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;lvm_vg0-home&lt;/span&gt;&lt;/tt&gt; to determine the LVM volume group (VG):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo lvdisplay | grep 'VG Name'
  VG Name                lvm_vg0
  VG Name                lvm_vg0
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The LVM VG, &lt;tt class="docutils literal"&gt;lvm_vg0&lt;/tt&gt;, maps to one ore more physical volumes:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo pvdisplay
  --- Physical volume ---
  PV Name               /dev/md1
  VG Name               lvm_vg0
  PV Size               297.99 GB / not usable 3.25 MB
  Allocatable           yes
  PE Size (KByte)       4096
  Total PE              76285
  Free PE               32765
  Allocated PE          43520
  PV UUID               mD6jat-SvPv-dOop-P3qZ-T7zC-r8ke-xSYRSj
&lt;/pre&gt;
&lt;p&gt;This output shows us that the LVM physical volume (PV) is using
&lt;tt class="docutils literal"&gt;/dev/md1&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Now, lookup &lt;tt class="docutils literal"&gt;md0&lt;/tt&gt; (from the top step) and &lt;tt class="docutils literal"&gt;md1&lt;/tt&gt; devices:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ cat /proc/mdstat
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
md1 : active raid10 sde2[0] sdd2[1]
      312466688 blocks 64K chunks 2 far-copies [2/2] [UU]

md0 : active raid1 sde1[0] sdd1[1]
      104320 blocks [2/2] [UU]
&lt;/pre&gt;
&lt;p&gt;OK, so the final answer is that &lt;tt class="docutils literal"&gt;md1&lt;/tt&gt; is using partitions: &lt;tt class="docutils literal"&gt;sde2&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;sdd2&lt;/tt&gt; and array &lt;tt class="docutils literal"&gt;md0&lt;/tt&gt; is using partitions: &lt;tt class="docutils literal"&gt;sde1&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;sdd1&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Now, create list of unmounted partitions, by filtering out the mounted
partitions:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ls --color=none /dev/sd* | grep [0-9] | egrep -v 'sde2|sdd2|sde1|sdd1'
/dev/sda1
/dev/sda2
/dev/sdb1
/dev/sdb2
/dev/sdc1
/dev/sdc2
/dev/sdf1
/dev/sdf2
/dev/sdf3
/dev/sdf4
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;To find RAID partitions, every device can be scanned for volume UUID value:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ mdadm --examine /dev/sda1 | grep UUID
           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
&lt;/pre&gt;
&lt;p&gt;With a little more work, all the unmounted devices can be scanned in a
single pass:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ls --color=none /dev/sd* | grep [0-9] | egrep -v 'sde2|sdd2|sde1|sdd1' | xargs -i sh -c 'sudo mdadm --examine {} | grep -H --label={} UUID'
/dev/sda1:           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
/dev/sda2:           UUID : cd72d060:e1139a47:8d379926:979de13e
/dev/sdb1:           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
/dev/sdb2:           UUID : 2eb0a293:e7705a2f:8d379926:979de13e
mdadm: No md superblock detected on /dev/sdc1.
/dev/sdc2:           UUID : 29d74ba3:2dff5d1d:e1635e97:4ded1971
mdadm: No md superblock detected on /dev/sdf1.
/dev/sdf2:           UUID : 29d74ba3:2dff5d1d:e1635e97:4ded1971
/dev/sdf3:           UUID : 2eb0a293:e7705a2f:8d379926:979de13e
/dev/sdf4:           UUID : cd72d060:e1139a47:8d379926:979de13e
&lt;/pre&gt;
&lt;p&gt;It looks like every device is part of a RAID array except &lt;tt class="docutils literal"&gt;/dev/sdc1&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;/dev/sdf1&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Manually sort the list in the last step by the UUID values. Every matching
UUID value indicates a single RAID array. Here is what your list should look
like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
/dev/sda1:           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
/dev/sdb1:           UUID : ae9a1594:27fc3cec:ceff8456:d50a26a6
-----
/dev/sda2:           UUID : cd72d060:e1139a47:8d379926:979de13e
/dev/sdf4:           UUID : cd72d060:e1139a47:8d379926:979de13e
-----
/dev/sdb2:           UUID : 2eb0a293:e7705a2f:8d379926:979de13e
/dev/sdf3:           UUID : 2eb0a293:e7705a2f:8d379926:979de13e
-----
/dev/sdc2:           UUID : 29d74ba3:2dff5d1d:e1635e97:4ded1971
/dev/sdf2:           UUID : 29d74ba3:2dff5d1d:e1635e97:4ded1971
&lt;/pre&gt;
&lt;p&gt;Using these value, assemble each RAID array. The &lt;tt class="docutils literal"&gt;/dev/md*&lt;/tt&gt; is not
important as long as you choose a value that does not currently exists in
the system.:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo mdadm --assemble /dev/md2 /dev/sda1 /dev/sdb1
mdadm: /dev/md2 has been started with 2 drives.

$ sudo mdadm --assemble /dev/md3 /dev/sda2 /dev/sdf4
mdadm: /dev/md3 has been started with 2 drives.

$ sudo mdadm --assemble /dev/md4 /dev/sdb2 /dev/sdf3
mdadm: /dev/md4 has been started with 2 drives.

$ sudo mdadm --assemble /dev/md5 /dev/sdc2 /dev/sdf2
mdadm: /dev/md5 has been started with 2 drives.
&lt;/pre&gt;
&lt;p&gt;Now check that all the previous steps by printing the &lt;tt class="docutils literal"&gt;mdstat&lt;/tt&gt; file:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ cat /proc/mdstat
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
md5 : active raid10 sdc2[0] sdf2[1]
      488281984 blocks 64K chunks 2 far-copies [2/2] [UU]

md4 : active raid10 sdb2[0] sdf3[1]
      244094080 blocks 64K chunks 2 far-copies [2/2] [UU]

md3 : active raid10 sda2[0] sdf4[1]
      244094080 blocks 64K chunks 2 far-copies [2/2] [UU]

md2 : active raid1 sdb1[0] sda1[1]
      104320 blocks [2/2] [UU]

md1 : active raid10 sde2[0] sdd2[1]
      312466688 blocks 64K chunks 2 far-copies [2/2] [UU]

md0 : active raid1 sde1[0] sdd1[1]
      104320 blocks [2/2] [UU]

unused devices: &amp;lt;none&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;When you are happy with the device mappings, update the
&lt;tt class="docutils literal"&gt;/etc/mdadm/mdadm.conf&lt;/tt&gt; file:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo sh -c 'mdadm --detail --scan &amp;gt;&amp;gt; /etc/mdadm/mdadm.conf'
&lt;/pre&gt;
&lt;p&gt;After this step, edit the file to remove any old entries.&lt;/p&gt;
&lt;div class="important"&gt;
&lt;p class="first admonition-title"&gt;Important&lt;/p&gt;
&lt;p class="last"&gt;Because of a bug in mdadm, change the &amp;quot;&lt;tt class="docutils literal"&gt;metadata&lt;/tt&gt;&amp;quot; version from
&amp;quot;&lt;tt class="docutils literal"&gt;00.90&lt;/tt&gt;&amp;quot; to &amp;quot;&lt;tt class="docutils literal"&gt;0.90&lt;/tt&gt;&amp;quot;.&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Now, with the RAID arrays active, scan for LVM volumes. First the physical
volumes (PV):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo pvscan
  PV /dev/md4   VG lvm_vg0   lvm2 [232.79 GB / 0    free]
  PV /dev/md3   VG lvm_vg0   lvm2 [232.79 GB / 956.00 MB free]
  PV /dev/md5   VG lvm_vg0   lvm2 [465.66 GB / 274.60 GB free]
  PV /dev/md1   VG lvm_vg0   lvm2 [297.99 GB / 127.99 GB free]
  Total: 4 [1.20 TB] / in use: 4 [1.20 TB] / in no VG: 0 [0   ]
&lt;/pre&gt;
&lt;p&gt;Next the volume groups (VG):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ sudo vgdisplay
  --- Volume group ---
  VG Name               lvm_vg0
  System ID
  Format                lvm2
  Metadata Areas        3
  Metadata Sequence No  58
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                3
  Open LV               1
  Max PV                0
  Cur PV                3
  Act PV                3
  VG Size               931.23 GB
  PE Size               4.00 MB
  Total PE              238395
  Alloc PE / Size       167859 / 655.70 GB
  Free  PE / Size       70536 / 275.53 GB
  VG UUID               yLjVr3-BKkp-BW33-QIsh-rpZX-byL7-bzF2Xg

  --- Volume group ---
  VG Name               lvm_vg0
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               297.99 GB
  PE Size               4.00 MB
  Total PE              76285
  Alloc PE / Size       43520 / 170.00 GB
  Free  PE / Size       32765 / 127.99 GB
  VG UUID               138ikB-v1Z0-381g-Qvi8-dWN2-pgJ7-namuLh
&lt;/pre&gt;
&lt;div class="warning"&gt;
&lt;p class="first admonition-title"&gt;Warning&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Be very careful if your system indicates identically named LVM Volume
Groups&lt;/strong&gt; (shown above). LVM will NOT let you mount the volumes from one
or all of the groups. You must resolve the name conflict before
continuing.&lt;/p&gt;
&lt;p class="last"&gt;Additionally, you will not be able to rename LVM VGs if either the old or
new VG has mounted logical volumes! If one of your VG's LV's is the &lt;strong&gt;root&lt;/strong&gt;
volume, you will have to resort to a live-boot CD.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;A VG can be renamed with the following command:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ vgrename vg0-old vg0-new
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Finally, mount the new volumes and update your &lt;tt class="docutils literal"&gt;/etc/fstab&lt;/tt&gt; like normal.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/2FS-0DrKkgI" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2009/5/2/mounting-unknown-raid-lvm-volumes-step-by-step</feedburner:origLink></entry>
  <entry xml:base="http://blog.tuxcoder.com/feed.atom">
    <title type="text">Better Google Keyboard Shortcuts using Greasemonkey</title>
    <id>http://blog.tuxcoder.com/2009/3/5/better-google-keyboard-shortcuts-using-greasemonkey</id>
    <updated>2009-03-05T00:00:00Z</updated>
    <link href="http://feedproxy.google.com/~r/tuxcoder/~3/j6s6oSZg2hw/better-google-keyboard-shortcuts-using-greasemonkey" />
    <author>
      <name>Patrick C. McGinty</name>
    </author>
    <content type="html">&lt;div class="caution"&gt;
&lt;p class="first admonition-title"&gt;Caution!&lt;/p&gt;
&lt;p class="last"&gt;This post should only be used for historical reference. I am no longer
supporting the Greasemonkey script at this time.&lt;/p&gt;
&lt;/div&gt;
&lt;img alt="/static/posts/005.greasemonkey/google_key.jpg" class="align-right" src="/static/posts/005.greasemonkey/google_key.jpg" style="width: 250px;" /&gt;
&lt;p&gt;I used to be one of those &amp;quot;simple&amp;quot; folk using &lt;a class="reference external" href="http://www.google.com/"&gt;Google&lt;/a&gt; the &lt;em&gt;normal&lt;/em&gt; way. This
has got to be one of the most aggravating experiences. Even more so when
looking for answers on an obscure topic. This is because Google is tricky to
use, and getting results always takes multiple attempts. Even with a good
search, it's likely the best match is buried a few pages in. The action of
typing, scrolling, mousing, then clicking a few links, only to &amp;quot;&lt;em&gt;rinse and
repeat&lt;/em&gt;&amp;quot; 15 seconds later is enough to inflame my wrist with an &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Repetitive_strain_injury"&gt;RSI&lt;/a&gt; in under
20 minutes. After a full day of work, this becomes hazardous to your health.&lt;/p&gt;
&lt;p&gt;You might be thinking that this kind of thing doesn't bother you. Well, just
wait until you try Google with optimized keyboard shortcuts. You will never
want to go back, I promise!&lt;/p&gt;
&lt;p&gt;Since sometime back in 2008, I have been using the &lt;a class="reference external" href="http://www.google.com/experimental/"&gt;Google Experimental
Keyboard Search&lt;/a&gt; feature to the point that it is almost second nature. With
it, I can bring up a search and get 10 result pages loading in the background,
in under 5 seconds. The speed comes from the fact that you can search and open
selected results without ever having to leave the keyboard. &lt;a class="reference external" href="http://www.google.com/search?q=rattlesnake&amp;amp;esrch=BetaShortcuts"&gt;Try it out for
yourself&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="http://www.google.com/experimental/"&gt;You can easily enable this feature&lt;/a&gt;,
but there are a few minor annoyances you have to deal with:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;The &amp;quot;stickiness&amp;quot; of the feature is tricky and I frequently find that the
Google search page eventually resets back to the default mode. The only way
to solve this it seems is to go back and re-join the experiment.&lt;/li&gt;
&lt;li&gt;There is no way to skip forward or back in the search results. Essentially
you are stuck to the first page of results. This actually used to not be an
issue, but sometime around late 2008 the &lt;strong&gt;J&lt;/strong&gt;/&lt;strong&gt;K&lt;/strong&gt; keys were disabled from
jumping to the next and previous result pages.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="section" id="greasemonkey-script"&gt;
&lt;h2&gt;Greasemonkey Script&lt;/h2&gt;
&lt;img alt="/static/posts/005.greasemonkey/screen.jpg" class="align-right" src="/static/posts/005.greasemonkey/screen.jpg" style="width: 250px;" /&gt;
&lt;p&gt;Ok, so what is the solution to the bugs? The answer is &lt;a class="reference external" href="http://www.greasespot.net/"&gt;Greasemonkey&lt;/a&gt;. If you
haven't heard of Greasemonkey, it is an &lt;a class="reference external" href="https://addons.mozilla.org/en-US/firefox/addon/748"&gt;add-on for Firefox&lt;/a&gt; users (&lt;em&gt;you do use
Firefox right?&lt;/em&gt;) to tweak any web page you download with custom JavaScript
code.&lt;/p&gt;
&lt;p&gt;I wrote a custom Greasemonkey script that will always enable the Google
Experimental Keyboard Search feature. This script also solves the other two
bugs listed above.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="setup"&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;Using Greasemonkey and user scripts is easy.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;If you do not have Greasemonkey, &lt;a class="reference external" href="https://addons.mozilla.org/en-US/firefox/addon/748"&gt;install it from the Mozilla Add-on page&lt;/a&gt;. Restart Firefox.&lt;/li&gt;
&lt;li&gt;Install my &lt;a class="reference external" href="http://userscripts.org/scripts/show/43131"&gt;Google Search Enhanced Keyboard Navigation&lt;/a&gt; user script with the &lt;a class="reference external" href="http://userscripts.org/scripts/source/43131.user.js"&gt;Installer
Link&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="usage"&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;After the script is installed, the Google search result page will have a
selection arrow on the left-hand side. The arrow indicates the active link that
can be opened.&lt;/p&gt;
&lt;p&gt;The following keyboard commands can control the page navigation:&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="15%" /&gt;
&lt;col width="85%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Key&lt;/th&gt;
&lt;th class="head"&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;Opens the previous results page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;J&lt;/td&gt;
&lt;td&gt;Selects the next result.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;K&lt;/td&gt;
&lt;td&gt;Selects the previous result.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;Opens the next results page.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;Opens the selected result.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;lt;Enter&amp;gt;&lt;/td&gt;
&lt;td&gt;Opens the selected result.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;/&lt;/td&gt;
&lt;td&gt;Puts the cursor in the search box.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&amp;lt;Esc&amp;gt;&lt;/td&gt;
&lt;td&gt;Removes the cursor from the search box.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Happy Googling!&lt;/p&gt;
&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/tuxcoder/~4/j6s6oSZg2hw" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://blog.tuxcoder.com/2009/3/5/better-google-keyboard-shortcuts-using-greasemonkey</feedburner:origLink></entry>
</feed>
