<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
<channel>
<title>Custom IT Consulting Company, Based in NYC</title>
<atom:link href="http://www.atlanticdynamic.com/feed/" rel="self" type="application/rss+xml" />
<link>http://www.atlanticdynamic.com</link>
<description>atlanticdynamic.com</description>
<lastBuildDate>Tue, 27 Nov 2012 22:24:11 +0000</lastBuildDate>
<language>en-US</language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<item>
<title>pgpool2 error: &#8220;pool_get_passwd: username is NULL&#8221;</title>
<link>http://www.atlanticdynamic.com/pgpool2-erro/</link>
<comments>http://www.atlanticdynamic.com/pgpool2-erro/#comments</comments>
<pubDate>Tue, 27 Nov 2012 22:23:19 +0000</pubDate>
<dc:creator>admin</dc:creator>
<category>
<![CDATA[Linux]]>
</category>
<category>
<![CDATA[Postgres]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=469</guid>
<description>
<![CDATA[If you receive the following error from pgpool2 pool_get_passwd: username is NULL, make sure to set enable_pool_hba = on in your pgpool.conf.]]>
</description>
<content:encoded>
<![CDATA[<p>If you receive the following error from pgpool2 <code>pool_get_passwd: username is NULL</code>, make sure to set <code>enable_pool_hba = on</code> in your pgpool.conf.</p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/pgpool2-erro/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Web server performance analysis : 2012</title>
<link>http://www.atlanticdynamic.com/web-server-performance-analysis-2012/</link>
<comments>http://www.atlanticdynamic.com/web-server-performance-analysis-2012/#comments</comments>
<pubDate>Fri, 15 Jun 2012 01:00:10 +0000</pubDate>
<dc:creator>Rob Terhaar</dc:creator>
<category>
<![CDATA[Performance]]>
</category>
<category>
<![CDATA[Python]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=399</guid>
<description>
<![CDATA[The famous Apache web server has recently received a negative reputation for being hard to configure, slow, and unable to handle &#8220;web-scale&#8221; traffic. Many people are moving their web traffic to newer web servers such as node.js and Nginx, but don&#8217;t really understand the benefits of these servers as compared to Apache. The performance benefits [...]]]>
</description>
<content:encoded>
<![CDATA[<p>The famous Apache web server has recently received a negative reputation for being hard to configure, slow, and unable to handle &#8220;web-scale&#8221; traffic. Many people are moving their web traffic to newer web servers such as node.js and Nginx, but don&#8217;t really understand the benefits of these servers as compared to Apache. The performance benefits of these newer web servers is notable, but only with specific traffic patterns.</p>
<p>Apache can do &#8220;web-scale&#8221;. Sometimes.</p>
<p><span id="more-399"></span></p>
<p>Benchmark results can very wildly, depending on everything from the color of Ethernet cables used (not really) to the kernel revision, and the major/minor point release and patch set of the software tested. Nginx 1.2.1 may have very different performance characteristics as compared to the Nginx 1.1.19-ubuntu-1 package that comes with Ubuntu 12.04. Due to the unpredicable performance of EC2 instances, all of the benchmarks were run multiple times, and the fastest test results were selected for comparison.</p>
<p>The performance of web server software will be very different for various web traffic workloads. For example, Nginx is a much better choice for internet radio streaming compared to Apache. You should perform benchmarks with your application on various web servers to understand the unique performance characteristics of your site.</p>
<p>The goal of this benchmark was to test raw throughput and average response time under load of various web servers. This benchmark did not test websockets, long-polling, large file transfers, or streaming. Each of the web servers were tuned and configured to the simple task of returning the string: &#8220;Hello World&#8221;. All of the benchmarks were performed on c1.medium EC2 instances, running Ubuntu 12.04 64bit. The benchmarks were run using <a href="http://jmeter.apache.org">JMeter 2.7</a>, and visualizations were produced by <a href="Loadosophia.org">Loadosophia.org</a>.</p>
<p>The Contenders:</p>
<table border="1">
<tbody>
<tr>
<th>Software</th>
<th>Revision</th>
<th>Notes</th>
</tr>
<tr>
<td>Apache &#8211; mpm_worker</td>
<td>2.2.22-1ubuntu1</td>
<td>Used the native Ubuntu packages available via `sudo apt-get install apache2`</td>
</tr>
<tr>
<td>Apache &#8211; mpm_event</td>
<td>2.2.22-1ubuntu1</td>
<td>Same as previous test target, but with a different MPM. Apache has plugable MPM back-ends, that have different response characteristics for various workloads.</td>
</tr>
<tr>
<td>Nginx</td>
<td>1.1.19-1</td>
<td>sudo apt-get install nginx</td>
</tr>
<tr>
<td>Brubeck b/w Mongrel2</td>
<td>Brubeck: 0.4.0 <br /> Mongrel2: Dev branch as of May 29, 2012</td>
<td>Advised in #mongrel2 to use the dev branch for benchmarks</td>
</tr>
<tr>
<td>Brubeck WSGI</td>
<td>0.4.0</td>
<td>Single process</td>
</tr>
<tr>
<td>Tornado</td>
<td>2.3</td>
<td>Single process.</td>
</tr>
</tbody>
</table>
<h2>Maximum throughput test</h2>
<p>The goal of this benchmark was to test the average response times under various amounts of load. Ideally, a good web server will respond quickly and the standard deviation of the requests will be minimal. We want low latency and consistent response times.</p>
<p>This test was run for about 8 minutes, started out with 100 jmeter threads un-capped with no timer, then moved upto 500, 1000, and finally 2000. Between each thread group run, there was a small cool-down period.</p>
<h3>Apache 2 &#8211; mpm_worker</h3>
<p><a href="https://loadosophia.org/examples/11760/"><img class="alignleft  wp-image-410" title="t1-apache2-worker" src="http://www.atlanticdynamic.com/wp-content/uploads/2012/06/t1-apache2-worker.png" alt="" width="480" height="340" /></a><strong>mpm_worker</strong> was able to sustain about 3.1k Requests-per-second, with an average response time of 132ms. Not much to say here, this test was performed as a simple baseline.</p>
<h3>Apache 2 &#8211; mpm_event</h3>
<p><a href="https://loadosophia.org/examples/11762/"><img class="alignleft  wp-image-411" title="t1- apache2-event" src="http://www.atlanticdynamic.com/wp-content/uploads/2012/06/t1-apache2-event.png" alt="" width="480" height="340" /></a><strong>mpm_event</strong> was slightly slower than <strong>mpm_worker</strong>, coming in at 3k Requests-per-second, with an average response time of 136ms. However in the 500-thread test, the standard deviation of the test results was lower compared to mpm_worker. </p>
<p>These results were surprising to me, since <strong>mpm_event</strong> is generally considered to be faster than <strong>mpm_worker</strong>.</p>
<p>&nbsp;</p>
<h3>Nginx</h3>
<p><a href="https://loadosophia.org/examples/11759/"><img class="alignleft  wp-image-418" title="t1-nginx" src="http://www.atlanticdynamic.com/wp-content/uploads/2012/06/t1-nginx.png" alt="" width="480" height="340" /></a><strong>Nginx</strong> was able to outperform <strong>Apache</strong> in these tests, but by a very small margin. The max requests-per-second hit 3.3k, and average response time was 117ms. However, the standard deviation was much higher than <strong>Apache</strong>. </p>
<p><strong>Nginx</strong> is slightly faster than <strong>Apache</strong> in this test, but <strong>Nginx</strong> does not show nearly as consistent performance.</p>
<p>&nbsp;</p>
<h3>Brubeck b/w Mongrel2</h3>
<p><a href="https://loadosophia.org/examples/11597/"><img class="alignleft  wp-image-417" title="t1-mongrel2" src="http://www.atlanticdynamic.com/wp-content/uploads/2012/06/t1-mongrel2.png" alt="" width="480" height="340" /></a>The performance of <strong>Mongrel2</strong> was the fastest of all servers, but it quickly it became overloaded. At 100 threads <strong>Mongrel2</strong> was able to sustain the highest RPS of the test, 6k RPS, at 28ms latency! However, as soon as <strong>Mongrel2</strong> hit a tipping point, it quickly fell over. </p>
<p>With the default configuration, running as non-root, <strong>Mongrel2</strong> hits a limit of file descriptors. I increased the file descriptors to 65535, and found that the max requests-per-second that <strong>Mongrel2</strong> was able to serve got cut in half from 6k down to 3k.</p>
<p>&nbsp;<br />
Zed Shaw wrote an <a href="http://sheddingbikes.com/posts/1280829388.html">article</a> about the polling mechanism in Mongrel2, and Willy Tarreau (author of haproxy, and epoll advocate) explains why adding more file descriptors actually slows down <strong>Mongrel2</strong> in <a href="http://www.mail-archive.com/haproxy@formilux.org/msg05526.html">this article</a>.</p>
<p>Even in the test with the increased file descriptors, <strong>Mongrel2</strong> had really good performance up to through 500 threads, but quickly fell over when 1000 jmeter threads came stampeding through. I was told that this performance limitation was probably related to internal ZeroMQ configs that <strong>Mongrel2</strong> does not currently expose for tuning. See also 6k RPS Data here: <a href="https://loadosophia.org/examples/11579/">https://loadosophia.org/examples/11579/</a></p>
<p>&nbsp;</p>
<h3>Brubeck WSGI</h3>
<p><a href="https://loadosophia.org/examples/11576/"><img class="alignleft  wp-image-422" title="t1-brubeck-wsgi" src="http://www.atlanticdynamic.com/wp-content/uploads/2012/06/t1-brubeck-wsgi.png" alt="" width="480" height="340" /></a>Until recently, <strong>Brubeck</strong> required running a <strong>Mongrel2</strong> instance in order to serve web traffic. But to ease the <strong>Brubeck</strong> development workflow, they recently added WSGI support. This benchmark shows the WSGI interface is highly performant and stable (I encountered no errors up until the 2000 thread test at the end of the test).</p>
<p>My first test followed the &#8220;hello world&#8221; example on the front of <a href="http://brubeck.io">brubeck.io</a>. I shared the results of the test with the development team in #brubeck,. They asked me to rerun the tests using function-based views.</p>
<p>By switching from class-based to function-based views I was able to increase the performance of <strong>Brubeck</strong> by 30%.</p>
<p>In the function-based views test, <strong>Brubeck</strong> WSGI was able to maintain an average 2.6kRPS, and response times had the lowest standard deviation observed throughout the entire test at 100 and 500 threads.</p>
<p>My theory is <strong>Brubeck</strong> has the most consistent performance of all the servers tested because it&#8217;s the only server that uses <a href="http://en.wikipedia.org/wiki/Green_threads">green threads</a>. Context switches are extremely slow in virtualized environments like EC2, much slower than on real hardware. By using python-managed threads instead of OS-managed threads like the other servers tested above, Brubeck is able to handle many more requests in a single scheduled clock cycle. For more information about gevent, and green threads, go watch <a href="http://pyvideo.org/video/618/optimize-performance-and-scalability-with-paralle">Bob Hancock&#8217;s tutorial from PyCon 2012</a> about concurrency.</p>
<p>See also: <strong>Brubeck</strong> class-based views data: <a href="https://loadosophia.org/examples/11575/">https://loadosophia.org/examples/11575/</a></p>
<p>&nbsp;</p>
<h3>Tornado</h3>
<p><a href="https://loadosophia.org/examples/11767/"><img class="alignleft  wp-image-423" title="t1-tornado" src="http://www.atlanticdynamic.com/wp-content/uploads/2012/06/t1-tornado.png" alt="" width="480" height="340" /></a>The design of <strong>Brubeck</strong> was inspired by the <strong>Tornado</strong> web server. However, where <strong>Brubeck</strong> differs is that <strong>Tornado</strong> prefers to use callbacks instead of gevent for concurrency. This model of programming can be confusing to implement, because you essentially have to program in reverse.</p>
<p>The performance of <strong>Tornado</strong> was not much faster than the traditional <strong>Apache</strong>/<strong>Nginx</strong> servers for this test, and was only able to sustain an average of 2k RPS, at 344ms. <strong>Tornado</strong> was not designed to handle this type of rapid ballistic traffic pattern, and it is much better suited for long-polling, or streaming data.</p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/web-server-performance-analysis-2012/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Guide to using Virtualenv and Python</title>
<link>http://www.atlanticdynamic.com/guide-to-using-virtualenv-and-python/</link>
<comments>http://www.atlanticdynamic.com/guide-to-using-virtualenv-and-python/#comments</comments>
<pubDate>Thu, 12 Apr 2012 12:17:28 +0000</pubDate>
<dc:creator>Rob Terhaar</dc:creator>
<category>
<![CDATA[Apple]]>
</category>
<category>
<![CDATA[Code]]>
</category>
<category>
<![CDATA[Python]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=380</guid>
<description>
<![CDATA[There are a few different methods for managing your Python development projects. Virtualenv tends to be at the core of these management systems. When I first got started with Python, my really smart Python friends said &#8220;Use Virtualenv!!&#8221; And honestly, I didn&#8217;t really listen to my smart Python friends at first. I didn&#8217;t listen to [...]]]>
</description>
<content:encoded>
<![CDATA[<p>There are a few different methods for managing your Python development projects. Virtualenv tends to be at the core of these management systems. When I first got started with Python, my really smart Python friends said &#8220;Use Virtualenv!!&#8221; And honestly, I didn&#8217;t really listen to my smart Python friends at first. I didn&#8217;t listen to them because I didn&#8217;t see the point of using Virtualenv instead of just installing &#8220;global&#8221; packages using: <code>sudo pip install foo</code></p>
<p><span id="more-380"></span></p>
<p>If you already use Virtualenv, great! I don&#8217;t have to tell you why it&#8217;s a good thing to use. But if you&#8217;re not using Virtualenv yet, give me two inches of screen space to explain why you should.</p>
<p>Virtualenv allows you to store projects in complete, self-contained folders. This means that when Django 1.4 came out last month, you can quickly try it out without breaking all of your Django 1.3 projects. You might think, &#8220;I only have one project!&#8221; This will change quickly. Using Virtualenv also allows you to git-clone other people&#8217;s projects, read their code, run their programs, and become inspired by their really smart ideas.</p>
<p>If you build an easy system to manage your Virtualenv projects, it&#8217;s actually easier to use Virtualenv, than not.</p>
<p>Now that I&#8217;ve convinced you to use Virtualenv to manage your python projects, I&#8217;ll explain my favorite way to work with Python and multiple Virtualenvs.</p>
<p><strong>I primarily use:</strong></p>
<ol>
<li>OS X Lion (but Linux is a fine choice as well)</li>
<li>MacPorts (Yes, I use a BSD-style package manager on a BSD system. If you&#8217;re using some ruby-based SYSV style package manager, that&#8217;s probably fine as well.)</li>
<li>Python27 (from Ports)</li>
<li>virtualenv &amp; virtualenv wrapper</li>
<li>Setup your virtualenv bash environment variables</li>
<li>Some clever pre/post hooks for virtualenv wrapper</li>
<li>Dropbox, to keep this all sync&#8217;d from my laptop/desktop</li>
</ol>
<p><strong>The Basics</strong></p>
<p>Assuming that you&#8217;re using OS X Lion, with Macports, this next section will be applicable to you. If you&#8217;re not using those, I assume you have enough Google skills to install Python, Virtualenv and Virtualenvwrapper. Skip to the advanced section below for my pre/post hooks and bash magic.</p>
<p><strong>1. OS X</strong><br />
Make sure all Apple updates are installed. As of writing this tutorial, the latest OS X is 10.7.3.<br />
Apple recently split out the command-line compilers as a peripheral download, called &#8220;Command Line Tools for Xcode&#8221;, search around on <a title="https://developer.apple.com/downloads/" href="https://developer.apple.com/downloads/" target="_blank">https://developer.apple.com/downloads/</a> for it, download it, install it. (should be about 171mb.)</p>
<p>If you have already installed Xcode from the Apple Appstore, open Xcode, open the preferences, and check the downloads tab to install the latest version of the command line tools. The fact that Apple split out these tools is interesting, and I&#8217;ve written about what I think that it means for the future of OSx in another post.</p>
<p><strong>2. MacPorts</strong><br />
Many people are starting to use Brew instead of MacPorts. I prefer MacPorts because it does not rely on as many OS libraries, thus is less susceptible to Apple&#8217;s bugs and secretive updates. However, the reason why I like MacPorts more than Brew is a topic for another article.</p>
<p>&nbsp;</p>
<ul>
<li>Install MacPorts for Lion from the DMG disk image at (<a title="http://www.macports.org/install.php" href="http://www.macports.org/install.php" target="_blank">http://www.macports.org/install.php</a>)</li>
</ul>
<p>The MacPorts installer will modify your UNIX path setting in the .profile file in the base of your home directory. (This file is hidden from the finder&#8217;s default view, use the Terminal to see it) Rename .profile to .bash_profile, or if you already have a .bash_profile, edit this file to make sure that the Macports setup correctly installed the path statement:<code></code></p>
<p><code><br />
# MacPorts Installer addition...<br />
export PATH=/opt/local/bin:/opt/local/sbin:$PATH<br />
</code></p>
<ul>
<li>Configure Spotlight to exclude /opt/local from indexing<br />
system prefs -&gt; spotlight -&gt; privacy -&gt; add /opt/local</li>
</ul>
<p><strong>3. Python 2.7</strong></p>
<ul>
<li>open a new Terminal</li>
<li>sudo port selfupdate</li>
<li>sudo install python27</li>
<li>sudo port select &#8211;set python python27</li>
</ul>
<p>(ignore the errors about missing xcodebuild, since this is only needed if you&#8217;re going to be building OS X native apps with MacPorts. Consider installing Xcode if you think you might be doing this in the future.)</p>
<p><strong>4. Pip/Virtualenv</strong></p>
<ul>
<li>sudo easy_install pip</li>
<li>sudo pip install virtualenv virtualenvwrapper</li>
</ul>
<p><strong>The Advanced stuff:</strong></p>
<p>Now that you&#8217;ve installed some of the basics, let&#8217;s configure out UNIX environment for Virtualenv.</p>
<p><strong>5. Bash environment variables for Virtualenv</strong><br />
Edit the <code>.bash_profile</code> folder in your home directory. (whenever you see ~/, that&#8217;s an automatic bash shortcut to refer to the location of your home directory)</p>
<p><code>vim ~/.bash_profile</code><br />
Then add:</p>
<p><code>if [ -f ~/.bash_virtualenv ]; then<br />
source ~/.bash_virtualenv<br />
fi</code></p>
<p>This will first test to see if the file <code>.bash_virtualenv</code> exists, and if it does, it will &#8216;include&#8217; this file every time we open a new terminal.</p>
<p>Now create the <code>.bash_virtualenv</code> file:</p>
<p><code>vim ~/.bash_virtualenv</code></p>
<p>This will setup several Bash environment variables that will be read by pip, virtualenv, and the virtualenv wrapper script. Some of the important variables set here are the pip download cache, so that pip doesn&#8217;t re-download packages, and the WORKON_HOME. Feel free to change the PY, and the VIRTUALENV_PROJECT… folders. I like to store git repositories in my Dropbox folder, and then push/pull to them in order to sync my work between multiple computers.</p>
<p><code># for virtualenv<br />
if [ -f /usr/local/bin/virtualenvwrapper.sh ]; then<br />
PY=~/Documents/python/virtualenvs<br />
export WORKON_HOME=$PY<br />
export PIP_VIRTUALENV_BASE=$PY<br />
export PIP_RESPECT_VIRTUALENV=true<br />
export VIRTUALENVWRAPPER_VIRTUALENV_ARGS='--distribute'<br />
export PIP_DOWNLOAD_CACHE=$HOME/.pip_download_cache<br />
export VIRTUALENV_PROJECT_GIT_ROOT=${HOME}/Dropbox/research/python/git<br />
source /usr/local/bin/virtualenvwrapper.sh<br />
fi</code></p>
<p>To test this file, do:<br />
source ~/.bash_virtualenv</p>
<p>And you should see something like:<br />
<code>virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/initialize<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/premkvirtualenv<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/postmkvirtualenv<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/prermvirtualenv<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/postrmvirtualenv<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/predeactivate<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/postdeactivate<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/preactivate<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/postactivate<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/get_env_details<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/premkproject<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/postmkproject<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/prermproject<br />
virtualenvwrapper.user_scripts creating /Users/rterhaar/Documents/python/virtualenvs/postrmproject</code></p>
<p><strong>6. Edit those pre/post virtualenv wrapper hooks, add some magic</strong></p>
<p><code>mkdir -p ~/Documents/python/virtualenvs<br />
source ~/.bash_virtualenv (or if you get any error messages, just open a new terminal)<br />
cd ~/Documents/python/virtualenvs</code></p>
<p>The four files that you should edit are:</p>
<ul>
<li>postactivate</li>
<li>postdeactivate</li>
<li>postmkvirtualenv</li>
<li>premkvirtualenv</li>
</ul>
<p>First, postactivate</p>
<p><code><br />
# Global virtualenvwrapper postactivate, lives in $WORKON_HOME/postactivate<br />
# from http://hmarr.com/2010/jan/19/making-virtualenv-play-nice-with-git/</code><br />
PROJECT_DIR=&#8221;${WORKON_HOME}/$(basename $VIRTUAL_ENV)&#8221;<br />
if [ -d $PROJECT_DIR ]; then<br />
  # If we aren&#8217;t already within the project dir, cd into it<br />
  if [[ ! `pwd` == "$PROJECT_DIR*" ]]; then<br />
    export PRE_VENV_ACTIVATE_DIR=`pwd`<br />
    cd &#8220;$PROJECT_DIR&#8221;<br />
  fi<br />
fi<br />
unset PROJECT_DIR</p>
<p>Now edit postdeactivate:</p>
<p><code>if [ $PRE_VENV_ACTIVATE_DIR ]; then<br />
cd $PRE_VENV_ACTIVATE_DIR<br />
unset PRE_VENV_ACTIVATE_DIR<br />
fi</code></p>
<p>Then edit premkvirtualenv:</p>
<p><code><br />
source ~/.bash_virtualenv</code></p>
<p>if [ -d $VIRTUALENV_PROJECT_GIT_ROOT ]; then</p>
<p>if [ -d ${VIRTUALENV_PROJECT_GIT_ROOT}/${1}.git ]; then<br />
echo &#8220;Git root already created&#8221;<br />
else<br />
echo &#8220;Creating git root&#8221;<br />
cd $VIRTUALENV_PROJECT_GIT_ROOT<br />
git init &#8211;bare ${1}.git<br />
fi</p>
<p>cd ${WORKON_HOME}/${1}<br />
git init<br />
git remote add origin file://${VIRTUALENV_PROJECT_GIT_ROOT}/${1}.git<br />
git config branch.master.remote origin<br />
git config branch.master.merge refs/heads/master<br />
git pull</p>
<p>if [ -f .gitignore ]; then<br />
echo &#8220;.gitignore already exists, skipping&#8221;<br />
else<br />
echo &#8220;bin/*<br />
include/*<br />
share/*<br />
lib/*<br />
man/*<br />
.Python<br />
.*.swp<br />
*.py[co]&#8221; &gt; .gitignore<br />
git add .gitignore<br />
git commit .gitignore -m &#8220;init&#8221;<br />
git push origin master<br />
fi<br />
fi</p>
<p>Now finally postmkvirtualenv:</p>
<p>if [ -f requirements.txt ]; then<br />
echo &#8220;requirements.txt already exists, skipping&#8221;<br />
else<br />
pip freeze &gt; requirements.txt<br />
git add requirements.txt<br />
git commit requirements.txt -m &#8220;adding basic pip reqs file&#8221;<br />
git push origin master<br />
fi</p>
<p>After adding these pre/post hooks to these files, you will have a really powerful and easy to use Virtualenv system. Here&#8217;s some tips for working with your new virtualenv system:</p>
<p>To start a new project, make a new virtualenv using:<br />
<code>mkvirtualenv my_project</code></p>
<p>This will create several folders, and &#8220;activate&#8221; your terminal session for the new virtualenv directory. When you&#8217;re done working, close the terminal or type &#8220;<code>deactivate</code>&#8221;</p>
<p>To continue working on an existing virtualenv:</p>
<p><code>workon my_project</code><br />
(Tab completion works, so if you type &#8216;workon&#8217; then hit the tab key twice, you&#8217;ll get a list of existing projects)</p>
<p>Once you&#8217;ve activated a virtualenv, install software inside this virtualenv by typing:</p>
<p><code>(my_project)users-Mac:~ user$ pip install ipython</code><br />
(notice! no sudo. We are using a special version of pip that will install ipython into the virtualenv, and not to your OS.)</p>
<p>That&#8217;s it! Hope you enjoy using Virtualenv to manage your Python projects. Please leave a comment if you have any problems, or suggestions.</p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/guide-to-using-virtualenv-and-python/feed/</wfw:commentRss>
<slash:comments>2</slash:comments>
</item>
<item>
<title>You should be using cloud-init</title>
<link>http://www.atlanticdynamic.com/you-should-be-using-cloud-init/</link>
<comments>http://www.atlanticdynamic.com/you-should-be-using-cloud-init/#comments</comments>
<pubDate>Tue, 07 Jun 2011 03:10:51 +0000</pubDate>
<dc:creator>Rob Terhaar</dc:creator>
<category>
<![CDATA[Uncategorized]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=354</guid>
<description>
<![CDATA[cloud-init is a feature of the Ubuntu Server EC2 images that implements a standard way of reading per-instance meta-data from the Amazon API and provisioning/bootstraping systems. The Problem When you create an Amazon EC2 instance, you are allowed to throw a small amount of data (64k ?) into instance metadata. This metadata can then be [...]]]>
</description>
<content:encoded>
<![CDATA[<p>cloud-init is a feature of the Ubuntu Server EC2 images that implements a standard way of reading per-instance meta-data from the Amazon API and provisioning/bootstraping systems.<br />
<span id="more-354"></span></p>
<p><strong>The Problem</strong><br />
When you create an Amazon EC2 instance, you are allowed to throw a small amount of data (64k ?) into instance metadata. This metadata can then be read back by the instance by querying a special URL. This feature has been used for server-classification and configuration of systems.</p>
<p>The problem is that everyone was using this metadata space in a different way. Some people were just throwing a single trigger word like &#8220;database&#8221; into this metadata space, and some people were storing large procedural configuration scripts that would be downloaded and executed by the instance. There has been much fragmentation onto how to use this metadata space for server configuration.</p>
<p><strong>Cloud-init as a solution</strong><br />
Let&#8217;s say that you want an Ubuntu machine to boot up, upgrade all available packages, install Puppet, then check-in to your PuppetMaster:<br />
<code><br />
#cloud-config<br />
apt_upgrade: true<br />
packages:<br />
 - puppet<br />
puppet:<br />
    conf:<br />
        agent:<br />
     server: "puppetmaster.example.org"<br />
</code></p>
<p>I look forward to software like cloud-init becoming common and universally supported by more cloud providers. The concept is simple, easy to work with, and powerful. </p>
<p>Read more about cloud-init at the <a href="https://help.ubuntu.com/community/CloudInit">Ubuntu Docs Page for cloudinit</a></p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/you-should-be-using-cloud-init/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Cloud Management Layers, or Don&#8217;t Use Templates!</title>
<link>http://www.atlanticdynamic.com/cloud-management-layers-or-dont-use-templates/</link>
<comments>http://www.atlanticdynamic.com/cloud-management-layers-or-dont-use-templates/#comments</comments>
<pubDate>Thu, 07 Apr 2011 15:34:31 +0000</pubDate>
<dc:creator>Rob Terhaar</dc:creator>
<category>
<![CDATA[Cloud]]>
</category>
<category>
<![CDATA[Puppet]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=339</guid>
<description>
<![CDATA[I was recently talking to a client (let&#8217;s call him Carl&#8230;) who had just begun the initial research phase into how he was going to redesign his server management infrastructure. Carl, like many people, had been using a template-based workflow, but was tired of the inherit difficulties and problems in managing non-congruent systems created from [...]]]>
</description>
<content:encoded>
<![CDATA[<p>I was recently talking to a client (let&#8217;s call him Carl&#8230;) who had just begun the initial research phase into how he was going to redesign his server management infrastructure. Carl, like many people, had been using a template-based workflow, but was tired of the inherit difficulties and problems in managing non-congruent systems created from templates.</p>
<h2>The Evil Template-Based Workflow Example</h2>
<ol>
<li>Configure your base system, install some good software</li>
<li>Take a Snapshot (somehow&#8230; re-bundle an AMI? Hit the snapshot button in VMWare?)</li>
<li>Shutdown your base system</li>
<li>Spin up instances based on this snapshot</li>
<li>Attempt to manage the chaos as configurations drift</li>
<li>Spin up your base system, apply various updates, and take a new snapshot</li>
<li>Spin up new instances based on new snapshot</li>
<li>Chaos!!</li>
</ol>
<p>You can see how without a dynamic configuration management system, the template-based workflow is impossible to manage. Outdated templates and manual system configuration result in complete infrastructure chaos.</p>
<h2>Configuration Management Systems (use them!)</h2>
<p>Carl realized that the smarter alternative to the template-based workflow is to use a configuration management system, but there&#8217;s so many options! Carl wasn&#8217;t sure which one to use, how to begin using any of them, or how all of the pieces fit together. Carl told me that one of the most confusing things in his research was to understand where the responsibilities of the various management system begin and end.</p>
<h2>A Nebulous Onion</h2>
<p>I drew the following diagram for Carl to help him understand how all of the current tools available fit together into a bigger picture of Cloud Management. This workflow example is bias to Cloud Providers with advanced APIs, and Linux/UNIX operating systems- but why would you ever use anything else?</p>
<ol>
<li><a href="http://www.atlanticdynamic.com/wp-content/uploads/2011/04/Cloud-Layers.png"><img class="alignright size-full wp-image-340" title="Cloud Layers" src="http://www.atlanticdynamic.com/wp-content/uploads/2011/04/Cloud-Layers.png" alt="" width="529" height="504" /></a><strong>Creation of Servers:</strong> Some event occurs, and servers are created. Maybe this is an auto-scaling request from your load balancer, or maybe John in Marketing says that your website is going to be mentioned on Oprah later this afternoon. (woo!)</li>
<li><strong>Servers are created programmatically:</strong> A bit of configuration metadata is stored somewhere in an API that will be referenced in step 3. e.g., these 10 new <strong>LARGE</strong> servers should be <strong>WEB</strong> servers in the <strong>PRODUCTION</strong> cluster.</li>
<li><strong>The OS boots:</strong> The instances boot, and cloud_init (or some custom script you spent all afternoon writing) reads the metadata that you stored back in step 2, and basic configuration begins. Puppet is installed, and your new instances prepare for their first connection to your Puppet master for configuration.</li>
<li><strong>Your Systems are 100% Configured</strong>: A good configuration management system will leave your systems in a fully-configured state. No manual intervention should be required.</li>
<li><strong>Connection to External Data:</strong> This could be the topic of a larger blog post, but the final step in configuration is to connect your instances to external data sources. This could mean mounting an NFS share, connecting an EBS volume, or joining a Gluster or Casandra ring. This is really upto your imagination, and your application&#8217;s needs.</li>
</ol>
<p>&nbsp;</p>
<h2>Summary:</h2>
<p>There are many tools for <em>Wrangling the Cloud</em>, and I&#8217;ve only described one example workflow from a very abstract level. There is no one-size-fits-all solution, however that doesn&#8217;t mean that you should reinvent the wheel. We&#8217;ve built a lot of systems like this for our clients, contact us for help with yours.</p>
<p>&nbsp;</p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/cloud-management-layers-or-dont-use-templates/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Postgres 8.4 is Broken in Debian Squeeze</title>
<link>http://www.atlanticdynamic.com/postgres-8-4-is-broken-in-debian-squeeze/</link>
<comments>http://www.atlanticdynamic.com/postgres-8-4-is-broken-in-debian-squeeze/#comments</comments>
<pubDate>Tue, 15 Mar 2011 02:20:11 +0000</pubDate>
<dc:creator>Rob Terhaar</dc:creator>
<category>
<![CDATA[Linux]]>
</category>
<category>
<![CDATA[Debian]]>
</category>
<category>
<![CDATA[Postgres]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=326</guid>
<description>
<![CDATA[Debian shipped an unstable, crippled version of Postgres 8.4 in the Winter 2010/2011 release of 6.0 (aka Squeeze.) Postgres contributor, Peter Eisentraut confirms this on his blog. Read more about it here. So how do you fix this? Luckily, Debian has packaged a new version of Postgres that will use the libreadline6 library if it [...]]]>
</description>
<content:encoded>
<![CDATA[<p>Debian shipped an unstable, crippled version of Postgres 8.4 in the Winter 2010/2011 release of 6.0 (aka Squeeze.) Postgres contributor, Peter Eisentraut confirms this on <a href="http://petereisentraut.blogspot.com/2011/02/squeeze-postgresql-broken.html">his blog</a>. Read more about it <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=608442">here</a>. So how do you fix this? </p>
<p>Luckily, Debian has packaged a new version of Postgres that will use the libreadline6 library if it has been installed instead of the inferior (but more open-licensed) libedit.  Unfortunately, the new Postgres package is only currently available in <a href="http://backports.debian.org/">Debian Backports</a> so you&#8217;ll have to enable the backports repo first.</p>
<p>Once you&#8217;ve installed Postgres8.4 > r114 from backports, all you have to do is install readline:<br />
<code>sudo apt-get update &#038;&#038; sudo apt-get install libreadline6</code> </p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/postgres-8-4-is-broken-in-debian-squeeze/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Solaris 11 Swap File Location</title>
<link>http://www.atlanticdynamic.com/solaris-11-swap-file-location/</link>
<comments>http://www.atlanticdynamic.com/solaris-11-swap-file-location/#comments</comments>
<pubDate>Wed, 23 Feb 2011 23:48:35 +0000</pubDate>
<dc:creator>Rob Terhaar</dc:creator>
<category>
<![CDATA[Solaris]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=318</guid>
<description>
<![CDATA[Because of ZFS, working with Swap files in Solaris is surprisingly easy. On our development server, the OS is running on a single SSD device, and there is a large array of standard SATA disks attached to the AHCI controller. Although this system has plenty of RAM, swap space is important so we avoid OOM [...]]]>
</description>
<content:encoded>
<![CDATA[<p>Because of ZFS, working with Swap files in Solaris is surprisingly easy. On our development server, the OS is running on a single SSD device, and there is a large array of standard SATA disks attached to the AHCI controller. Although this system has plenty of RAM, swap space is important so we avoid <a href="http://developers.sun.com/solaris/articles/subprocess/subprocess.html#overcom">OOM</a> (out-of-memory) errors.</p>
<p>In order to move the swap file from the OS drive to the data drive:<br />
<code><br />
zfs create -V 4G tank/swap<br />
zfs set dedup=off tank/swap<br />
swap -a /dev/zvol/dsk/tank/swap<br />
swap -d /dev/zvol/dsk/rpool/swap<br />
</code></p>
<p>And then to make this change persistent across reboots, also edit the swap path in your /etc/vfstab.<br />
<code><br />
/dev/zvol/dsk/tank/swap -               -               swap    -       no      -<br />
</code></p>
<p><span id="more-318"></span>Using a shared swap device is fine for development and small office servers, but you should consider using dedicated and mirrored swap if this server will be under any serious load.</p>
<p>First find two physical disks for your new mirrored swap<br />
<code><br />
root@gyro:~# format<br />
Searching for disks...done</p>
<p>AVAILABLE DISK SELECTIONS:<br />
0. c7t0d0<br />
/pci@0,0/pci8086,3472@1f,2/disk@0,0<br />
1. c7t1d0<br />
/pci@0,0/pci8086,3472@1f,2/disk@1,0<br />
2. c7t2d0<br />
/pci@0,0/pci8086,3472@1f,2/disk@2,0<br />
3. c7t3d0<br />
/pci@0,0/pci8086,3472@1f,2/disk@3,0<br />
4. c9t0d0<br />
/pci@0,0/pci8086,25f7@2/pci8086,350c@0,3/pci11ab,11ab@2/disk@0,0<br />
5. c9t1d0<br />
/pci@0,0/pci8086,25f7@2/pci8086,350c@0,3/pci11ab,11ab@2/disk@1,0<br />
6. c9t2d0<br />
/pci@0,0/pci8086,25f7@2/pci8086,350c@0,3/pci11ab,11ab@2/disk@2,0<br />
7. c9t3d0<br />
/pci@0,0/pci8086,25f7@2/pci8086,350c@0,3/pci11ab,11ab@2/disk@3,0<br />
</code></p>
<p>Let&#8217;s pick the last two drives for our example<br />
<code><br />
zpool create SWAP_ZPOOL mirror c9t2d0 c9t3d0<br />
zfs set mountpoint=legacy SWAP_ZPOOL<br />
</code><br />
Setting mountpoint=legacy will keep Solaris from mounting this drive automatically upon import. From here, follow the steps above to add this device to configure this device as swap and add to vfstab.</p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/solaris-11-swap-file-location/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Using Puppet instead of Bash</title>
<link>http://www.atlanticdynamic.com/puppet-instead-of-bash/</link>
<comments>http://www.atlanticdynamic.com/puppet-instead-of-bash/#comments</comments>
<pubDate>Sun, 30 Jan 2011 01:52:16 +0000</pubDate>
<dc:creator>Rob Terhaar</dc:creator>
<category>
<![CDATA[Code]]>
</category>
<category>
<![CDATA[Linux]]>
</category>
<category>
<![CDATA[Puppet]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=304</guid>
<description>
<![CDATA[If you&#8217;ve done any amount of heavy UNIX systems administration work, you&#8217;ve undoubtedly written several big ugly Bash scripts. #!/bin/bash for i in `more standard_package_list.txt ` do apt-get install $i done This simple code example will read a txt file with a list of required packages, and then install all packages. So how can Puppet [...]]]>
</description>
<content:encoded>
<![CDATA[<p>If you&#8217;ve done any amount of heavy UNIX systems administration work, you&#8217;ve undoubtedly written several big ugly Bash scripts.<br />
<code><br />
#!/bin/bash<br />
for i in `more standard_package_list.txt `<br />
  do<br />
    apt-get install $i<br />
done<br />
</code><br />
This simple code example will read a txt file with a list of required packages, and then install all packages.</p>
<p>So how can Puppet help us with this task?<br />
<code><br />
#!/usr/bin/puppet</p>
<p>$package_list = ['apache2','php5','screen']</p>
<p>package{$package_list:<br />
      ensure    => 'latest',<br />
      provider  => 'apt',<br />
}<br />
</code><br />
Then make sure to chown this file:<br />
<code><br />
$ chmod +x packages.pp<br />
$ ./packages.pp<br />
</code><br />
Now, when you run this file, Puppet will use the built in &#8216;apt&#8217; package provider to install the list of packages defined at the top of the file.</p>
<p>It&#8217;s actually much easier to write a complex script using a high-level language such as Puppet, rather than Bash, despite this example that requires more code to accomplish the same task using Puppet than Bash.</p>
<p>Using Puppet instead of Bash for basic system scripting gives you many advantages such as better debugging, better error handling, standard formatting, better readability, and is generally much easier to perform complicated tasks than Bash or perl. </p>
<p>It also is a great introduction if you&#8217;re just getting your feet wet in the Puppet world. Good luck, and check back soon for more Puppet tutorials. </p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/puppet-instead-of-bash/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>SSL/TLS Insecure Renegotiation and Payment Processors</title>
<link>http://www.atlanticdynamic.com/ssltls-insecure-renegotiation-and-payment-processors/</link>
<comments>http://www.atlanticdynamic.com/ssltls-insecure-renegotiation-and-payment-processors/#comments</comments>
<pubDate>Fri, 21 Jan 2011 16:45:44 +0000</pubDate>
<dc:creator>Rob Terhaar</dc:creator>
<category>
<![CDATA[Java]]>
</category>
<category>
<![CDATA[SSL]]>
</category>
<category>
<![CDATA[Tomcat]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=277</guid>
<description>
<![CDATA[This week, we ran into an issue with a client&#8217;s Java/Tomcat application that connects to FirstData&#8217;s WSDL API for Credit Card payment processing. The problem was related to the recently discovered SSL renegotiation protocol flaw. (read more about the protocol flaw over at Slashdot) Problem symptoms included Tomcat freezing while initializing, then after 10mns timing [...]]]>
</description>
<content:encoded>
<![CDATA[<p>This week, we ran into an issue with a client&#8217;s Java/Tomcat application that connects to FirstData&#8217;s WSDL API for Credit Card payment processing. The problem was related to the recently discovered SSL renegotiation protocol flaw. (read more about the protocol flaw over at <a href="http://it.slashdot.org/story/09/11/16/2327230/SSL-Renegotiation-Attack-Becomes-Real">Slashdot</a>)</p>
<p>Problem symptoms included Tomcat freezing while initializing, then after 10mns timing out with error messages saying that it was unable to contact the WSDL URL. Before we could connect to that URL, we had to tell Java&#8217;s SSL Libraries to allow unsafe renegotiation. </p>
<p>How to fix this:</p>
<p>Short Answer:<br />
In /etc/default/tomcat6 (Debian/Ubuntu), add a new line to your &#8216;CATALINA_OPTS=&#8217; section.<br />
<code><br />
-Dsun.security.ssl.allowUnsafeRenegotiation=true<br />
</code></p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/ssltls-insecure-renegotiation-and-payment-processors/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
<item>
<title>Optimizing OS X for SSD</title>
<link>http://www.atlanticdynamic.com/optimizing-os-x-for-ssd/</link>
<comments>http://www.atlanticdynamic.com/optimizing-os-x-for-ssd/#comments</comments>
<pubDate>Mon, 18 Oct 2010 02:24:51 +0000</pubDate>
<dc:creator>Rob Terhaar</dc:creator>
<category>
<![CDATA[Fix]]>
</category>
<category>
<![CDATA[Apple]]>
</category>
<category>
<![CDATA[SSD]]>
</category>
<category>
<![CDATA[UNIX]]>
</category>
<guid isPermaLink="false">http://www.atlanticdynamic.com/?p=199</guid>
<description>
<![CDATA[A few minor changes can be made to OS X 10.6 in order to maximize performance with solid state disks (SSD.) The settings changes recommended in this post start out from very simple to implement and progressively become more complicated. Read on to find out more!]]>
</description>
<content:encoded>
<![CDATA[<p>These changes are not officially endorsed or supported by Apple,  however are widely considered safe and sane.</p>
<p><strong>noatime</strong><br />
A very typical UNIX/Linux tweak is to turn off &#8216;atime&#8217; on your system drive. As part of the POSIX, your OS must write &#8216;last accessed&#8217; time to each time upon read. On SSD disks, the default &#8216;atime&#8217; feature can cause pauses and high latency due to excessive small writes. Turning off &#8216;atime&#8217; may affect HD clean-up tools that check for infrequently accessed files, and may also affect a few UNIX applications, such as older versions of Mutt.</p>
<p>In UNIX and Linux, the noatime setting is easily configured via /etc/fstab, but in OS X, a launchd file must be configured. The idea and implementation for this is from: http://blogs.nullvision.com/?p=275</p>
<p>Open your terminal (/Applications/Utilities/Terminal) and type:</p>
<blockquote><p>sudo nano /Library/LaunchDaemons/com.nullvision.noatime.plist</p></blockquote>
<p>And inside that new file, paste the following:</p>
<blockquote>
<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
        "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
    &lt;dict&gt;
        &lt;key&gt;Label&lt;/key&gt;
        &lt;string&gt;com.nullvision.noatime&lt;/string&gt;
        &lt;key&gt;ProgramArguments&lt;/key&gt;
        &lt;array&gt;
            &lt;string&gt;mount&lt;/string&gt;
            &lt;string&gt;-vuwo&lt;/string&gt;
            &lt;string&gt;noatime&lt;/string&gt;
            &lt;string&gt;/&lt;/string&gt;
        &lt;/array&gt;
        &lt;key&gt;RunAtLoad&lt;/key&gt;
        &lt;true/&gt;
    &lt;/dict&gt;
&lt;/plist&gt;</code></pre>
</blockquote>
<p>Hold CTRL and hit X to exit, make sure to save when asked. Then reboot your computer, and open the terminal again. We will now confirm that your system has &#8216;noatime&#8217; enabled.</p>
<blockquote><p>mount | grep &#8221; / &#8220;</p></blockquote>
<p>You should see something simular to:</p>
<blockquote><p>/dev/disk0s2 on / (hfs, local, journaled, noatime)</p></blockquote>
<p>Success! your operating system drive has been mounted with &#8216;noatime&#8217;.</p>
<p><strong>Move your Swap</strong><br />
If you have a system with both an SSD as well as a standard magnetic HD, you may consider moving your swap file off the SSD and onto the HD. There are various arguments for making this change- by moving your swap to the slower/larger storage device, paging operations to disk will obviously be much slower, however if your system has ample RAM, the swap file should be mostly untouched anyhow. Your upgrade priorities should be reevaluated if you have an SSD in a system that has less than 4GB of RAM.</p>
<p>To move your swap to a new location, we will modify a built-in system launchd file, and create a wrapper script. Editing base files installed by the OS is scary, and dangerous, so make sure you have a backup before attempting this step. This step also requires that the Xcode developer tools have been installed, since the plist editor is not included in the base OS X install. (implementation modified from http://hintsforums.macworld.com/showthread.php?p=452409 )</p>
<p>First, we&#8217;re going to create the wrapper script:</p>
<blockquote><p>mkdir -p /opt/local/bin/<br />
sudo nano /opt/local/bin/dynamic_pager_init.sh</p></blockquote>
<p>And now inside that file:</p>
<blockquote><p>#!/bin/bash<br />
#launch Apple&#8217;s dynamic_pager only when the swap volume is mounted</p>
<p>MOUNTPOINT=$1</p>
<p>#check to see if swap storage has been mounted yet<br />
/sbin/mount | /usr/bin/grep -q $MOUNTPOINT</p>
<p>#if $MOUNTPOINT is mounted, then create swap file, otherwise exit1<br />
if [ $? -ne 0 ];then<br />
  echo &#8220;Swap storage not mounted yet, waiting&#8221;;<br />
  exit 1<br />
else<br />
  echo &#8220;Launching dynamic pager on volume Swap&#8221;;<br />
  /bin/mkdir -p $MOUNTPOINT/.vm<br />
  /sbin/dynamic_pager -F $MOUNTPOINT/.vm/swapfile;<br />
fi
</p></blockquote>
<p>Hit CTRL-X and save the file, and then set execute permissions on the file:</p>
<blockquote><p>sudo chmod +x /opt/local/bin/dynamic_pager_init.sh</p></blockquote>
<p>Now that the wrapper script is in place, we&#8217;re going to tell the launchd config to use this script to create the swap file at boot. Launchd will continually rerun the script until your selected swap volume is mounted, and dynamic_pager runs successfully.</p>
<p>Open your terminal, (/Applications/Utilities/Terminal) and type in:</p>
<blockquote><p>sudo open /Developer/Applications/Utilities/Property\ List\ Editor.app /System/Library/LaunchDaemons/com.apple.dynamic_pager.plist</p></blockquote>
<p>You should see the following plist settings:<br />
<a href="http://www.atlanticdynamic.com/wp-content/uploads/2010/10/pager_default.png"><img src="http://www.atlanticdynamic.com/wp-content/uploads/2010/10/pager_default.png" alt="" title="pager_default" width="669" height="392" class="alignnone size-full wp-image-209" /></a></p>
<p>In order to use the wrapper script instead of calling the dynamic_pager_init binary directly, make your plist look like this:</p>
<p><a href="http://www.atlanticdynamic.com/wp-content/uploads/2010/10/pager_updated.png"><img src="http://www.atlanticdynamic.com/wp-content/uploads/2010/10/pager_updated.png" alt="" title="pager_updated" width="653" height="378" class="alignnone size-full wp-image-208" /></a></p>
<p>Make sure to change the value at &#8220;item 1&#8243; to the name of your mounted HD. The HD on my system is mounted at &#8220;/Volumes/Data&#8221;. In order to find out the name of yours, check in the OS X &#8220;Disk Utility&#8221; or from the Terminal, type in &#8220;mount&#8221; and find the name of your HD in the list. </p>
<p>I then had to save this file to my desktop, and then copy the file in place via:</p>
<blockquote><p>sudo cp ~/Desktop/com.apple.dynamic_pager.plist /System/Library/LaunchDaemons/</p></blockquote>
<p> Now reboot, and test to make sure your swap has been successfully relocated by typing:</p>
]]>
</content:encoded>
<wfw:commentRss>http://www.atlanticdynamic.com/optimizing-os-x-for-ssd/feed/</wfw:commentRss>
<slash:comments>0</slash:comments>
</item>
</channel>
</rss>
<!-- Served from: _ @ 2013-05-23 00:48:54 by W3 Total Cache -->