<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title></title>
  <subtitle></subtitle>
  <id>https://www.endpointdev.com/blog/tags/environment/</id>
  <link href="https://www.endpointdev.com/blog/tags/environment/"/>
  <link href="https://www.endpointdev.com/blog/tags/environment/" rel="self"/>
  <updated>2018-12-20T00:00:00+00:00</updated>
  <author>
    <name>End Point Dev</name>
  </author>
  
    <entry>
      <title>Data Center Relocation Initiatives: Daunting But Achievable</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/12/data_center_relocation_initiatives_daunting_but_achievable/"/>
      <id>https://www.endpointdev.com/blog/2018/12/data_center_relocation_initiatives_daunting_but_achievable/</id>
      <published>2018-12-20T00:00:00+00:00</published>
      <author>
        <name>Charles Chang</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2018/12/data_center_relocation_initiatives_daunting_but_achievable/banner.jpg&#34; alt=&#34;Datacenter room&#34;&gt;
&lt;a href=&#34;https://www.flickr.com/photos/seeweb/9771315606/&#34;&gt;Photo by Seeweb · CC BY-SA 2.0, cropped&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;introduction&#34;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;A customer asked for our help dealing with logistical nightmares they encountered during a hardware update and data center relocation project. The customer had two active data centers, and wanted to relocate one of them to a modern Tier 4 facility to improve its performance and provide redundancy for critical systems. They also wanted to consolidate or decommission equipment to reduce recurring expenses and reduce their carbon footprint. The client decided to move to a Tier 4 data center because they provide across-​the-​board redundancy within the data center.&lt;/p&gt;
&lt;h3 id=&#34;moving-forward-with-tier-iv&#34;&gt;Moving forward with Tier IV&lt;/h3&gt;
&lt;p&gt;
&lt;img align=&#34;right&#34; src=&#34;/blog/2018/12/data_center_relocation_initiatives_daunting_but_achievable/data-center-1.jpg&#34; style=&#34;margin: 1em&#34; width=&#34;200&#34;&gt;
Enterprises typically transition to Tier 4 data centers because they offer the highest uptime guarantees, and have no single points of failure. These facilities are fully redundant in terms of electrical circuits, cooling, and networking. This architecture is best able to withstand even the most serious technical incidents without server availability being affected. Tier IV facilities have contracts with disaster management companies who will provide them, for example, with fuel in the event that a natural disaster damages the power grid.
&lt;/p&gt;
&lt;p&gt;(More information about the four data center levels is at the end of this post.)&lt;/p&gt;
&lt;h3 id=&#34;key-issues&#34;&gt;Key Issues&lt;/h3&gt;
&lt;p&gt;Some of the customer’s key concerns were:&lt;/p&gt;
&lt;p&gt;1. To safely move their virtual environment to the new data center.&lt;/p&gt;
&lt;p&gt;2. To protect assets during the relocation.&lt;/p&gt;
&lt;p&gt;3. To completely shut down the current data center and migrate seamlessly to the new data center.&lt;/p&gt;
&lt;p&gt;4. To update external DNS records without causing any downtime for the web applications used by their customers.&lt;/p&gt;
&lt;h3 id=&#34;project-planning&#34;&gt;Project Planning&lt;/h3&gt;
&lt;p&gt;To manage data center relocations is challenging because there are many moving parts and variables. Typically, planning starts 6 months ahead of the scheduled relocation date. We seek to understand the role of each system by consulting in-depth with all the teams involved. We analyze each part of the client’s tech infrastructure, break it down, and strategize about the best approach for handling the migration of each component. Additional time to plan can help especially when a large group of stakeholders is involved. Successful planning requires hard and sometimes extensive work, but makes an otherwise overwhelming data center migration smooth and worry free.&lt;/p&gt;
&lt;p&gt;Here are some of our procedures for pre-​migration preparation:&lt;/p&gt;
&lt;p&gt;1. Process the paperwork for new hardware. Identify, review, and approve all applications. Hire movers. Schedule and coordinate with internal management and key stakeholders like IT staff, system admins, contractors, circuit providers, etc.&lt;img align=&#34;right&#34; src=&#34;/blog/2018/12/data_center_relocation_initiatives_daunting_but_achievable/data-center-2.jpg&#34; style=&#34;margin: 1em&#34; width=&#34;200&#34;/&gt;&lt;/p&gt;
&lt;p&gt;2. Collect and analyze resource usage associated with the critical and non-critical systems and compare resource needs to resource availability at the new facility.&lt;/p&gt;
&lt;p&gt;3. Design and schedule the migration of critical systems to the new data center. Discuss the plan with key stakeholders.&lt;/p&gt;
&lt;p&gt;4. Make sure replicas of critical systems are up to date.&lt;/p&gt;
&lt;p&gt;5. Set up a new environment with new hardware in the new data center and establish network connections.&lt;/p&gt;
&lt;p&gt;6. Prepare hardware and virtualization technology in the new data center.&lt;/p&gt;
&lt;p&gt;7. Test, retest, and burn in the new hardware (2–4 weeks of testing).&lt;/p&gt;
&lt;p&gt;8. Create a non-​essential server within the virtualization environment and test it.&lt;/p&gt;
&lt;h3 id=&#34;a-challenge-eliminating-downtime&#34;&gt;A Challenge: Eliminating Downtime&lt;/h3&gt;
&lt;img align=&#34;right&#34; src=&#34;/blog/2018/12/data_center_relocation_initiatives_daunting_but_achievable/data-center-3.jpg&#34; style=&#34;margin: 1em&#34; width=&#34;200&#34;/&gt;
&lt;p&gt;To minimize or eliminate downtime requires very careful preparation. With this particular client, we had the luxury of their already having a secondary data center, which could accommodate a majority of the critical systems during the migration.&lt;/p&gt;
&lt;p&gt;We originally planned to leverage this by simply changing the external DNS records to point to this data center during the migration, but during planning determined that the external DNS record would not replicate worldwide quickly enough to meet the uptime needs of their global operation.&lt;/p&gt;
&lt;h3 id=&#34;solutions&#34;&gt;Solutions&lt;/h3&gt;
&lt;p&gt;After discussing various approaches, we ended up using a load balancer. A load balancer is a network device that routes incoming traffic destined for a single destination (web site, application, or service) and ‘shares’ the incoming connections across multiple destination devices or services. In this case, the data center we were to migrate to housed the client’s critical systems like web servers, database, etc. The secondary data center housed a replica of the critical systems using a replication technology, e.g. Actifio, Rubrik, SAN mirroring, VMWare SRM, or Zerto — we used Actifio in this scenario.
&lt;img align=&#34;right&#34; src=&#34;/blog/2018/12/data_center_relocation_initiatives_daunting_but_achievable/data-center-4.jpg&#34; style=&#34;margin: 1em&#34; width=&#34;200&#34;/&gt;&lt;/p&gt;
&lt;p&gt;The customer had multiple systems with external DNS records and public IP addresses. We did not change the public DNS names for the critical systems. We did change the public IP addresses associated with the public DNS names, to point to the load balancer, which then pointed to the appropriate data center throughout the process. This setup enabled a gradual, flexible, and fully controlled transition to the new data center.&lt;/p&gt;
&lt;h3 id=&#34;summary&#34;&gt;Summary&lt;/h3&gt;
&lt;img align=&#34;right&#34; src=&#34;/blog/2018/12/data_center_relocation_initiatives_daunting_but_achievable/data-center-5.jpg&#34; style=&#34;margin: 1em&#34; width=&#34;200&#34;/&gt;
&lt;p&gt;Our client wanted to reduce their servers’ power usage 40% by consolidating into a hyper-​converged system. Other goals were to reduce floor space by 50%, and monthly recurring data center charges by 50%. We transitioned them to a new hardware stack (compute, storage, network, backup environment) in a Tier 4 data center, and saved them 50% percent on data center operation costs. Additionally, during the process we corrected issues associated with disaster recovery and business continuity, leaving the client’s operations more resilient, affordable, and more secure.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;appendix-data-center-classifications&#34;&gt;Appendix: Data Center Classifications&lt;/h3&gt;
&lt;h4 id=&#34;tier-iv-best&#34;&gt;Tier IV (Best)&lt;/h4&gt;
&lt;p&gt;Tier IV data centers have redundancies for every process and data protection stream. No single outage or error can shut down the system. To keep Tier IV ranking, data centers must have 99.995% minimum uptime per year. They come equipped with 2N+1 infrastructure (two times the amount required for operation plus a backup), which is considered “fully redundant.”&lt;/p&gt;
&lt;h4 id=&#34;tier-iii-average&#34;&gt;Tier III (Average)&lt;/h4&gt;
&lt;p&gt;N+1 (the amount required for operation plus a backup) fault tolerance, which means a Tier III facility can undergo routine maintenance without a hiccup in operations. 99.982% minimum uptime per annum, used for maintenance and overwhelming emergencies.&lt;/p&gt;
&lt;h4 id=&#34;tier-ii-minimal&#34;&gt;Tier II (Minimal)&lt;/h4&gt;
&lt;p&gt;99.749% minimum uptime. Tier II facilities have considerably more downtime than Tier III facilities, primarily because Tier II facilities have less redundancy. They do however have partial cooling redundancy and multiple power redundancies.&lt;/p&gt;
&lt;h4 id=&#34;tier-i-basic-cheapest&#34;&gt;Tier I (Basic, Cheapest)&lt;/h4&gt;
&lt;p&gt;99.671% minimum uptime, with 28.8 hours of downtime each year.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Shell Command Outputs Truncated in Python</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2018/04/shell-command-outputs-truncated-in-python/"/>
      <id>https://www.endpointdev.com/blog/2018/04/shell-command-outputs-truncated-in-python/</id>
      <published>2018-04-05T00:00:00+00:00</published>
      <author>
        <name>Selvakumar Arumugam</name>
      </author>
      <content type="html">
        &lt;p&gt;&lt;img src=&#34;/blog/2018/04/shell-command-outputs-truncated-in-python/programmers-reviewing-code-on-computer_925x.jpg&#34; alt=&#34;Two guys working at computers&#34; /&gt;&lt;br /&gt;
&lt;small&gt;&lt;a href=&#34;https://burst.shopify.com/photos/programmers-reviewing-code-on-computer&#34;&gt;Photo by Sarah Pflug of Burst&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Recently I was working on a Python script to do some parsing and processing on the output of shell commands in Ubuntu. The output that showed up was truncated.&lt;/p&gt;
&lt;p&gt;The below sections will walk through the debugging process to identify the root cause and implement a solution with detailed explanation, using Python 2.&lt;/p&gt;
&lt;h3 id=&#34;problem&#34;&gt;Problem&lt;/h3&gt;
&lt;p&gt;The following code block shows the output of a shell command which lists the installed packages, name and version, in Ubuntu.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# dpkg -l | grep ^ii | awk &amp;#39;{print $2 &amp;#34;    &amp;#34; $3}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;accountsservice    0.6.35-0ubuntu7.3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;acl    2.2.52-1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;adduser    3.113+nmu3ubuntu3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ant    1.9.3-2build1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ant-optional    1.9.3-2build1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2    2.4.7-1ubuntu4.18
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-bin    2.4.7-1ubuntu4.18
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-data    2.4.7-1ubuntu4.18
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-utils    2.4.7-1ubuntu4.18
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apparmor    2.10.95-0ubuntu2.6~14.04.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The same shell command executes in the Python console but the output shows truncated values for a few packages’ versions, for example, accountsservice, adduser, apache2, etc.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;subprocess&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; installed_packages = subprocess.check_output([&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;dpkg -l | grep ^ii | awk &lt;/span&gt;&lt;span style=&#34;color:#04d;background-color:#fff0f0&#34;&gt;\&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;{print $2 &amp;#34;    &amp;#34; $3}&lt;/span&gt;&lt;span style=&#34;color:#04d;background-color:#fff0f0&#34;&gt;\&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;&lt;/span&gt;], shell=&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style=&#34;color:#038&#34;&gt;print&lt;/span&gt; installed_packages
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;accountsservice    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0.6.35&lt;/span&gt;-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;ubuntu7.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;acl    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2.2.52&lt;/span&gt;-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;adduser    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;3.113&lt;/span&gt;+nmu3ubuntu
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ant    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1.9.3&lt;/span&gt;-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;build1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ant-optional    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1.9.3&lt;/span&gt;-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2&lt;/span&gt;build1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2.4.7&lt;/span&gt;-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;ubuntu4&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-&lt;span style=&#34;color:#038&#34;&gt;bin&lt;/span&gt;    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2.4.7&lt;/span&gt;-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;ubuntu4&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-data    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2.4.7&lt;/span&gt;-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;ubuntu4&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-utils    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2.4.7&lt;/span&gt;-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1&lt;/span&gt;ubuntu4&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apparmor    &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;2.10.95&lt;/span&gt;-&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;ubuntu2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;root-cause&#34;&gt;Root Cause&lt;/h3&gt;
&lt;p&gt;To identify the root cause of the problem, I started with source command &lt;code&gt;dpkg -l&lt;/code&gt; command without any filters and processing. I have noticed two different results for this command, with and without less command. The less command showed the complete result with scrolling as below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# dpkg -l | less&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;Desired&lt;/span&gt;=Unknown/Install/Remove/Purge/Hold
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| &lt;span style=&#34;color:#369&#34;&gt;Status&lt;/span&gt;=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|/ Err?=(none)/Reinst-required (Status,Err: &lt;span style=&#34;color:#369&#34;&gt;uppercase&lt;/span&gt;=bad)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;||/ Name                                  Version                                    Architecture Description
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+++-=====================================-==========================================-============-===============================================================================
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rc  aacraid                               1.2.1-52011                                amd64        This driver supports Adaptec by PMC aacraid family of cards.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  accountsservice                       0.6.35-0ubuntu7.3                          amd64        query and manipulate user account information
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  acl                                   2.2.52-1                                   amd64        Access control list utilities
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  adduser                               3.113+nmu3ubuntu3                          all          add and remove users and groups
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  ant                                   1.9.3-2build1                              all          Java based build tool like make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  ant-optional                          1.9.3-2build1                              all          Java based build tool like make - optional libraries
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apache2                               2.4.7-1ubuntu4.18                          amd64        Apache HTTP Server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apache2-bin                           2.4.7-1ubuntu4.18                          amd64        Apache HTTP Server (binary files and modules)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apache2-data                          2.4.7-1ubuntu4.18                          all          Apache HTTP Server (common files)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apache2-utils                         2.4.7-1ubuntu4.18                          amd64        Apache HTTP Server (utility programs &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; web servers)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rc  apache2.2-common                      2.2.22-1ubuntu1.11                         amd64        Apache HTTP Server common files
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apparmor                              2.10.95-0ubuntu2.6~14.04.1                 amd64        user-space parser utility &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; AppArmor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But &lt;code&gt;dpkg -l&lt;/code&gt; prints on the screen with truncated data due to the columns width constraint. The truncated values exactly match the Python console output. The output column width is decided by environment variable COLUMNS and commands restrict the column width in output based on COLUMNS value.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# echo $COLUMNS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;127&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;# dpkg -l&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;Desired&lt;/span&gt;=Unknown/Install/Remove/Purge/Hold
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| &lt;span style=&#34;color:#369&#34;&gt;Status&lt;/span&gt;=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|/ Err?=(none)/Reinst-required (Status,Err: &lt;span style=&#34;color:#369&#34;&gt;uppercase&lt;/span&gt;=bad)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;||/ Name                   Version          Architecture     Description
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+++-======================-================-================-==================================================
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rc  aacraid                1.2.1-52011      amd64            This driver supports Adaptec by PMC aacraid family
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  accountsservice        0.6.35-0ubuntu7. amd64            query and manipulate user account information
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  acl                    2.2.52-1         amd64            Access control list utilities
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  adduser                3.113+nmu3ubuntu all              add and remove users and groups
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  ant                    1.9.3-2build1    all              Java based build tool like make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  ant-optional           1.9.3-2build1    all              Java based build tool like make - optional librari
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apache2                2.4.7-1ubuntu4.1 amd64            Apache HTTP Server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apache2-bin            2.4.7-1ubuntu4.1 amd64            Apache HTTP Server (binary files and modules)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apache2-data           2.4.7-1ubuntu4.1 all              Apache HTTP Server (common files)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apache2-utils          2.4.7-1ubuntu4.1 amd64            Apache HTTP Server (utility programs &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; web serve
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rc  apache2.2-common       2.2.22-1ubuntu1. amd64            Apache HTTP Server common files
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  apparmor               2.10.95-0ubuntu2 amd64            user-space parser utility &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; AppArmor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;solution&#34;&gt;Solution&lt;/h3&gt;
&lt;p&gt;The subprocess module of Python provides complete untruncated output of the shell command when the argument &lt;code&gt;env={}&lt;/code&gt; is passed to check_output function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; installed_packages = subprocess.check_output([&amp;#39;dpkg -l | grep ^ii | awk \&amp;#39;{print $2 &amp;#34;    &amp;#34; $3}\&amp;#39;&amp;#39;], shell=True, env={})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; print installed_packages
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;accountsservice    0.6.35-0ubuntu7.3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;acl    2.2.52-1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;adduser    3.113+nmu3ubuntu3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ant    1.9.3-2build1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ant-optional    1.9.3-2build1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2    2.4.7-1ubuntu4.18
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-bin    2.4.7-1ubuntu4.18
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-data    2.4.7-1ubuntu4.18
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apache2-utils    2.4.7-1ubuntu4.18
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apparmor    2.10.95-0ubuntu2.6~14.04.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;explanation&#34;&gt;Explanation&lt;/h3&gt;
&lt;p&gt;Curious to know what is happening behind the scenes? The check_output function uses C library functions &lt;code&gt;execv&lt;/code&gt; or &lt;code&gt;execve&lt;/code&gt; for processing. It chooses the function based on the &lt;code&gt;env&lt;/code&gt; argument.&lt;/p&gt;
&lt;p&gt;Reference:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.python.org/2/library/subprocess.html&#34;&gt;subprocess documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/python/cpython/blob/master/Lib/subprocess.py&#34;&gt;subprocess.py source&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/google/python-subprocess32/blob/master/_posixsubprocess.c&#34;&gt;posixsubprocess.c source&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When no env argument is passed to &lt;code&gt;subprocess.check_output&lt;/code&gt;, the &lt;code&gt;os.execv&lt;/code&gt; function is called.&lt;/p&gt;
&lt;p&gt;When an env argument is passed to &lt;code&gt;subprocess.check_output&lt;/code&gt;, the &lt;code&gt;os.execve&lt;/code&gt; function is called.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;for&lt;/span&gt; (i = &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;0&lt;/span&gt;; exec_array[i] != &lt;span style=&#34;color:#038&#34;&gt;NULL&lt;/span&gt;; ++i) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;char&lt;/span&gt; *executable = exec_array[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;if&lt;/span&gt; (envp) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;execve&lt;/span&gt;(executable, argv, envp);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#080;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#06b;font-weight:bold&#34;&gt;execv&lt;/span&gt;(executable, argv);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What makes the &lt;code&gt;execv&lt;/code&gt; and &lt;code&gt;execve&lt;/code&gt; functions produce different output?&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;execv&lt;/code&gt; function passes through the shell COLUMNS variable which leads to truncating output columns to 127 width, like our reference system.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# echo $COLUMNS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;127
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; print subprocess.check_output([&amp;#39;dpkg -l | grep libqtcore4&amp;#39;], shell=True)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  libqtcore4:amd64          4:4.8.5+git192-g0 amd64             Qt 4 core module
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; print subprocess.check_output([&amp;#39;dpkg -l | grep libqtcore4&amp;#39;], shell=True, env={&amp;#39;COLUMNS&amp;#39;:&amp;#39;127&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  libqtcore4:amd64          4:4.8.5+git192-g0 amd64             Qt 4 core module&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;execve&lt;/code&gt; function uses additional argument environment variables and it is based on the &lt;code&gt;environ&lt;/code&gt; function. It uses environment variables available in env command which doesn&amp;rsquo;t have COLUMNS initialised. So output values returned without any column width restriction.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; print subprocess.check_output([&amp;#39;dpkg -l | grep libqtcore4&amp;#39;], shell=True, env={})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  libqtcore4:amd64                      4:4.8.5+git192-g085f851+dfsg-2ubuntu4.1    amd64        Qt 4 core module
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; print subprocess.check_output([&amp;#39;dpkg -l | grep libqtcore4&amp;#39;], shell=True, env={&amp;#39;COLUMNS&amp;#39;:&amp;#39;&amp;#39;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ii  libqtcore4:amd64                      4:4.8.5+git192-g085f851+dfsg-2ubuntu4.1    amd64        Qt 4 core module&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For more details refer to the man pages of &lt;code&gt;execv&lt;/code&gt;, &lt;code&gt;execve&lt;/code&gt;, &lt;code&gt;environ&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;It is always good to pass &lt;code&gt;env={}&lt;/code&gt; argument to &lt;code&gt;subprocess.check_output&lt;/code&gt; function whenever processing shell command output in Python. It helps avoid unstable results down the line due to truncated values.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Separate and Not Equal: Development Environments to Support People, Process, and Automation</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2017/01/separate-not-equal-dev-environments/"/>
      <id>https://www.endpointdev.com/blog/2017/01/separate-not-equal-dev-environments/</id>
      <published>2017-01-18T00:00:00+00:00</published>
      <author>
        <name>Dylan Wooters</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2017/01/separate-not-equal-dev-environments/bauhausstage.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;I believe in the separation of software environments for the long term peace and prosperity of developers, product owners, and users. Ideally, there’s a dedicated environment purpose-built to support each community: the developers, the testers, the acceptors, and the users.&lt;/p&gt;
&lt;p&gt;I learned this process from taking part in software development projects over the course of many years and working with a variety of different teams, including my own dev team, our clients’ in-house IT teams, and often other consulting firms. While each group had its own approach, one consistent factor for success was the separation of environments to support key roles.&lt;/p&gt;
&lt;h3 id=&#34;dev&#34;&gt;Dev&lt;/h3&gt;
&lt;p&gt;Development environments will vary by project and technology stack. A common decision is developing locally or creating a remote VM, and both approaches have trade-offs. Developing remotely allows you to setup an environment that mirrors QA and Production, and it also allows you to use remote desktop to connect to your dev environment from any machine: PC, Mac, or Linux. However, developing remotely comes with latency, and often it doesn’t feel as smooth as working locally. More importantly, if I find myself traveling or otherwise without a stable internet connection, developing remotely can be challenging if not impossible.&lt;/p&gt;
&lt;p&gt;The setup of the dev environment should be quick and painless, and the project should have clear documentation on how to get started developing. We often keep this in a Wiki in the project’s Git repository. Pairing this documentation with a pre-built dev environment is the ultimate way to get new developers up-and-running. This can be done by packaging up a VM, which can then be run locally or remotely using virtualization software like &lt;a href=&#34;https://www.virtualbox.org&#34;&gt;VirtualBox&lt;/a&gt; or a cloud platform like &lt;a href=&#34;https://aws.amazon.com&#34;&gt;AWS&lt;/a&gt;. &lt;a href=&#34;https://www.vagrantup.com&#34;&gt;Vagrant&lt;/a&gt; is another option worth checking out, as it touts a one-command setup of a complete dev environment.&lt;/p&gt;
&lt;h3 id=&#34;qa&#34;&gt;QA&lt;/h3&gt;
&lt;p&gt;The QA environment serves two purposes: as a place where various team members’ code can be built and run together, and a place where the specific task of QA can be performed. When you move to QA testing, it’s a good idea to create a separate branch in source control.This allows developers to push to a common QA branch, which can then be deployed to the QA environment, ideally using a CI tool like TeamCity.&lt;/p&gt;
&lt;p&gt;Once the QA testers have signed off, you can move into the UAT/Staging environment. It’s crucial that this environment match production as closely as possible, to rule out any “environmental bugs” that may creep in after deployment to Production. This means ensuring that all the framework versions match (.NET, Node, etc.), system resources are similar, and that the same security is in place (firewalls, VPNs). The data should also replicate what will be found in production, if not outright synced from production using a tool like &lt;a href=&#34;https://www.sqldelta.com/&#34;&gt;SQL Delta&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;stage&#34;&gt;Stage&lt;/h3&gt;
&lt;p&gt;In staging, the software is put before a specially designated group of users for a dress rehearsal.&lt;/p&gt;
&lt;p&gt;If I’m developing a desktop or mobile application (not a web app), I ensure that testing on a variety of different OS versions is incorporated into the UAT process. For example, I use Apple’s &lt;a href=&#34;https://developer.apple.com/testflight/&#34;&gt;TestFlight&lt;/a&gt; to test across a variety of devices using different iOS versions.&lt;/p&gt;
&lt;h3 id=&#34;prod&#34;&gt;Prod&lt;/h3&gt;
&lt;p&gt;Production is the main stage, and code should obviously only be pushed there after proper testing. Even if I have customers, clients, and/or bosses yelling at me, I try and resist the urge to push a fix directly to Production! Although the fix may have worked perfectly in my dev environment, it might not work in production, and then I can easily find myself in even deeper trouble than before. If there is not time to coordinate UAT, then at the very least I push to QA, where the build can be verified in a separate environment, and another set of eyes can perform some testing. It goes without saying that all of this can be made less frightful with unit testing, a topic that we will explore later.&lt;/p&gt;
&lt;p&gt;It’s also important to ensure that production has adequate resources before going live. If I’m building a new version or replacement of existing software, I review the existing reporting/​analytics to know things like concurrent user count and storage requirements per user. This may seem obvious, but in the rush to get software out to market, basic things can be overlooked. Also, I ensure that I have some baseline security in place on production. This means encrypting sensitive data in config files, not storing passwords (just salted hashes!), and if I’m using a cloud provider like AWS or Azure, I add two-factor authentication to the admin account.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>8 Simple Steps to Saner Software Development</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2016/11/8-simple-steps-to-saner-software-development/"/>
      <id>https://www.endpointdev.com/blog/2016/11/8-simple-steps-to-saner-software-development/</id>
      <published>2016-11-10T00:00:00+00:00</published>
      <author>
        <name>Dylan Wooters</name>
      </author>
      <content type="html">
        &lt;div class=&#34;separator&#34; style=&#34;clear: both; text-align: center;&#34;&gt;&lt;img border=&#34;0&#34; src=&#34;/blog/2016/11/8-simple-steps-to-saner-software-development/layercake.jpg&#34;/&gt;&lt;/div&gt;
&lt;p&gt;While these might seem obvious for seasoned developers, many projects, especially legacy software, still fail to follow most of the steps below.&lt;/p&gt;
&lt;p&gt;In future posts, I’ll expand on these steps and give more details. For now, here’s an overview of some basic guidelines for making the process of software development smoother (&amp;amp; saner) for both the client and the dev team.&lt;/p&gt;
&lt;h3 id=&#34;separate-environments&#34;&gt;Separate environments:&lt;/h3&gt;
&lt;p&gt;Ideally there should be Dev, QA, UAT/Staging, and Production environments. And, UAT/Staging should be as close to Production as possible. It’s amazing how many software projects are still done on someone’s local machine and pushed directly to Production.&lt;/p&gt;
&lt;h3 id=&#34;use-a-bug-tracking-tool&#34;&gt;Use a bug tracking tool:&lt;/h3&gt;
&lt;p&gt;This is pretty obvious. Bugs need to be logged and labeled so that they can be tracked through stages of development (i.e., To-Do, In Progress, Completed). Using a bug tracking tool like Jira or GitHub also helps the non-technical stakeholders comment on and clarify requirements/issues.&lt;/p&gt;
&lt;h3 id=&#34;have-a-source-control-strategy&#34;&gt;Have a source control strategy:&lt;/h3&gt;
&lt;p&gt;It doesn’t have to be fancy. For example, if you’re using Git, it should be more than having multiple developers working out of the master branch. Ideally link branches to features or bugs defined in a bug tracking tool, and keep in mind the separation of environments, especially if the application is already in Production.&lt;/p&gt;
&lt;h3 id=&#34;do-pullmerge-requests&#34;&gt;Do pull/merge requests:&lt;/h3&gt;
&lt;p&gt;Even a short five minute review will improve the overall quality of code, reduce bugs, and communicate changes between developers responsible for different parts of the application. Web-based source control systems like GitLab, GitHub, and Bitbucket make this simple.&lt;/p&gt;
&lt;h3 id=&#34;write-unit-tests&#34;&gt;Write unit tests:&lt;/h3&gt;
&lt;p&gt;A lot of developers either feel pressure to move quickly or get lazy and don’t write tests. Regression testing becomes a nightmare without unit tests. Plus it makes you feel better to see all those tests passing.&lt;/p&gt;
&lt;h3 id=&#34;use-a-continuous-integration-tool&#34;&gt;Use a continuous integration tool:&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://www.jetbrains.com/teamcity/&#34;&gt;TeamCity&lt;/a&gt;, &lt;a href=&#34;https://jenkins-ci.org&#34;&gt;Jenkins&lt;/a&gt;, or even basic &lt;a href=&#34;http://githooks.com&#34;&gt;GitHooks&lt;/a&gt; are some options. Automated deployments save time and, if integrated with unit tests, reduce the bugs that make it to Production.&lt;/p&gt;
&lt;h3 id=&#34;setup-notifications&#34;&gt;Setup notifications:&lt;/h3&gt;
&lt;p&gt;If the CI tool alerts team members of deployment status, hundreds of “is the deployment done yet?” emails and chat messages can be saved. Slack integration is a good option here.&lt;/p&gt;
&lt;h3 id=&#34;consolidate-project-credentials&#34;&gt;Consolidate project credentials:&lt;/h3&gt;
&lt;p&gt;Have a secure and centralized location for managing passwords. We like keeping a KeePass checked into the relevant project’s repo.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>2015 Perl Dancer Conference videos</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/12/2015-perl-dancer-conference-videos/"/>
      <id>https://www.endpointdev.com/blog/2015/12/2015-perl-dancer-conference-videos/</id>
      <published>2015-12-30T00:00:00+00:00</published>
      <author>
        <name>Sam Batschelet</name>
      </author>
      <content type="html">
        &lt;p&gt;The 2015 &lt;a href=&#34;https://www.perl.dance&#34;&gt;Perl Dancer Conference&lt;/a&gt; has recently released the presentation videos. This year the conference was hosted in beautiful Vienna, Austria. Josh Lavin and I were both honored to attend the conference as well as give talks. Earlier, Josh wrote summaries of the conference:&lt;/p&gt;
&lt;h3 id=&#34;conference-recap&#34;&gt;Conference Recap&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;/blog/2015/10/perl-dancer-conference-2015-report/&#34;&gt;Training Days&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;/blog/2015/10/perl-dancer-conference-2015-report_30/&#34;&gt;Conference Days&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;conference-presentations&#34;&gt;Conference Presentations&lt;/h3&gt;
&lt;h4 id=&#34;spacecamps-the-final-frontier&#34;&gt;SpaceCamps “The Final Frontier”&lt;/h4&gt;
&lt;p&gt;I gave a talk exploring new technologies for End Point’s own &lt;a href=&#34;http://devcamps.org&#34;&gt;DevCamps&lt;/a&gt; development tool. During the presentation I detailed my research into containers and what a cloud-based development environment might look like.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=IYKs8FF8--Y&#34;&gt;SpaceCamps Presentation Video&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;angularjs--dancer-for-modern-web-development&#34;&gt;AngularJS &amp;amp; Dancer for Modern Web Development&lt;/h4&gt;
&lt;p&gt;Josh detailed his experience migrating legacy applications utilizing Dancer, AngularJS, and modern Perl techniques. Josh highlighted the challenges he faced during the process, as well as lessons he learned along the way.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=m7q6QbSHrkA&#34;&gt;AngularJS &amp;amp; Dancer for Modern Web Development Presentation Video&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;lightning-talks&#34;&gt;Lightning Talks&lt;/h3&gt;
&lt;p&gt;Josh and I both gave short “lightning talks.” Josh’s was on &lt;a href=&#34;https://youtu.be/-eg21qxxIAA?t=12m47s&#34;&gt;Writing Unit Tests for a Legacy App (Interchange 5)&lt;/a&gt;, and mine was on &lt;a href=&#34;https://youtu.be/-eg21qxxIAA?t=19m11s&#34;&gt;Plack &amp;amp; Interchange 5.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To review the rest of the presentations please checkout the &lt;a href=&#34;https://www.youtube.com/channel/UCWtnsx6yRuHvO2e-xX2Yyng&#34;&gt;Perl Dancer Conference YouTube channel&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;summary&#34;&gt;Summary&lt;/h3&gt;
&lt;p&gt;The Perl Dancer community continues to flourish and the conference this year hosted a record 5 core &lt;a href=&#34;http://perldancer.org&#34;&gt;Dancer&lt;/a&gt; developers. Dancer is about to release the finalized version of its long awaited plugin infrastructure for &lt;a href=&#34;https://github.com/PerlDancer/Dancer2&#34;&gt;Dancer2&lt;/a&gt;. A lot of work on this was completed during the conference. Being an organizer of the conference, it brings me great joy to see this success. This news along with the release of Perl 6, I am certain 2016 will be a wonderful year for not only Dancer but the entire &lt;a href=&#34;https://www.perl.org/&#34;&gt;Perl&lt;/a&gt; community.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Handling databases in dev environments for web development</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/04/handling-databases-in-dev-environments/"/>
      <id>https://www.endpointdev.com/blog/2015/04/handling-databases-in-dev-environments/</id>
      <published>2015-04-21T00:00:00+00:00</published>
      <author>
        <name>Spencer Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;One of the biggest problems for web development environments is copying large amounts of data.  Every time a new environment is needed, all that data needs to be copied.  Source code should be tracked in version control software, and so copying it should be a simple matter of checking it out from the code repository.  So that is usually not the problem.  The main problem area is database data.  This can be very large, take a long time to copy, and can impact the computers involved in the copy (usually the destination computer gets hammered with IO which makes load go high).&lt;/p&gt;
&lt;p&gt;Often databases for development environments are created by copying a database dump from production and then importing that database dump.  And since database dumps are text, they can be highly compressed, which can result in a relatively small file to copy over.  But the import of the dump can still take lots of time and cause high load on the dev computer as it rebuilds tables and indexes.  As long as your data is relatively small, this process may be perfectly acceptable.&lt;/p&gt;
&lt;h3 id=&#34;your-database-will-get-bigger&#34;&gt;Your database WILL get bigger&lt;/h3&gt;
&lt;p&gt;At some point though your database will get so big that this process will take too long and cause too much load to be acceptable.&lt;/p&gt;
&lt;p&gt;To address the problem you can try to reduce the amount of data involved by only dumping a portion of the database data instead of all of it, or possibly using some “dummy sample data” instead.  These techniques may work if you don’t care that development environments no longer have the same data as production.  However, one serious problem with this is that a bug or behavior found in production can’t be replicated in a development environment because the data involved isn’t the same.  For example, say a customer can’t checkout on the live site but you can’t replicate the bug in your development environment to fix the bug.  In this example, the root cause of the problem could be a bug in the code handling certain products that are out of stock, and since the dev database didn’t have the same data it could make finding and fixing these types of problems &lt;em&gt;a lot harder&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&#34;snapshots&#34;&gt;Snapshots&lt;/h3&gt;
&lt;p&gt;Another option is to use file system snapshots, like LVM snapshots, to quickly make clones of the database without needing to import the database dump each time.  This works great if development environments live on the same server, or at least the development databases live on the same server.  You would need to create a volume to hold a single copy of the database; this copy would be the origin for all snapshots.  Then for each development environment, you could snapshot the origin volume, mount it read-write in a place accessible by the developer, customize the database configuration (like setting a unique port number to listen on), and then start up the database.  This then provides a clone of the entire database in a tiny fraction of the time and uses less disk space and other system resources too.&lt;/p&gt;
&lt;p&gt;In using snapshots there are some things you’ll need to be careful about.  Snapshots are usually created using copy-on-write tables.  The more snapshots mounted read-write, the more IO overhead is involved for the volumes involved.  For this reason it is important that writes to the origin volume be avoided as much as possible while the snapshots are open.  Also, snapshots that get a lot of writes can fill up their copy-on-write table, and depending on the file system and database that you are using this can be a big problem.  So it is important to monitor each open snapshot for how full it is and increase their size if needed so they don’t fill up.  Updating the origin database will require shutting down and removing all snapshots first, then update the origin database, then create and mount all the snapshots again.  This is because all the copy-on-write tables would get full if you tried to update the origin while the snapshots are open.&lt;/p&gt;
&lt;p&gt;Using snapshots like this may sound more complicated, and it is, but the processes involved can be scripted and automated and the benefits can be pretty significant if you have several developers and a lot of data to copy.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>On End Point’s Development Environment</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2015/03/on-end-points-development-environment/"/>
      <id>https://www.endpointdev.com/blog/2015/03/on-end-points-development-environment/</id>
      <published>2015-03-11T00:00:00+00:00</published>
      <author>
        <name>Steph Skardal</name>
      </author>
      <content type="html">
        &lt;p&gt;A few recent conversations have sparked my interest in writing up a blog post that summarizes the familiar elements of our development environments. The majority of End Pointers work remotely, but many of the tools listed below are common to many developers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ssh/sftp&lt;/strong&gt;: We do primarily remote development. Many of us are familiar with local development, but remote development with camps (see next point) is typically the most efficient arrangement in working with multiple development instances that are accessible to clients for testing and staging.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;camps&lt;/strong&gt;: &lt;a href=&#34;http://www.devcamps.org/&#34;&gt;DevCamps&lt;/a&gt; are a tool specific to and created by End Point, which are development instances with an entire webserver, database, and app server stack, similar to containers like &lt;a href=&#34;https://www.docker.com/&#34;&gt;Docker&lt;/a&gt;. Check out &lt;a href=&#34;http://www.devcamps.org/&#34;&gt;the DevCamps website&lt;/a&gt; for more information.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;vim/emacs/nano&lt;/strong&gt;: While most of our employees use vim or emacs for command-line editors, nano is an inefficient but easy to use editor that we can suggest to new developers. Not many of us use &lt;a href=&#34;https://en.wikipedia.org/wiki/Integrated_development_environment&#34;&gt;IDEs&lt;/a&gt;, if at all.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;screen/tmux&lt;/strong&gt;: screen and tmux are our preferred terminal multitasking and sharing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;command-line database interaction (specifically psql and mysql ad-hoc querying)&lt;/strong&gt;: Working with an SQL database through an &lt;a href=&#34;https://en.wikipedia.org/wiki/Object-relational_mapping&#34;&gt;ORM&lt;/a&gt; like &lt;a href=&#34;http://guides.rubyonrails.org/active_record_basics.html&#34;&gt;Active Record&lt;/a&gt;, &lt;a href=&#34;http://www.dbix-class.org/&#34;&gt;DBIC&lt;/a&gt;, etc. is not enough for us.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;*nix / basic command-line interaction&lt;/strong&gt;: This topic could make up its own blog post, but some of the tools we use frequently are netstat/ss, ifconfig/ip, lsof, ps/top/htop/atop, free, df, nice/ionice, tail -f, sort, uniq -c, grep.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;git &amp;amp; &lt;a href=&#34;https://github.com/&#34;&gt;github&lt;/a&gt;&lt;/strong&gt;: Not uncommon to devshops these days, git is the most popular version control system, and github an extremely popular host of both open source and private repositories.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IRC, Skype, Google Hangouts, &lt;a href=&#34;https://appear.in/&#34;&gt;appear.in&lt;/a&gt;, &lt;a href=&#34;https://talky.io/&#34;&gt;talky.io&lt;/a&gt;, &lt;a href=&#34;https://glideroom.com/&#34;&gt;glideroom.com&lt;/a&gt;, Google Voice, &amp;amp; &lt;em&gt;gasp&lt;/em&gt; regular phones&lt;/strong&gt;: As remote developers, we communicate often and there are a number of tools available in the communication space that we leverage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s interesting to note that if any new developers come in with a preference for a trendy new tool, while we are happy to let them work in an environment that allows them to be efficient, ultimately we can’t provide support for those tools that we are unfamiliar with.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Looking at development environments with DevCamps and Vagrant</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/08/looking-at-development-environments/"/>
      <id>https://www.endpointdev.com/blog/2014/08/looking-at-development-environments/</id>
      <published>2014-08-25T00:00:00+00:00</published>
      <author>
        <name>Spencer Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;For most web developers, you have practices and tools that you are used to using to do your work. And for most web developers this means setting up your workstation with all the things you need to do your editing, compiling, testing, and pushing code to some place for sharing or deployment. This is a very common practice even though it is fraught with problems- like getting a database setup properly, configuring a web server, any other services (memcached, redis, mongodb, etc), and many more issues.&lt;/p&gt;
&lt;p&gt;Hopefully at some point you realize the pain that is involved in doing everything on your workstation directly and start looking for a better way to do web development. In this post I will be looking at some ways to do this better: using a virtual machine (VM), Vagrant, and DevCamps.&lt;/p&gt;
&lt;h3 id=&#34;using-a-vm-for-development&#34;&gt;Using a VM for development&lt;/h3&gt;
&lt;p&gt;One way to improve things is to use a local virtual machine for your development (for example, using VirtualBox, or VMware Fusion). You can edit your code normally on your workstation, but then execute and test it in the VM. This also makes your workstation “clean”, moving all those dependencies (like a database, web server, etc.) off your workstation and into the VM. It also gets your dev environment closer to production, if not identical. Sounds nice, but let’s break down the pros and cons.&lt;/p&gt;
&lt;h4 id=&#34;benefits-of-using-a-vm&#34;&gt;Benefits of using a VM&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Dev environment closely matches production.&lt;/li&gt;
&lt;li&gt;Execute and test code in a dedicated machine (not your workstation directly).&lt;/li&gt;
&lt;li&gt;Allows for multiple projects to be worked on concurrently (one VM per project).&lt;/li&gt;
&lt;li&gt;Exposes the developer to the Operations (systems administration) side of the web application (always a good thing).&lt;/li&gt;
&lt;li&gt;Developer can edit files using their favorite text editor locally on the workstation (but will need to copy files to the VM as needed).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;problems-with-using-a-vm&#34;&gt;Problems with using a VM&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Need to create and configure the VM. This could be very time consuming and error prone.&lt;/li&gt;
&lt;li&gt;Still need to install and configure all services and packages. This could also be time consuming and error prone.&lt;/li&gt;
&lt;li&gt;Backups of your work/configuration/everything are your own responsibility (extremely unlikely to happen).&lt;/li&gt;
&lt;li&gt;Access to your dev environment is extremely limited, thus probably only you can access it and test things on it. No way for a QA engineer or business owner to test/demo your work.&lt;/li&gt;
&lt;li&gt;Inexperienced developers can break things, or change them to no longer match production (install arbitrary packages, different versions than what is in production, screw up the db, screw up Apache configuration, etc.).&lt;/li&gt;
&lt;li&gt;If working with an established database, then downloading a dump, installing, and getting the database usable is time consuming and error prone. (“I just broke my dev database!” can be a complete blocker for development.)&lt;/li&gt;
&lt;li&gt;The developer needs to set up networking for the VM in order to ssh to it, copy files back and forth, and point a web browser to it. This may include manually setting up DNS, or /etc/hosts entries, or port forwarding, or more complex setups.&lt;/li&gt;
&lt;li&gt;If using SSL with the web application, then the developer also needs to generate and install the SSL cert and configure the web server correctly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;vagrant&#34;&gt;Vagrant&lt;/h3&gt;
&lt;p&gt;What is &lt;a href=&#34;https://www.vagrantup.com&#34;&gt;Vagrant&lt;/a&gt;? It is a set of tools to make it easier to use a virtual machine for your web development. It attempts to lessen many of the problems listed above through the use of automation. By design it also makes some assumptions about how you are using the VM. For example, it assumes that you have the source code for you project in a directory somewhere directly on your workstation and would prefer to use your favorite text editor on those files. Instead of expecting you to continually push updated files to your VM, it sets up a corresponding directory on the VM and keeps the two in sync for you (using either shared folders, NFS, Samba, or rsync). It also sets up the networking for accessing the VM, usually with port forwarding, so you don’t have to worry about that.&lt;/p&gt;
&lt;h4 id=&#34;benefits-of-vagrant&#34;&gt;Benefits of Vagrant&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Same as those listed above for using a VM, plus&amp;hellip;&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Flexible configuration (Vagrantfile) for creating and configuring the VM.&lt;/li&gt;
&lt;li&gt;Automated networking for the VM with port forwarding. Abstracted ssh access (don’t need to set up a hostname for the VM, simply type &lt;code&gt;vagrant ssh&lt;/code&gt; to connect). Port forwarded browser access to the VM (usually http://localhost:8080, but configurable).&lt;/li&gt;
&lt;li&gt;Synced directory between your workstation and the VM for source code. Allows for developers to use their favorite text editor locally on their workstation without needing to manually copy files to the VM.&lt;/li&gt;
&lt;li&gt;Expects the use of a configuration management system (like puppet, chef, salt, or bash scripts) to “provision” the VM (which could help with proper and consistent setup).&lt;/li&gt;
&lt;li&gt;Through the use of &lt;a href=&#34;https://vagrantcloud.com/&#34;&gt;Vagrant Cloud&lt;/a&gt; you can get a generated url for others to access your VM (makes it publicly available through a tunnel created with the command &lt;code&gt;vagrant share&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Configuration (Vagrantfile and puppet/chef/salt/etc.) files can be maintained/reviewed by Operations engineers for consistency with production.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;problems-with-vagrant&#34;&gt;Problems with Vagrant&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Still need to install and configure all services and packages. This is lessened with the use of a configuration management tool like puppet, but you still need to create/debug/maintain the puppet configuration and setup.&lt;/li&gt;
&lt;li&gt;Backups of your work/configuration/everything are your own responsibility (extremely unlikely to happen). This may be lessened for VM configuration files, assuming they are included in your project’s VCS repo along with your source code.&lt;/li&gt;
&lt;li&gt;Inexperienced developers can still break things, or change them to no longer match production (install arbitrary packages, different versions than what is in production, screw up the db, screw up Apache configuration, etc.).&lt;/li&gt;
&lt;li&gt;If working with an established database, then downloading a dump, installing, and getting the database usable is time consuming and error prone. (“I just broke my dev database!” can be a complete blocker for development.)&lt;/li&gt;
&lt;li&gt;If using SSL with the web application, then the developer also needs to generate and install the SSL cert and configure the web server correctly. This might be lessened if puppet (or whatever) is configured to manage this for you (but then you need to configure puppet to do that).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;devcamps&#34;&gt;DevCamps&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&#34;http://devcamps.org&#34;&gt;DevCamps&lt;/a&gt; system takes a different approach. Instead of using VMs for development, it utilizes a shared server for all development. Each developer has their own account on the camps server and can create/update/delete “camps” (which are self-contained environments with all the parts needed). There is an initial setup for using camps which needs thorough understanding of the web application and all of its dependencies (OS, packages, services, etc.). For each camp, the system will create a directory for the user with everything related to that camp in it, including the web application source code, their own web server configuration, their own database with its own configuration, and any other resources. Each camp is assigned a camp number, and all services for that camp run on different ports (based on the camp number). For example, camp 12 may have Apache running on ports 9012 (HTTP) and 9112 (HTTPS) and MySQL running on port 8912. The developer doesn’t need to know these ports, as tools allow for easier access to the needed services (commands like &lt;code&gt;mkcamp&lt;/code&gt;, &lt;code&gt;re&lt;/code&gt; for restarting services, &lt;code&gt;mysql_camp&lt;/code&gt; for access to the database, etc.).&lt;/p&gt;
&lt;p&gt;DevCamps has been designed to address some of the pain usually associated with development environments. Developers usually do not need to install anything, since all dependencies should already be installed on the camps server (which should be maintained by an Operations engineer who can keep the packages, versions, etc. consistent with production). Having all development on a server allows Operations engineers to backup all dev work fairly easily. Databases do not need to be downloaded, manually setup, or anything- they should be set up initially with the camps system and then running &lt;code&gt;mkcamp&lt;/code&gt; clones the database and sets it up for you. Running &lt;code&gt;refresh-camp --db&lt;/code&gt; allows a developer to delete their camp’s database and get a fresh clone, ready to use.&lt;/p&gt;
&lt;h4 id=&#34;benefits-of-devcamps&#34;&gt;Benefits of DevCamps&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Each developer can create/delete camps as needed, allowing for multiple camps at once and multiple projects at once.&lt;/li&gt;
&lt;li&gt;Operations engineers can manage/maintain all dependencies for development, ensuring everything is consistent with production.&lt;/li&gt;
&lt;li&gt;Backups of all dev work is easy (Operations engineer just needs to backup the camps server).&lt;/li&gt;
&lt;li&gt;Developer does not need to configure services (camp templating system auto-generates needed configuration for proper port numbers), such as Apache, nginx, unicorn, MySQL, Postgres, etc.&lt;/li&gt;
&lt;li&gt;SSL certificates can be easily shared/generated/installed/etc. automatically with the &lt;code&gt;mkcamp&lt;/code&gt; script. Dev environments can easily have HTTPS without the developer doing anything.&lt;/li&gt;
&lt;li&gt;Developers should not have permissions to install/change system packages or services. Thus inexperienced developers should not be able to break the server, other developer’s environments, install arbitrary software. Screwing up their database or web server config can be fixed by either creating a new camp, refreshing their existing one, or an Operations engineer can easily fix it for them (since it is on a central server they would already have access to, and not need to worry about how to access some VM who knows where).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;problems-with-devcamps&#34;&gt;Problems with DevCamps&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Since all camps live on a shared server running on different ports, this will not closely match production in that way. However, this may not be significant if nearly everything else does closely match production.&lt;/li&gt;
&lt;li&gt;Adding a new dependency (for example, adding mongodb, or upgrading the version of Apache) may require quite a bit of effort and will affect all camps on the server- Operations engineer will need to install the needed packages and add/change the needed configuration to the camps system and templates.&lt;/li&gt;
&lt;li&gt;Using your favorite text editor locally on your workstation doesn’t really work since all code lives on the server. It is possible to SFTP files back and forth, but this can be tedious and error prone.&lt;/li&gt;
&lt;li&gt;Many aspects of the Operations (systems administration) side of the web application are hidden from the developer (this might also be considered a benefit).&lt;/li&gt;
&lt;li&gt;All development is on a single server, which may be a single point of failure (if the camps server is down, then all development is blocked for all developers).&lt;/li&gt;
&lt;li&gt;One camp can use up more CPU/RAM/disk/etc. then others and affect the server’s load, affecting the performance of all other camps.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;concluding-thoughts&#34;&gt;Concluding Thoughts&lt;/h3&gt;
&lt;p&gt;It seems that Vagrant and DevCamps certainly have some good things going for them. I think it might be worth some thought and effort to try to meld the two together somehow, to take the benefits of both and reduce the problems as much as possible. Such a system might look like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Utilize vagrant commands and configuration, but have all VMs live on a central VM server. Thus allowing for central backups and access.&lt;/li&gt;
&lt;li&gt;Source code and configuration lives on the server/VM but a synced directory is set up (sshfs mount point?) to allow for local editing of text files on the workstation.&lt;/li&gt;
&lt;li&gt;VMs created should have restricted access, preventing developers from installing arbitrary packages, versions, screwing up the db, etc.&lt;/li&gt;
&lt;li&gt;Configuration for services (database, web server, etc.) should be generated/managed by Operations engineers for consistency (utilizing puppet/chef/salt/etc.).&lt;/li&gt;
&lt;li&gt;Databases should be cloned from a local copy on the VM server, thus avoiding the need to download anything and reducing setup effort.&lt;/li&gt;
&lt;li&gt;SSL certs should be copied/generated locally on the VM server and installed as appropriate.&lt;/li&gt;
&lt;li&gt;Sharing access to a VM should not depend on Vagrant Cloud, but instead should use some sort of internal service on the VM server to automate VM hostname/DNS for browser and ssh access to the VM.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m sure there are more pros and cons that I’ve missed. Add your thoughts to the comments below. Thanks.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Provisioning a Development Environment with Packer, Part 2</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/03/provisioning-development-environment_14/"/>
      <id>https://www.endpointdev.com/blog/2014/03/provisioning-development-environment_14/</id>
      <published>2014-03-14T00:00:00+00:00</published>
      <author>
        <name>Mike Farmer</name>
      </author>
      <content type="html">
        &lt;p&gt;In my &lt;a href=&#34;/blog/2014/03/provisioning-development-environment/&#34;&gt;previous post&lt;/a&gt; on provisioning a development environment with &lt;a href=&#34;https://www.packer.io&#34;&gt;Packer&lt;/a&gt; I walked through getting a server setup with an operating system installed. This post will be focused setting up &lt;a href=&#34;https://www.ansible.com&#34;&gt;Ansible&lt;/a&gt; so that I can setup my development environment just the way I like it. Packer supports many different methods for provisioning. After playing with some of them, I decided that Ansible was a good mix of simplicity and functionality.&lt;/p&gt;
&lt;p&gt;A Packer provisioner is simply a configuration template that is added to the json configuration file. The “provisioners” section of the configuration file takes an array of json objects which means that you aren’t stuck with just one kind of provisioner. For example, you could run some shell scripts using the &lt;a href=&#34;https://www.packer.io/docs/provisioners/shell.html&#34;&gt;shell provisioner&lt;/a&gt;, then upload some files using the &lt;a href=&#34;https://www.packer.io/docs/provisioners/file.html&#34;&gt;File Uploads&lt;/a&gt; provisioner, followed by your devops tool of choice (&lt;a href=&#34;https://web.archive.org/web/20150706082720/https://www.packer.io/docs/provisioners/puppet-masterless.html&#34;&gt;puppet&lt;/a&gt;, &lt;a href=&#34;https://web.archive.org/web/20190508114914/http://packer.io/docs/provisioners/salt-masterless.html&#34;&gt;salt&lt;/a&gt;, &lt;a href=&#34;https://web.archive.org/web/20210615181646/https://www.packer.io/docs/provisioners/chef-solo&#34;&gt;chef&lt;/a&gt;, or &lt;a href=&#34;https://web.archive.org/web/20210615182101/https://www.packer.io/docs/provisioners/ansible-local&#34;&gt;ansible&lt;/a&gt;). You can even &lt;a href=&#34;https://web.archive.org/web/20160405051550/https://www.packer.io/docs/extend/provisioner.html&#34;&gt;roll-your-own&lt;/a&gt; provisioner if desired. Here’s an example provisioner setup for the shell provisioner:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;variables&amp;#34;: {...},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;builders&amp;#34; : [...],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;provisioners&amp;#34; [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;type&amp;#34;: &amp;#34;shell&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;inline&amp;#34;: [ &amp;#34;echo foo&amp;#34; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;sudo-and-user-considerations&#34;&gt;Sudo and User Considerations&lt;/h3&gt;
&lt;p&gt;Packer will login to the server over ssh and run your provisioners. The big headache that always comes out of this is some provisioners require sudo, or being logged in as root, to run their commands. Packer, however, will login as the user that was created during the build stage (see the “builders” section in the code snippet in the &lt;a href=&#34;/blog/2014/03/provisioning-development-environment/&#34;&gt;previous post&lt;/a&gt;). There are a couple of ways to handle this. First, you can do everything in packer as root. I don’t love this approach because I like to simulate the way that I setup a machine by hand and I never login as root if I can help it. The second method is to grant your user sudo access. This gets a little tricky so I’ll just show the a code snippet and then explain it below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;type&amp;#34;: &amp;#34;shell&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;execute_command&amp;#34;: &amp;#34;echo &amp;#39;{{user `ssh_pass`}}&amp;#39; | {{ .Vars }} sudo -E -S sh &amp;#39;{{ .Path }}&amp;#39;&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;#34;inline&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;echo &amp;#39;%sudo    ALL=(ALL)  NOPASSWD:ALL&amp;#39; &amp;gt;&amp;gt; /etc/sudoers&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Utilizing the shell provisioner, the execute_command option is used to specify to the provisioner that whenever a command is run, use this command. The commands provided to the inline array are compiled into a single shell script which is injected as the .Path variable. To quote the Packer &lt;a href=&#34;https://www.packer.io/docs/provisioners/shell.html&#34;&gt;documentation&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The -S flag tells sudo to read the password from stdin, which in this case is being piped in with the value of [the user variable ssh_pass.] The -E flag tells sudo to preserve the environment, allowing our environmental variables to work within the script.&lt;/p&gt;
&lt;p&gt;By setting the execute_command to this, your script(s) can run with root privileges without worrying about password prompts.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Taking advantage of this trick, a command can now be placed in the inline section that will add all members of the sudo group to the sudoers file granting them permission to use sudo without a password. Now I know this isn’t secure but for my purpose, which is to create a custom development enviornment on a Virtual Machine running only on my machine, this will be just fine. I also use this example to illustrate how to run commands as sudo.&lt;/p&gt;
&lt;h3 id=&#34;the-ansible-provisioner&#34;&gt;The Ansible Provisioner&lt;/h3&gt;
&lt;p&gt;Once the shell provisioner is working, Ansible can be installed on the new machine and then executed using Packer’s Ansible provisioner. The easiest way to do this that I found was to have the shell provisioner install Ansible on the virtual machine as well as upload an ssh public key so that the Ansible user could log in. My “provisioners” section looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;#34;provisioners&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;type&amp;#34;: &amp;#34;shell&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;inline&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;mkdir .ssh&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;echo &amp;#39;{{user `public_key`}}&amp;#39; &amp;gt;&amp;gt; .ssh/authorized_keys&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;type&amp;#34;: &amp;#34;shell&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;execute_command&amp;#34;: &amp;#34;echo &amp;#39;{{user `ssh_pass`}}&amp;#39; | {{ .Vars }} sudo -E -S sh &amp;#39;{{ .Path }}&amp;#39;&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;inline&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;add-apt-repository ppa:rquillo/ansible&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;apt-get update&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;apt-get install -y ansible&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;#34;echo &amp;#39;%sudo    ALL=(ALL)  NOPASSWD:ALL&amp;#39; &amp;gt;&amp;gt; /etc/sudoers&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;type&amp;#34;: &amp;#34;ansible-local&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;#34;playbook_file&amp;#34;: &amp;#34;site.yml&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This configuration uses a variable in which I placed an ssh public key (I could also have used the File Uploads provisioner for this), installs Ansible from an updated PPA, and grants the user sudo priveliges via the sudo group as explained above. This also shows how you can execute more than one statement at a time using the “shell” provisioner.&lt;/p&gt;
&lt;h3 id=&#34;ansible-provisioning-tip&#34;&gt;Ansible Provisioning Tip&lt;/h3&gt;
&lt;p&gt;This tip could probably apply to any of the devops tools you’d like to use. If you are creating your Ansible yml files for the first time, you will likely run into the issue where you spend a lot of time waiting for the machine to build and provision only to discover your Ansible script is wrong. Troubleshooting becomes a problem because if anything fails during the provision, Packer will stop running and delete the Virtual Machine leaving you with no option other than fixing your mistake and then waiting for the entire process to run again.&lt;/p&gt;
&lt;p&gt;One way I found around this is to take the last section of the provisioners array out, build your machine, and then move the base machine into a new directory once it’s been successfully built. From there you can start the machine manually and then run the ansible-playbook command from your local machine while you develop your playbook. Once you have a working playbook, add the ansible-local section back to the provisioners array and rebuild your machine with Packer. That should speed up your development and troubleshooting cycles.&lt;/p&gt;
&lt;h3 id=&#34;a-hiccup-with-ansible-and-packer&#34;&gt;A Hiccup with Ansible and Packer&lt;/h3&gt;
&lt;p&gt;Ansible allows you to create template files that can be used for configuration files and the like. According to the documentation, you can specify the location of the templates and other files using the playbook_paths option in the provisioner. I could not get this to work and after a lot of troubleshooting and looking at the code for the provisioner I am convinced there is a bug copying the playbook_paths directories to the remote machine. I’ve &lt;a href=&#34;https://groups.google.com/forum/#!topic/packer-tool/RrIGFH3K1bE&#34;&gt;posted on the Packer discussion group&lt;/a&gt; about this but haven’t had any response on it yet. Once I get to the bottom the issue I’ll post an update here.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Packer has turned out to be a fabulous resource for me in quickly ramping up development environments. Ansible has also been a breath for fresh air for provisioning those machines. I’ve previously used &lt;a href=&#34;https://www.getchef.com/chef/&#34;&gt;chef&lt;/a&gt; and other devops tools which only led to a great deal of frustration. I’m happy to have some new tools in my belt that took very little time to learn and to get working.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Provisioning a Development Environment with Packer, Part 1</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/03/provisioning-development-environment/"/>
      <id>https://www.endpointdev.com/blog/2014/03/provisioning-development-environment/</id>
      <published>2014-03-12T00:00:00+00:00</published>
      <author>
        <name>Mike Farmer</name>
      </author>
      <content type="html">
        &lt;p&gt;I recently needed to reconstruct an old development environment for a project I worked on over a year ago. The codebase had aged a little and I needed old versions of just about everything from the OS and database to Ruby and Rails. My preferred method for creating a development environment is to setup a small virtual machine (VM) that mimics the production environment as closely as possible.&lt;/p&gt;
&lt;h3 id=&#34;introducing-packer&#34;&gt;Introducing Packer&lt;/h3&gt;
&lt;p&gt;I have been hearing a lot of buzz lately about &lt;a href=&#34;https://www.packer.io/&#34;&gt;Packer&lt;/a&gt; and wanted to give it a shot for setting up my environment. Packer is a small command line tool written in the increasingly popular &lt;a href=&#34;https://golang.org/&#34;&gt;Go&lt;/a&gt; programming language. It serves three primary purposes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Building a machine based on a set of configuration parameters&lt;/li&gt;
&lt;li&gt;Running a provisioner to setup the machine with a desired set of software and settings&lt;/li&gt;
&lt;li&gt;Performing any post processing instructions on that machine&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Packer is really simple to install and I would refer you to their &lt;a href=&#34;https://www.packer.io/docs/installation.html&#34;&gt;great documentation&lt;/a&gt; to get it set up. Once set up, you will have the &lt;code&gt;packer&lt;/code&gt; command at your disposal. To build a new machine, all you need to is call:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;packer build my_machine.json&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The file my_machine.json can be the name of any json file and contains all the information Packer needs to setup your machine. The configuration json has three major sections: variables, builders, and provisioners. Variables are simply key value pairs that you can reference later in the builders and provisioners sections.&lt;/p&gt;
&lt;h3 id=&#34;the-builder-configuration&#34;&gt;The Builder Configuration&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://web.archive.org/web/20160318014945/https://www.packer.io/docs/templates/builders.html&#34;&gt;Builders&lt;/a&gt; takes an array of JSON objects that specify different ways to build your machines. You can think of them as instructions on how to get your machine setup and running. For example, to get a machine up and running you need to create a machine, install an operating system (OS) and create a user so that you can login to the machine. There are many different types of builders, but for the example here, I’ll just use the &lt;code&gt;vmware-iso&lt;/code&gt; machine type. Here’s a working JSON configuration file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;variables&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;ssh_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;mikefarmer&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;ssh_pass&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;mikefarmer&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;hostname&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;packer-test&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;builders&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;vmware-iso&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;iso_url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;os/ubuntu-12.04.4-server-amd64.iso&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;iso_checksum&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;e83adb9af4ec0a039e6a5c6e145a34de&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;iso_checksum_type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;md5&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;ssh_username&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;{{user `ssh_name`}}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;ssh_password&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;{{user `ssh_pass`}}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;ssh_wait_timeout&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;20m&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;http_directory&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;preseeds&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;http_port_min&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;9001&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;http_port_max&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;9001&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;shutdown_command&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;echo {{user `ssh_pass`}} | sudo -S shutdown -P now&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#b06;font-weight:bold&#34;&gt;&amp;#34;boot_command&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&amp;lt;esc&amp;gt;&amp;lt;esc&amp;gt;&amp;lt;enter&amp;gt;&amp;lt;wait&amp;gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;/install/vmlinuz noapic &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/precise_preseed.cfg &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;debian-installer=en_US auto locale=en_US kbd-chooser/method=us &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;hostname={{user `hostname`}} &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;fb=false debconf/frontend=noninteractive &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;keyboard-configuration/variant=USA console-setup/ask_detect=false &amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;initrd=/install/initrd.gz -- &amp;lt;enter&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href=&#34;https://web.archive.org/web/20160318014945/https://www.packer.io/docs/templates/builders.html&#34;&gt;documentation&lt;/a&gt; for these settings is really good but I want to point out a few things that weren’t immediately clear. Some of these pertain mostly to the vmware-iso builder type, but I believe they are worth pointing out because some of them apply to other builder types as well.&lt;/p&gt;
&lt;p&gt;First, the &lt;code&gt;iso_url&lt;/code&gt; setting can be either an absolute path, a relative path, or a fully qualified url. The relative path is relative to the directory where you run the &lt;code&gt;packer&lt;/code&gt; command. So here, when I run &lt;code&gt;packer&lt;/code&gt;, I need to make sure that I do so from a directory that has an os subdirectory with the ubuntu iso located therein.&lt;/p&gt;
&lt;p&gt;Next, once the ISO is downloaded, Packer will automatically start up your VMWare client and boot the virtual machine. Immediately after that, Packer will start up a &lt;a href=&#34;https://en.wikipedia.org/wiki/Virtual_Network_Computing&#34;&gt;VNC client and server&lt;/a&gt; along with a mini web server to provide information for your machine. The &lt;code&gt;http_port_min&lt;/code&gt; and &lt;code&gt;http_port_max&lt;/code&gt; specify which ports to use for the VNC clients. Setting them to the same will allocate just that port for it to use. The &lt;code&gt;http_directory&lt;/code&gt; setting provides the name of a local directory to use for the mini web server as the document root. This is important for providing your VM with a preseed file, more about the preseed file will be discussed below.&lt;/p&gt;
&lt;p&gt;Since we are using Ubuntu as our main machine, we will need to use sudo to send the shutdown command. The &lt;code&gt;shutdown_command&lt;/code&gt; setting is used to gracefully shut down the machine at the conclusion of the run and provisioning of the machine.&lt;/p&gt;
&lt;h3 id=&#34;installing-your-os&#34;&gt;Installing your OS&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;boot_command&lt;/code&gt; is a series of keystrokes that you can send to the machine via VNC. If you have set up a Linux machine from scratch you know that you have to enter in a bunch of information to the machine about how to set it up for the first time such as time zone, keyboard layout, how to partition the hard drive, host name, etc. All these keystrokes needed to set up your machine can be used here.&lt;/p&gt;
&lt;p&gt;But if you think about it, that’s a ton of keystrokes and this command could get quite long. A better way to approach this is to use a preseed file. A &lt;a href=&#34;https://web.archive.org/web/20210518144703/https://help.ubuntu.com/lts/installation-guide/s390x/apb.html&#34;&gt;preseed.cfg&lt;/a&gt; file contains the same information you enter when you setup a machine for the first time. This isn’t something provided by Packer, but it is provided by the operating system to automatically provision machines. For Ubuntu, a preseed file is used like so:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When you boot from the startup media (in this case an ISO image), you can choose the location of the preseed file via a URL.&lt;/li&gt;
&lt;li&gt;The preseed file is uploaded into memory and the configuration is read.&lt;/li&gt;
&lt;li&gt;The installation process begins using information from the preseed file to enter the values where the user would normally enter them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So how do we get the preseed file up to the machine? Remember that little web server that Packer sets up? Well, the IP address and port is made available to the virtual machine when it boots from the ISO. The following line tells the OS where to find the web server and the configuration file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/precise_preseed.cfg&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Strings in Packer can be interpolated using a simple template format similar to &lt;a href=&#34;https://mustache.github.io/&#34;&gt;mustache&lt;/a&gt;. The double curly braces tell Packer to insert a variable here instead of text. The HTTPIP and HTTPPort variables are made available by Packer to the template.&lt;/p&gt;
&lt;p&gt;One more important note about the preseed file: You need to make sure that the settings for the username and password are the same as listed in your variables section so that you can login to the machine once it is built. Where do you get a preseed file? I found &lt;a href=&#34;https://kappataumu.com/articles/creating-an-Ubuntu-VM-with-packer.html&#34;&gt;one on a blog titled Packer in 10 Minutes&lt;/a&gt; by &lt;a href=&#34;https://twitter.com/kappataumu&#34;&gt;@kappataumu&lt;/a&gt;. I only had to modify a few settings that were specific to my setup.&lt;/p&gt;
&lt;p&gt;Remember that &lt;code&gt;http_directory&lt;/code&gt; mentioned above? Well, that directory needs to include your preseed file. I’ve named mine &lt;code&gt;precise_preseed.cfg&lt;/code&gt; for Ubuntu 12.04 Precise Pangolin.&lt;/p&gt;
&lt;p&gt;Next up is provisioning but that is such a big topic by itself that I’ll move that into a separate blog post. The config file above will work as-is and once run it should setup a basic Ubuntu server for you. Go ahead and give it a try and let me know in the comments how it worked out for you.&lt;/p&gt;
&lt;h3 id=&#34;super-powers&#34;&gt;Super Powers&lt;/h3&gt;
&lt;p&gt;I said that Packer has 3 primary purposes earlier. Well, I lied.&lt;/p&gt;
&lt;p&gt;Packer’s superpower is that it can perform those 3 purposes over any number of machines, whether virtual, hosted, or otherwise in parallel. Supported machines are currently:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Amazon EC2 (AMI)&lt;/li&gt;
&lt;li&gt;DigitalOcean&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Google Compute Engine&lt;/li&gt;
&lt;li&gt;OpenStack&lt;/li&gt;
&lt;li&gt;QEMU&lt;/li&gt;
&lt;li&gt;VirtualBox&lt;/li&gt;
&lt;li&gt;VMware&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Consider for a moment that you can now automatically setup and provision multiple machines with the same environment using a single command. Now you are seeing the power of Packer.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Mobile Emulation in Chrome DevTools</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/01/mobile-emulation-in-chrome-devtools/"/>
      <id>https://www.endpointdev.com/blog/2014/01/mobile-emulation-in-chrome-devtools/</id>
      <published>2014-01-24T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;p&gt;I have been doing some mobile development lately and wanted to share the new Mobile Emulation feature in Chrome Canary with y’all. &lt;a href=&#34;https://www.google.ca/intl/en/chrome/browser/canary.html&#34;&gt;Chrome Canary&lt;/a&gt; is a development build of Chrome which gets updated daily and gives you the chance to use the latest and greatest features in Chrome. I’ve been using it as my primary browser for the past year or so and it’s been fairly stable. What’s great is that you can run Chrome Canary side-by-side with the stable release version of Chrome. For the odd time I do have issues with stability etc., I can just use the latest stable Chrome and be on my way. If you need more convincing, Paul Irish’s &lt;a href=&#34;http://www.paulirish.com/2012/chrome-canary-for-developers/&#34;&gt;Chrome Canary for Developers&lt;/a&gt; post might be helpful.&lt;/p&gt;
&lt;p&gt;I should mention that Chrome Canary is only available for OS X and Windows at this point. I tested &lt;a href=&#34;http://www.chromium.org/getting-involved/dev-channel#TOC-Linux&#34;&gt;Dev channel Chromium&lt;/a&gt; on Ubuntu 13.10 this afternoon and the new mobile emulation stuff is not ready there yet. It should not be long though.&lt;/p&gt;
&lt;h3 id=&#34;mobile-emulation-in-chrome-dev-tools&#34;&gt;Mobile Emulation in Chrome Dev Tools&lt;/h3&gt;
&lt;img alt=&#34;Mobile emulation chrome canary&#34; border=&#34;0&#34; height=&#34;334&#34; src=&#34;/blog/2014/01/mobile-emulation-in-chrome-devtools/image-0.png&#34; title=&#34;mobile-emulation-chrome-canary.png&#34; width=&#34;559&#34;/&gt; 
&lt;p&gt;Once enabled, the Emulation panel shows up in the Dev Tools console drawer. It gives you the option of emulating a variety devices (many are listed in the drop-down) and you also have the ability to fine tuning the settings à la carte. If you choose to emulate the touchscreen interface the mouse cursor will change and operate like a touch interface. Shift+drag allows you to pinch and zoom. There are some cool features for debugging and inspecting touch events as well.&lt;/p&gt;
&lt;h3 id=&#34;learning-more&#34;&gt;Learning More&lt;/h3&gt;
&lt;p&gt;If you would like to learn more, be sure to check out the &lt;a href=&#34;https://developers.google.com/chrome-developer-tools/docs/mobile-emulation&#34;&gt;Mobile emulation documentation&lt;/a&gt; at the Chrome DevTools docs site.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Copy Data Between MySQL Databases with Sequel Pro</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2014/01/copy-data-between-mysql-databases-with/"/>
      <id>https://www.endpointdev.com/blog/2014/01/copy-data-between-mysql-databases-with/</id>
      <published>2014-01-10T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;sequel-pro&#34;&gt;Sequel Pro&lt;/h3&gt;
&lt;img alt=&#34;Sequel pro&#34; border=&#34;0&#34; height=&#34;350&#34; src=&#34;/blog/2014/01/copy-data-between-mysql-databases-with/image-0.png&#34; style=&#34;display:block&#34; title=&#34;sequel-pro.png&#34; width=&#34;450&#34;/&gt;
&lt;p&gt;I often use &lt;a href=&#34;https://www.sequelpro.com/&#34;&gt;Sequel Pro&lt;/a&gt; when I’m getting up to speed on the data model for a project or when I just want to debug in a more visual way than with the mysql command-line client. It’s a free OS X application that lets you inspect and manage MySQL databases. I also find it very useful for making small changes to the data while I develop and test web apps.&lt;/p&gt;
&lt;h3 id=&#34;quickly-copy-data-between-databases&#34;&gt;Quickly Copy Data Between Databases&lt;/h3&gt;
&lt;p&gt;I recently needed a way to copy a few dozen records from one &lt;a href=&#34;http://www.devcamps.org/&#34;&gt;camp&lt;/a&gt; to another. I tried using the &lt;a href=&#34;https://dev.mysql.com/doc/refman/5.7/en/select-into.html&#34;&gt;&amp;ldquo;SELECT&amp;hellip;INTO OUTFILE&amp;rdquo;&lt;/a&gt; method but ran into a permissions issue with that approach. Using &lt;a href=&#34;https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html&#34;&gt;mysqldump&lt;/a&gt; was another option but that seemed like overkill in this case—​I only needed to copy a few records from a single table. At this point I found a really neat and helpful feature in Sequel Pro: Copy as SQL INSERT&lt;/p&gt;
&lt;img alt=&#34;Copy as sql insert&#34; border=&#34;0&#34; height=&#34;407&#34; src=&#34;/blog/2014/01/copy-data-between-mysql-databases-with/image-1.png&#34; title=&#34;copy-as-sql-insert.png&#34; width=&#34;562&#34;/&gt;
&lt;p&gt;I simply selected the records I wanted to copy and used the “Copy as SQL INSERT” feature. The SQL insert statement I needed was now copied to the system clipboard and easily copied over to the other camp and imported via the mysql command-line client.&lt;/p&gt;
&lt;h3 id=&#34;bundles&#34;&gt;Bundles&lt;/h3&gt;
&lt;p&gt;The Sequel Pro website describes &lt;a href=&#34;https://www.sequelpro.com/bundles&#34;&gt;Bundles&lt;/a&gt; which extend the functionality in various ways—​including copying data as JSON. Very handy stuff. Many thanks to the &lt;a href=&#34;https://web.archive.org/web/20140208071143/http://northofthree.com/&#34;&gt;developers&lt;/a&gt; of this fine software. If you’re on OS X, be sure to give it a try.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Adventures with using Ruby 2.0 and libreadline</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2013/05/adventures-with-using-ruby-20-and/"/>
      <id>https://www.endpointdev.com/blog/2013/05/adventures-with-using-ruby-20-and/</id>
      <published>2013-05-17T00:00:00+00:00</published>
      <author>
        <name>Kamil Ciemniewski</name>
      </author>
      <content type="html">
        &lt;p&gt;I was asked to develop a prototype app for one of our clients lately. The basis for this app was an old Rails app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rails 3.2.8&lt;/li&gt;
&lt;li&gt;RailsAdmin&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;rbenv + ruby-build&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wanted to upgrade the stack to work with latest toys all cool kids are so thrilled about. I also didn’t have Rails console facility at my disposal since the Ruby version installed on the development machine hadn’t been compiled against libreadline.&lt;/p&gt;
&lt;p&gt;Not having root or sudo access on the machine I embarked on a sligthly hacky journey to make myself a better working environment.&lt;/p&gt;
&lt;h3 id=&#34;ruby-20&#34;&gt;Ruby 2.0&lt;/h3&gt;
&lt;p&gt;After reading Mike Farmer’s &lt;a href=&#34;/blog/2013/04/today-first-speaker-at-mwrc-is-one-and/&#34;&gt;blog post&lt;/a&gt; about Ruby 2.0 and tons of other material about it on the Internet, I wanted to get a feeling of how faster &amp;amp; greater the new Ruby is. It’s always great also to stay up-to-date with latest technologies. It’s great for me as a developer, and more importantly—​it’s great for our clients.&lt;/p&gt;
&lt;h3 id=&#34;importance-of-libreadline-in-development-with-ruby&#34;&gt;Importance of libreadline in development with Ruby&lt;/h3&gt;
&lt;p&gt;To be productive developing any Rails-based application, we have to have Rails-console available at any moment. It serves a multitude of purposes. It’s also a great scratch-pad when developing methods.&lt;/p&gt;
&lt;p&gt;While you don’t need your Ruby to support libreadline for basic uses of &lt;strong&gt;irb&lt;/strong&gt;, you need it when using with Rails.&lt;/p&gt;
&lt;h3 id=&#34;installing-ruby-200-with-rbenv-ruby-build&#34;&gt;Installing Ruby 2.0.0 with rbenv (ruby-build)&lt;/h3&gt;
&lt;p&gt;If you’ve installed ruby-build some time ago, chances are that you need to update it in order to be able to install latest build of Ruby 2.0.0&lt;/p&gt;
&lt;p&gt;To do it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;cd&lt;/span&gt; ~/.rbenv/plugins/ruby-build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git pull&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And you should be able now to have available latest Ruby build to install:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rbenv install 2.0.0-p195&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you want to install Ruby compiled with support for libreadline, you have to have it installed in your system &lt;strong&gt;before&lt;/strong&gt; compiling the build with &lt;em&gt;rbenv install&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you have access to root or sudo on your system, the easiest way is to e. g:&lt;/p&gt;
&lt;p&gt;on Debian-related Linuxes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apt-get install libreadline-dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;or on Fedora:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;yum install readline-devel&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;installing-libreadline-from-sources&#34;&gt;Installing libreadline from sources&lt;/h3&gt;
&lt;p&gt;In my case—​I had to download sources and compile them myself. Luckily the system had all needed essential packages installed for building it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;ftp://ftp.cwru.edu/pub/bash/readline-6.2.tar.gz&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tar xvf readline-6.2.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#038&#34;&gt;cd&lt;/span&gt; readline-6.2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./configure --prefix=/home/kamil/libs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I had to specify &lt;em&gt;–prefix&lt;/em&gt; option pointing at the path where I wanted the libreadline library to be installed after compilation.&lt;/p&gt;
&lt;p&gt;Then, I was able to actually build Ruby with readline support “on”:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#369&#34;&gt;CONFIGURE_OPTS&lt;/span&gt;=&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;--with-readline-dir=/home/kamil/libs&amp;#34;&lt;/span&gt; rbenv install 2.0.0-p195&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Notice:&lt;/strong&gt; I was making myself a development environment and compiling from sources was my last resort. It is &lt;strong&gt;not&lt;/strong&gt; a good practice for production environments.&lt;/p&gt;
&lt;p&gt;Last thing I needed to do was to get rb-readline working with the project I was working on.&lt;/p&gt;
&lt;p&gt;It turnes out that latest rb-readline doesn’t play well with latest Ruby. Also, when using Ruby 2.0.0 one have to explicitely specify it in the Gemfile, or else it won’t be loaded for the console.&lt;/p&gt;
&lt;p&gt;Gemfile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gem &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;rb-readline&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;~&amp;gt; 0.4.2&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&#34;this-still-isnt-perfect&#34;&gt;This still isn’t perfect&lt;/h3&gt;
&lt;p&gt;While this setup works, it won’t let you use arrow keys. The irb process crashes quickly after even first try to navigate through the text.&lt;/p&gt;
&lt;p&gt;For some reason, after upgrading Ruby, the RailsAdmin stylesheets stopped working. I noticed that they are being served with comments which should be replaced by other stylesheets like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;/* ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;*= require_self
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;*= require_tree .
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888&#34;&gt;*/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I had to update Rails version in the Gemfile to have my admin back:&lt;/p&gt;
&lt;p&gt;Gemfile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gem &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;rails&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;3.2.13&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Console:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bundle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Last thing I wanted to do, was to try if I could upgrade Rails even further and have a working Rails4 setup. This was impossible unfortunately since RailsAdmin isn’t yet compatible with it &lt;a href=&#34;https://github.com/sferik/rails_admin/issues/1443&#34;&gt;as stated here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I conclude that latest Ruby is quite usable right now. If you don’t mind the quirks with the readline—​you’re pretty safe to upgrade. This assumes though that your app doesn’t use any incompatible elements.&lt;/p&gt;
&lt;p&gt;The main Ruby site describes them like so:&lt;/p&gt;
&lt;p&gt;There are five notable incompatibilities we know of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The default encoding for ruby scripts is now UTF-8 [&lt;a href=&#34;https://bugs.ruby-lang.org/issues/6679&#34;&gt;#6679&lt;/a&gt;]. Some people report that it affects existing programs, such as some benchmark programs becoming very slow [ruby-dev:46547].&lt;/li&gt;
&lt;li&gt;Iconv was removed, which had already been deprecated when M17N was introduced in ruby 1.9. Use String#encode, etc. instead.&lt;/li&gt;
&lt;li&gt;There is ABI breakage [ruby-core:48984]. We think that normal users can/should just reinstall extension libraries. You should be aware: DO NOT COPY .so OR .bundle FILES FROM 1.9.&lt;/li&gt;
&lt;li&gt;#lines, #chars, #codepoints, #bytes now returns an Array instead of an Enumerator [&lt;a href=&#34;https://bugs.ruby-lang.org/issues/6670&#34;&gt;#6670&lt;/a&gt;]. This change allows you to avoid the common idiom “lines.to_a”. Use #each_line, etc. to get an Enumerator.&lt;/li&gt;
&lt;li&gt;Object#inspect does always return a string like &lt;code&gt;#&amp;lt;ClassName:0x…&amp;gt;&lt;/code&gt; instead of delegating to #to_s. [&lt;a href=&#34;https://bugs.ruby-lang.org/issues/2152&#34;&gt;#2152&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;There are some comparatively small incompatibilities. [ruby-core:49119]&lt;/li&gt;
&lt;/ul&gt;

      </content>
    </entry>
  
    <entry>
      <title>Test Web Sites with Internet Explorer for Free</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2012/09/test-web-sites-with-internet-explorer/"/>
      <id>https://www.endpointdev.com/blog/2012/09/test-web-sites-with-internet-explorer/</id>
      <published>2012-09-26T00:00:00+00:00</published>
      <author>
        <name>Greg Davidson</name>
      </author>
      <content type="html">
        &lt;h3 id=&#34;browser-testing&#34;&gt;Browser Testing&lt;/h3&gt;
&lt;p&gt;While many Web Developers prefer to build sites and web applications with browsers like &lt;a href=&#34;https://www.google.com/intl/en/chrome/browser/&#34;&gt;Chrome&lt;/a&gt; or &lt;a href=&#34;http://getfirefox.com&#34;&gt;Firefox&lt;/a&gt; it&amp;rsquo;s important for us to keep an eye on the &lt;a href=&#34;http://marketshare.hitslink.com/browser-market-share.aspx?qprid=0&amp;amp;qpcustomd=0&amp;amp;qpcustomc=&#34;&gt;browser market share&lt;/a&gt; for &lt;strong&gt;all&lt;/strong&gt; web users. &lt;a href=&#34;http://windows.microsoft.com/en-US/internet-explorer/products/ie/home&#34;&gt;Internet Explorer&lt;/a&gt; (IE) still owns a large piece of this pie and because of this, it is important to test sites and applications to ensure they work properly when viewed in IE. This poses a potential problem for developers who do not use Windows.&lt;/p&gt;
&lt;p&gt;Although I use OS X on my desktop, I have Windows virtual machines with IE 6,7,8,9 and 10 installed. I also have a Linux virtual machine running Ubuntu so I can check out Chrome/Chromium and Firefox on that platform. In the past I had tried solutions like &lt;a href=&#34;http://tredosoft.com/Multiple_IE&#34;&gt;MultipleIEs&lt;/a&gt; but wasn&amp;rsquo;t satisfied with them. In my experience I&amp;rsquo;ve found that the best way to see what users are seeing is to have a virtual machine running the same software they are.&lt;/p&gt;
&lt;p&gt;I did some IE8 testing for a colleague a short time ago and suggested she should give VirtualBox a shot. Her response was &amp;ldquo;You should write a blog post about that!&amp;rdquo;. So here we are.&lt;/p&gt;
&lt;h3 id=&#34;free-tools&#34;&gt;Free Tools&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://www.virtualbox.org/&#34;&gt;VirtualBox&lt;/a&gt; is a free virtualization application similar to &lt;a href=&#34;http://www.parallels.com/&#34;&gt;Parallels&lt;/a&gt; or &lt;a href=&#34;http://www.vmware.com/&#34;&gt;VMWare&lt;/a&gt;. These applications aim to solve this problem by allowing us to run different &amp;ldquo;guest&amp;rdquo; operating systems on the &amp;ldquo;host&amp;rdquo; operating system of our choice. For example, I run several versions of IE and Windows on my computer which is running OS X.&lt;/p&gt;
&lt;p&gt;Microsoft have begun in recent years to release Virtual PC (VPC) images for free to enable Web Developers to test their sites and applications with various versions of Internet Explorer. The most recent images were released on July 30, 2012 and you can check them out &lt;a href=&#34;http://www.microsoft.com/en-us/download/details.aspx?id=11575&#34;&gt;here&lt;/a&gt;. Although these images are created to run on Microsoft&amp;rsquo;s &lt;a href=&#34;http://www.microsoft.com/windows/virtual-pc/&#34;&gt;Virtual PC&lt;/a&gt; application, with a little bit of effort we can also use them on Linux, OS X or Windows via VirtualBox.&lt;/p&gt;
&lt;p&gt;For our purposes, we will be building a Windows 7 virtual machine running Internet Explorer 8. However, there are several images available with various Windows OS and Internet Explorer version combinations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows 7 / IE8&lt;/li&gt;
&lt;li&gt;Windows 7 / IE9&lt;/li&gt;
&lt;li&gt;Windows Vista / IE7&lt;/li&gt;
&lt;li&gt;Windows XP / IE6&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There will likely be some differences creating virtual machines for the various images but the process will be similar to what we&amp;rsquo;ll document here for Windows 7 / IE.&lt;/p&gt;
&lt;h3 id=&#34;linux-and-os-x-users&#34;&gt;Linux and OS X Users&lt;/h3&gt;
&lt;p&gt;In researching this article I came across a very helpful project on GitHub. The &lt;a href=&#34;https://github.com/xdissent/ievms#readme&#34;&gt;ievms project&lt;/a&gt; by &lt;a href=&#34;https://github.com/xdissent&#34;&gt;xdissent&lt;/a&gt; is a bash script that automates this process. I was able to run the script and run my newly created Windows 7 / IE virtual machine shortly afterward.&lt;/p&gt;
&lt;h3 id=&#34;requirements&#34;&gt;Requirements&lt;/h3&gt;
&lt;p&gt;To start we&amp;rsquo;ll need to download and install VirtualBox. Be sure you have the most recent version available as it gets updated quite often. We&amp;rsquo;ll also need to install the VirtualBox Extension Pack. Both are available on the &lt;a href=&#34;https://www.virtualbox.org/wiki/Downloads&#34;&gt;VirtualBox Downloads page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because the &lt;a href=&#34;http://www.microsoft.com/en-us/download/details.aspx?id=11575&#34;&gt;VPC images&lt;/a&gt; are quite large (~2.6GB in our case) they have been split up into several files. For the Windows 7 / IE8 image we&amp;rsquo;ll download the following files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://download.microsoft.com/download/B/7/2/B72085AE-0F04-4C6F-9182-BF1EE90F5273/Windows_7_IE8.part01.exe&#34;&gt;Windows 7 / IE8 - Part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://download.microsoft.com/download/B/7/2/B72085AE-0F04-4C6F-9182-BF1EE90F5273/Windows_7_IE8.part02.rar&#34;&gt;Windows 7 / IE8 - Part 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://download.microsoft.com/download/B/7/2/B72085AE-0F04-4C6F-9182-BF1EE90F5273/Windows_7_IE8.part03.rar&#34;&gt;Windows 7 / IE8 - Part 3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://download.microsoft.com/download/B/7/2/B72085AE-0F04-4C6F-9182-BF1EE90F5273/Windows_7_IE8.part04.rar&#34;&gt;Windows 7 / IE8 - Part 4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once the files have been extracted we have created our virtual machine the disk will take up close to 10 GB. Make sure you have enough disk space available. I run my virtual machines on an external USB hard drive which works well if your local hard drive is starved for space.&lt;/p&gt;
&lt;h3 id=&#34;extract-the-vpc-files&#34;&gt;Extract the VPC Files&lt;/h3&gt;
&lt;p&gt;Once you have all of the the VPC image files downloaded you&amp;rsquo;ll need to extract them:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Windows users&lt;/strong&gt;: double-click the Windows_7_IE8.part01.exe file&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linux / OS X users&lt;/strong&gt;: You will need to install unrar. I did so on OS X with Homebrew and there are packages available for Ubuntu as well.&lt;/p&gt;
&lt;p&gt;Once you have unrar installed, issue the following command in the directory containing all of the VPC image files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;unrar e -y Windows_7_IE8.part01.exe&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will extract the files and combine them into a single .vhd file. The -y flag tells unrar to say &amp;ldquo;yes&amp;rdquo; to the EULA from Microsoft so be aware of that.&lt;/p&gt;
&lt;h3 id=&#34;create-a-new-machine&#34;&gt;Create a new Machine&lt;/h3&gt;
&lt;p&gt;Once the .vhd file is ready we can create a new machine in VirtualBox. Start up VirtualBox and click the &amp;ldquo;New&amp;rdquo; button:&lt;/p&gt;
&lt;img alt=&#34;Vbox new&#34; border=&#34;0&#34; height=&#34;198&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-0.png&#34; title=&#34;vbox-new.png&#34; width=&#34;518&#34;/&gt; 
&lt;p&gt;Click &amp;ldquo;Continue&amp;rdquo; to proceed.&lt;/p&gt;
&lt;h3 id=&#34;vm-name-and-os-type&#34;&gt;VM Name and OS Type&lt;/h3&gt;
&lt;p&gt;We&amp;rsquo;ll enter a name (IE8 / Windows 7) and select &amp;ldquo;Microsoft&amp;rdquo; and &amp;ldquo;Windows 7&amp;rdquo; in the Operating System and Version drop-downs:&lt;/p&gt;
&lt;img alt=&#34;Vbox name and type&#34; border=&#34;0&#34; height=&#34;345&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-1.png&#34; title=&#34;vbox-name-and-type.png&#34; width=&#34;600&#34;/&gt;
&lt;p&gt;Click &amp;ldquo;Continue&amp;rdquo; to proceed.&lt;/p&gt;
&lt;h3 id=&#34;memory&#34;&gt;Memory&lt;/h3&gt;
&lt;p&gt;Specify how much memory (RAM) you&amp;rsquo;d like to allocate to the virtual machine. This really depends on how much you have available but it is best to go with the minimum at the very least: &lt;img alt=&#34;Vbox mem config&#34; border=&#34;0&#34; height=&#34;345&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-2.png&#34; title=&#34;vbox-mem-config.png&#34; width=&#34;600&#34;/&gt;&lt;/p&gt;
&lt;p&gt;Click &amp;ldquo;Continue&amp;rdquo; to proceed.&lt;/p&gt;
&lt;h3 id=&#34;disk&#34;&gt;Disk&lt;/h3&gt;
&lt;p&gt;Select the &amp;ldquo;Do not add a virtual hard drive&amp;rdquo; option.: &lt;img alt=&#34;Vbox do not add hdd 1&#34; border=&#34;0&#34; height=&#34;394&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-3.png&#34; title=&#34;vbox-do-not-add-hdd-1.png&#34; width=&#34;600&#34;/&gt;&lt;/p&gt;
&lt;p&gt;The reason we skip this for now is because we want to add the hard disk as an IDE drive. For some reason VirtualBox adds the disk as a SATA drive which causes the blue screen of death (BSOD) to appear when the virtual machine is booted up.&lt;/p&gt;
&lt;p&gt;Click &amp;ldquo;Continue&amp;rdquo; to proceed &lt;strong&gt;and&lt;/strong&gt; click &amp;ldquo;Continue&amp;rdquo; again when presented with the warning about not attaching a hard disk.&lt;/p&gt;
&lt;h3 id=&#34;review-settings-and-create-the-vm&#34;&gt;Review Settings and Create the VM&lt;/h3&gt;
&lt;p&gt;At this point you can review the settings you&amp;rsquo;ve made and click &amp;ldquo;Create&amp;rdquo; to complete the process:&lt;/p&gt;
&lt;img alt=&#34;Vbox review and create&#34; border=&#34;0&#34; height=&#34;369&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-4.png&#34; title=&#34;vbox-review-and-create.png&#34; width=&#34;600&#34;/&gt;
&lt;h3 id=&#34;configure-storage-settings&#34;&gt;Configure Storage Settings&lt;/h3&gt;
&lt;p&gt;Highlight your newly created virtual machine and click the &amp;ldquo;Settings&amp;rdquo; button. From there, click the &amp;ldquo;Storage&amp;rdquo; tab and add a hard disk to the IDE controller: &lt;img alt=&#34;Vbox storage add hd&#34; border=&#34;0&#34; height=&#34;509&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-5.png&#34; title=&#34;vbox-storage-add-hd.png&#34; width=&#34;600&#34;/&gt;&lt;/p&gt;
&lt;h3 id=&#34;absolute-pointing-device&#34;&gt;Absolute Pointing Device&lt;/h3&gt;
&lt;p&gt;In the Settings, click on the &amp;ldquo;System&amp;rdquo; tab and uncheck &amp;ldquo;Enable absolute pointing device&amp;rdquo;. I had to do this in order to to get the mouse working properly.&lt;/p&gt;
&lt;h3 id=&#34;start-it-up&#34;&gt;Start it Up&lt;/h3&gt;
&lt;p&gt;We&amp;rsquo;re almost there: next we need to start up the VM by clicking the &amp;ldquo;Start&amp;rdquo; button. You&amp;rsquo;ll see Administrator and IEUser accounts and the password for both is &amp;ldquo;Password1&amp;rdquo;. Log in as Administrator and check it out! It&amp;rsquo;s important to note when the virtual machine has the keyboard and mouse focus. When you click inside the virtual machine window, it will capture the input from your mouse and keyboard. To return focus back to your computer you will need to press the &amp;ldquo;host key&amp;rdquo; sequence on your computer:&lt;/p&gt;
&lt;img alt=&#34;Vbox host key&#34; border=&#34;0&#34; height=&#34;123&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-6.png&#34; title=&#34;vbox-host-key.png&#34; width=&#34;343&#34;/&gt;
&lt;p&gt;The &amp;ldquo;host-key&amp;rdquo; sequence can be configured in the VirtualBox preferences. On my computer, the host-key sequence is the left CTRL key (displayed as Left ^). When the arrow icon is illuminated, the guest computer – Windows 7 in this case, has the focus. When I press the left CTRL key on my computer the arrow icon goes tray to indicate focus has been returned to my computer.&lt;/p&gt;
&lt;h3 id=&#34;activation&#34;&gt;Activation&lt;/h3&gt;
&lt;p&gt;As soon as you log in you will be presented with the Windows Activation wizard. Follow the steps to activate this copy of Windows. Once that is complete you will be prompted to restart your computer. Go ahead and do that.&lt;/p&gt;
&lt;img alt=&#34;Vbox activate now&#34; border=&#34;0&#34; height=&#34;487&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-7.png&#34; title=&#34;vbox-activate-now.png&#34; width=&#34;600&#34;/&gt;
&lt;p&gt;The screen resolution in the virtual machine will be quite low at first — I believe 800x600 is the default. Don&amp;rsquo;t worry about this as it will be addressed in the next step.&lt;/p&gt;
&lt;h3 id=&#34;guest-additions&#34;&gt;Guest Additions&lt;/h3&gt;
&lt;p&gt;Log in as Administrator (Password1) and Install the VirtualBox Guest Additions. To do this,  navigate to Devices in the VirtualBox menu on your computer (the &amp;ldquo;host&amp;rdquo; machine&amp;quot;). Choose the menu option to &amp;ldquo;Install Guest Additions&amp;rdquo;. Each time you are prompted with the &amp;ldquo;Would you like to install&amp;hellip;&amp;rdquo; dialog, choose &amp;ldquo;Install&amp;rdquo;:&lt;/p&gt;
&lt;img alt=&#34;Vbox install guest additions&#34; border=&#34;0&#34; height=&#34;487&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-8.png&#34; title=&#34;vbox-install-guest-additions.png&#34; width=&#34;600&#34;/&gt;
&lt;p&gt;This will install some drivers optimized by VirtualBox which allow you to change the screen resolution, improve the interaction between your host computer and the Windows guest operating system. Once the install process is complete you will be prompted to restart your virtual machine once more.&lt;/p&gt;
&lt;h3 id=&#34;finished-product&#34;&gt;Finished Product&lt;/h3&gt;
&lt;p&gt;With Windows activated and the Guest Additions installed you should be able to log in to your very own Windows 7 / IE8 testing machine!&lt;/p&gt;
&lt;img alt=&#34;Vbox ie8 mr&#34; border=&#34;0&#34; height=&#34;476&#34; src=&#34;/blog/2012/09/test-web-sites-with-internet-explorer/image-9.png&#34; title=&#34;vbox-ie8-mr.png&#34; width=&#34;600&#34;/&gt;
&lt;p&gt;This free copy of Windows will operate for 30 days and the trial period can be extended twice by running the following at the command prompt:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;slmgr –rearm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Check out &lt;a href=&#34;http://www.microsoft.com/en-us/download/details.aspx?id=11575#overview&#34;&gt;the documentation&lt;/a&gt; at Microsoft for more details.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>GNU Screen &#43; SSH_AUTH_SOCK; my new approach</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2011/02/gnu-screen-sshauthsock-my-new-approach/"/>
      <id>https://www.endpointdev.com/blog/2011/02/gnu-screen-sshauthsock-my-new-approach/</id>
      <published>2011-02-23T00:00:00+00:00</published>
      <author>
        <name>David Christensen</name>
      </author>
      <content type="html">
        &lt;p&gt;Over the years, I’ve played around with several different methods of keeping my forwarded SSH-Agent authentication socket up-to-date in long-running screen sessions (referenced via the $SSH_AUTH_SOCK shell variable). The basic issue here is that Screen sees the process environment at the time it was initially launched, not that which exists when reattaching in a subsequent login session. This means that the $SSH_AUTH_SOCK variable as screen sees it will refer to a socket which no longer exists (as it was removed when you logged out after detaching on the initial login when starting screen).&lt;/p&gt;
&lt;p&gt;Some of my previous methods have included a hard-coded variable for the socket itself (downsides: if it’s a predictable name you’re potentially opening some security issues, plus if you open multiple sessions to the same account, you kill the latest socket), symlinking the latest $SSH_AUTH_SOCK to a hard-coded value on login (similar issues), dumping $SSH_AUTH_SOCK to a file, and aliasing ssh and scp to first source said file to populate the local window’s enviroment (doesn’t work in scripts, too much manual setup when adapting to a new system/environment, won’t work with any other subsystem not already explicitly handled, etc).&lt;/p&gt;
&lt;p&gt;Recently though, I’ve come up with a simple approach using screen’s -X option to execute a screen command outside of screen and just added the following to my .bashrc:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;screen -X setenv SSH_AUTH_SOCK &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#369&#34;&gt;$SSH_AUTH_SOCK&lt;/span&gt;&lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While not perfect, in my opinion this is a bit of an improvement for the following reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It’s dirt-simple. No complicated scripts to adjust/maintain, just a command that’s almost completely self-explanatory.&lt;/li&gt;
&lt;li&gt;It doesn’t kill the environment for existing screen windows, just adjusts the $SSH_AUTH_SOCK variable for new screen windows. This ends up matching my workflow almost every time, as unless a connection dies, I leave the screen window open indeterminately.&lt;/li&gt;
&lt;li&gt;If you have multiple sessions open to the same account (even if not running both in screen), you’re not stomping on your existing socket.&lt;/li&gt;
&lt;li&gt;Did I mention it’s dirt-simple?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are presumably a number of other environment variables that would be useful to propagate in this way. Any suggestions or alternate takes on this issue?&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Managing Perl environments with perlbrew</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2011/02/managing-perl-environments-with/"/>
      <id>https://www.endpointdev.com/blog/2011/02/managing-perl-environments-with/</id>
      <published>2011-02-21T00:00:00+00:00</published>
      <author>
        <name>Jason Dixon</name>
      </author>
      <content type="html">
        &lt;p&gt;As a Perl hobbyist, I’ve gotten used to the methodical evolution of Perl 5 over the years. Perl has always been a reliable language, not without its faults, but with a high level of flexibility in syntactical expression and even deployment options. Even neophytes quickly learn how to install their own Perl distribution and CPAN libraries in $HOME. But the process can become unwieldy, particularly if you want to test across a variety of Perl versions.&lt;/p&gt;
&lt;p&gt;To contrast, Ruby core development frequently experiences ABI breakages, even between minor releases. In spite of the wide adoption of Ruby as a Web development language (thanks to Ruby on Rails), Ruby developers are able to plod along unconcerned, where these incompatibilities would almost certainly lead to major bickering within the Perl or PHP communities. How do they do it? The &lt;a href=&#34;https://rvm.io/&#34;&gt;Ruby Version Manager&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ruby Version Manager (RVM) allows users to install Ruby and RubyGems within their own self-contained environment. This allows each user to install all (or only) the software that their particular application requires. Particularly for Ruby developers, this provides them with the flexibility to quickly test upgrades for regressions, ABI changes and enhancements without impacting system-wide stability. Thankfully a lot of the ideas in RVM have made their way over to the Perl landscape, in the form of &lt;a href=&#34;https://github.com/gugod/App-perlbrew&#34;&gt;perlbrew&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Perlbrew offers many of the same features found in RVM for Ruby. It’s easy to install. It isolates different Perl versions and CPAN installations in your $HOME and helps you switch between them. It automates your environment setup and teardown. And most importantly, using perlbrew means not having to clutter your default system Perl with application-specific CPAN dependencies.&lt;/p&gt;
&lt;p&gt;Getting started with perlbrew couldn’t be easier. A quick one-liner is all it takes to install perlbrew in your home directory.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ curl -L http://xrl.us/perlbrewinstall | bash&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you need to install perlbrew somewhere other than your home directory, just download the installer and pass it the PERLBREW_ROOT environment variable.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ curl -LO http://xrl.us/perlbrew
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ chmod +x perlbrew
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ PERLBREW_ROOT=/mnt/perlbrew ./perlbrew install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Follow the instructions on screen and you’ll be ready to use perlbrew in no time. The perlbrew binary will be installed in ~/perl5/perlbrew/bin, so make sure to adjust your login $PATH accordingly.&lt;/p&gt;
&lt;p&gt;Once you’re done installing perlbrew there are a couple commands you’ll want to run before installing your own Perl versions or CPAN modules. The perlbrew init command is mandatory; this initializes your perlbrew directory. It can also be used later if you need to modify your PERLBREW_ROOT setting. The perlbrew mirror is optional (but recommended) to help you select a preferred CPAN mirror.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perlbrew init
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perlbrew mirror&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next comes the fun part. Start off by verifying the Perl version(s) that perlbrew sees.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perlbrew list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* /usr/bin/perl (5.10.1)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Install a newer version of Perl.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perlbrew install 5.12.3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now switch to the newer Perl.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perlbrew list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* /usr/bin/perl (5.10.1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perl-5.12.3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perlbrew switch perl-5.12.3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perlbrew list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/usr/bin/perl (5.10.1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* perl-5.12.3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perl -v
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;This is perl 5, version 12, subversion 3 (v5.12.3) built for x86_64-linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Copyright 1987-2010, Larry Wall
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Perl may be copied only under the terms of either the Artistic License or the
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GNU General Public License, which may be found in the Perl 5 source kit.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Complete documentation for Perl, including FAQ lists, should be found on
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;this system using “man perl” or “perldoc perl”. If you have access to the
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Internet, point your browser at http://www.perl.org/, the Perl Home Page.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, if you only want to test a different Perl version, try the perlbrew use command (note: this only works in bash and zsh). Unlike the switch command, use is only active for the current shell.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perlbrew use system
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ perlbrew list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* /usr/bin/perl (5.10.1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perl-5.12.3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A quick peek behind the curtain reveals much of the simplicity behind perlbrew.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ls -l ~/perl5/perlbrew/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total 2680
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r--  1 testy  users      408 Feb 10 23:58 Conf.pm
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x  2 testy  users      512 Feb 10 23:46 bin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x  4 testy  users      512 Feb 11 09:59 build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r--  1 testy  users  1333196 Feb 11 10:33 build.log
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x  2 testy  users      512 Feb 11 09:59 dists
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x  2 testy  users      512 Feb 10 23:47 etc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x  4 testy  users      512 Feb 11 10:32 perls
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ls -l ~/perl5/perlbrew/perls/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total 8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x  5 testy  users  512 Feb 11 00:38 perl-5.12.3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;drwxr-xr-x  5 testy  users  512 Feb 11 10:32 perl-5.13.6&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you’re a Perl developer, the &lt;a href=&#34;https://github.com/gugod/App-perlbrew&#34;&gt;perlbrew&lt;/a&gt; project may help alleviate a lot of the pain associated with team development or multi-tenant programming environments. Suddenly it becomes much easier to manage your own software requirements, resulting in faster development and testing cycles for you, and fewer headaches for your System Administrators.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Visit at DistribuTECH</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2011/02/visit-at-distributech/"/>
      <id>https://www.endpointdev.com/blog/2011/02/visit-at-distributech/</id>
      <published>2011-02-02T00:00:00+00:00</published>
      <author>
        <name>Ron Phipps</name>
      </author>
      <content type="html">
        &lt;p&gt;I had the chance to attend DistribuTECH in San Diego, CA this past week. DistribuTECH is billed as the utility industry’s leader in smart grid conference and exposition. End Point was present at the conference on behalf of Silver Spring Networks. Silver Spring Networks contracted with us to provide a Liquid Galaxy installation for their exhibit.&lt;/p&gt;
&lt;p&gt;The Liquid Galaxy did its job from what I could tell. The exhibit was consistently surrounded with conference goers both interested in listening and watching the tours that were being presented as well as wanting to see what the Liquid Galaxy was all about. This was the first time I had seen the Liquid Galaxy and was quite impressed with how well it worked. I saw many people moving their bodies in sync with what was being displayed on the screen, showing that they felt immersed while within the galaxy. One gentleman knelt down while attempting to look under a graph that was being presented on the screen. This same person had returned to the exhibit several times, bringing colleagues back each time to “show off” what he had found.&lt;/p&gt;
&lt;p&gt;I spent some time on the conference floor, checking out what was being displayed and seeing how others were getting the attention of the attendees. I could not find anything that compared to the Liquid Galaxy in both wow factor and usability. The fine folks at Silver Spring Networks also seemed impressed with the reaction they were receiving.&lt;/p&gt;
&lt;p&gt;One product that I found interesting while walking the floor was a large unit that would freeze itself at night, when power is less expensive, the draw on the grid is less, and it is cooler outside and then use the ice as a coolant to be pumped into the AC unit during the day resulting in a reduction of cost and energy usage to cool a building.&lt;/p&gt;
&lt;p&gt;I also took a look at the Silver Spring Networks products on display. One that interested me was their home portal that allowed customers that had Silver Spring smart meters installed by their utility to visit a web portal and view several things including their current usage and compare their usage to that of their neighbors. I can see how someone concerned with the environment could use this information to lessen their power usage.&lt;/p&gt;
&lt;p&gt;Keep an eye out here for a few blog posts from Adam on his experience with tour development for the Liquid Galaxy.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Debugging jQuery</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2010/09/debugging-jquery/"/>
      <id>https://www.endpointdev.com/blog/2010/09/debugging-jquery/</id>
      <published>2010-09-28T00:00:00+00:00</published>
      <author>
        <name>Ron Phipps</name>
      </author>
      <content type="html">
        &lt;p&gt;A recent reskin project for a client requires that we convert some of their old Prototype code to jQuery as well as create new jQuery code. I have not done much with converting Prototype to jQuery and I felt like my debugging tools for JavaScript were under par. So this morning I set out to find what was available for jQuery and I found this &lt;a href=&#34;https://msdn.microsoft.com/en-us/magazine/ee819093.aspx&#34;&gt;article&lt;/a&gt; on the subject.&lt;/p&gt;
&lt;p&gt;I’ve used Firebug for some time now, but was unaware of some of the supporting plugins that would certainly help with debugging JavaScript. Some of the plugins and methods found in the article that I found immediately helpful were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FireFinder&lt;/strong&gt;: Makes it quite easy to verify that the selector values in your code are correct and that the proper elements are returned. I was able to immediately pinpoint problems with my selectors and this brought to light why certain events were not firing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Firebug Console&lt;/strong&gt;: Using the console.log function allowed me to check values without littering my code with alert statements.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FireQuery&lt;/strong&gt;: At a glance this plugin for Firebug shows which elements have event handlers bound to them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Firebug Breakpoints&lt;/strong&gt;: Setting breakpoints and watch statements in your code makes it easier to see what is happening in the JavaScript code as it is executed instead of trying to figure out what happened after the code has run its course.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to the author of the article, Elijah Manor, for the in-depth information on debugging jQuery code.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Guidelines for Interchange site migrations</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2010/09/guidelines-for-interchange-site/"/>
      <id>https://www.endpointdev.com/blog/2010/09/guidelines-for-interchange-site/</id>
      <published>2010-09-03T00:00:00+00:00</published>
      <author>
        <name>Ron Phipps</name>
      </author>
      <content type="html">
        &lt;p&gt;I’m involved at End Point often with Interchange site migrations. These migrations can be due to a new client coming to us and needing hosting or migrating from one server to another within our own infrastructure.&lt;/p&gt;
&lt;p&gt;There are many different ways to do a migration, in the end though we need to hit on certain points to make sure that the migration goes smoothly. Below you will find steps which you can adapt for your specific migration.&lt;/p&gt;
&lt;p&gt;During the start of the migration it might be a good time to introduce git for source control. You can do this by creating the repository and cloning it to /home/account/live, setting up .gitignore files for logs, counter files, gdbm files. Then commit the changes back to the repo and you’ve now introduced source control without much effort, improving the ability to make changes to the site in the future. This is also helpful to document the changes you make to the code base along the way during the migration in case you need to merge changes from the current production site before completing the migration.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Export all of the gdbm databases to their text file equivalents on the production server&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Take a backup from production of the database, catalog, interchange server, htdocs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Setup an account&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create the database and user&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Restore the database, catalog, interchange server and htdocs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the paths in interchange/bin for each script to point at the new location&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grep the restored code for hard coded paths and update those paths to the new locations. Better yet move these paths out to a catalog_local.cfg where environment specific information can go.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grep the restored code for hard coded urls and use the [area] tag to generate the urls&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the urls in products/variable.txt to point at the test domain&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the sql settings in products/variable.txt to point at the new database using the new user&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remove the gdbm databases so they will be recreated on startup from the source text files&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install a local Perl if it’s not already installed (./configure -des will compile and install Perl locally)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Bundle::InterchangeKitchenSink&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install the DBD module for MySQL or PostgreSQL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Review the code base looking for use statements in custom code and Require module settings in interchange.cfg. Install the Perl modules found into the local Perl.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Setup a non ssl and ssl virtual host using a temporary domain. Configure the temporary domain to use the SSL certificate from the production domain.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Firewall or password protect the virtual host so it is not accessible to the public&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate a vlink using interchange/bin/compile and copy it into the cgi-bin directory and name it properly&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Startup the new Interchange&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Review error messages and resolve until Interchange will start properly&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test the site thoroughly, resolving issues as they appear. Make sure that checkout, charging credit cards, sending of emails, using the admin, etc all function.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Migrate any cron jobs running on the current production site, such as session expiration scripts&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Setup logrotation for the new logs that will be created&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verify that you have access to make DNS changes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set the TTL for the domain to a low value such as 5 minutes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Modify the new production site to respond to the production url, test by updating your hosts file to manually set the IP address of the domain&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Shutdown the new Interchange&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Restore a copy of the original backup for Interchange, the catalog and htdocs to /tmp on the production server&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Shutdown the production Interchange, put up a maintenance note on the production site.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Take a backup of the production database and restore on the new server&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Diff the Interchange, catalog and htdocs directory between /tmp and the current production locations, making note of the files that have changed since we took the original copy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the files that have changed, making sure to merge with any changes we have made on the new production site. Making sure to copy over all .counter and .autonumber files to the new production site.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start Interchange on the new production server&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test the site thoroughly on the new production server, using the production url. Make sure that checkout with charging the credit card functions properly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Resolve any remaining issues found during the testing&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Setup the Interchange daemon to start at boot for this site in /etc/rc.d/rc.local or in cron using @reboot&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update DNS to point at the new production IP address&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the TTL of the domain to a longer value&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the site to the public by opening the firewall or removing the password protection&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Keep an eye on the error logs for any issues that might crop up&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will hopefully give you a solid guide for performing an Interchange site migration from one server to another and some of the things to watch out for that might cause issues during the migrations.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Why is my load average so high?</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2010/07/why-is-my-load-average-so-high/"/>
      <id>https://www.endpointdev.com/blog/2010/07/why-is-my-load-average-so-high/</id>
      <published>2010-07-15T00:00:00+00:00</published>
      <author>
        <name>Josh Tolley</name>
      </author>
      <content type="html">
        &lt;p&gt;One of the most common ways people notice there’s a problem with their server is when Nagios, or some other monitoring tool, starts complaining about a high load average. Unfortunately this complaint carries with it very little information about what might be causing the problem. But there are ways around that. On Linux, where I spend most of my time, the load average represents the average number of process in either the &amp;ldquo;run&amp;rdquo; or &amp;ldquo;uninterruptible sleep&amp;rdquo; states. This code snippet will display all such processes, including their process ID and parent process ID, current state, and the process command line:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#c00;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ps -eo pid,ppid,state,cmd |&lt;span style=&#34;color:#04d;background-color:#fff0f0&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#04d;background-color:#fff0f0&#34;&gt;&lt;/span&gt;    awk &lt;span style=&#34;color:#d20;background-color:#fff0f0&#34;&gt;&amp;#39;$3 ~ /[RD]/ { print $0 }&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Most of the time, this script has simply confirmed what I already anticipated, such as, &amp;ldquo;PostgreSQL is trying to service 20 times as many simultaneous queries as normal.&amp;rdquo; On occasion, however, it’s very useful, such as when it points out that a backup job is running far longer than normal, or when it finds lots of &amp;ldquo;[pdflush]&amp;rdquo; operations in process, indicating that the system was working overtime to write dirty pages to disk. I hope it can be similarly useful to others.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>dstat: better system resource monitoring</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2009/12/dstat/"/>
      <id>https://www.endpointdev.com/blog/2009/12/dstat/</id>
      <published>2009-12-19T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;I recently came across a useful tool I hadn’t heard of before: &lt;a href=&#34;http://dag.wiee.rs/home-made/dstat/&#34;&gt;dstat&lt;/a&gt;, by Dag Wieers (of DAG RPM-building fame). He describes it as “a versatile replacement for vmstat, iostat, netstat, nfsstat and ifstat.”&lt;/p&gt;
&lt;p&gt;The most immediate benefit I found is the collation of system resource monitoring output at each point in time, removing the need to look at output from multiple monitors. The coloring helps readability too:&lt;/p&gt;
&lt;p&gt;% dstat                                                                         &lt;/p&gt;
&lt;p&gt;&amp;mdash;-total-cpu-usage&amp;mdash;- -dsk/total- -net/total- &amp;mdash;paging&amp;ndash; &amp;mdash;system&amp;ndash;         &lt;/p&gt;
&lt;p&gt;usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw          &lt;/p&gt;
&lt;p&gt;  4   1  92   3   0   0|  56k   84k|   0     0 |  94B  188B|1264  1369          &lt;/p&gt;
&lt;p&gt;  3   7  43  44   1   1| 368k   11M| 151B  222B|   0   260k|1453  1565          &lt;/p&gt;
&lt;p&gt;  3   2  46  48   1   0| 432k 5784k|   0     0 |   0     0 |1421  1584          &lt;/p&gt;
&lt;p&gt;  2   2  47  49   0   0| 592k    0 |   0     0 |   0     0 |1513  1763          &lt;/p&gt;
&lt;p&gt;  6   2  44  49   1   0| 448k  248k|   0     0 |   0     0 |1398  1640          &lt;/p&gt;
&lt;p&gt;  8   4  41  45   3   0| 456k    0 | 135B  222B|   0     0 |1530  2102          &lt;/p&gt;
&lt;p&gt; 18   4  38  41   0   0| 408k  128k|   0    47B|   0     0 |1261  1977          &lt;/p&gt;
&lt;p&gt; 10   4  44  43   0   0| 728k  208k|   0     0 |   0     0 |1445  2203          &lt;/p&gt;
&lt;p&gt;  6   3  39  51   0   0| 648k  256k|3607B 4124B|   0     0 |1496  2180          &lt;/p&gt;
&lt;p&gt;  7   7  34  53   0   0|1088k    0 |1234B  582B|   0     0 |1465  2057          &lt;/p&gt;
&lt;p&gt; 14   8  28  49   0   0|2856k  104k|   0     0 |   0    52k|1610  2995          &lt;/p&gt;
&lt;p&gt;  6   6  43  45   0   0|1992k    0 |5964B 4836B|   0     0 |1493  2391          &lt;/p&gt;
&lt;p&gt;  9  14  34  44   0   0|2432k  112k|7854B  726B|   0     0 |1527  2190          &lt;/p&gt;
&lt;p&gt;  9  11  40  41   1   0|2680k    0 |1382B  972B|   0     0 |1550  2298          &lt;/p&gt;
&lt;p&gt;  5   4  68  22   0   0| 576k 1096k|  12k 4628B|   0     0 |1522  1731 ^C       &lt;/p&gt;
&lt;p&gt;(Textual screenshot by script of &lt;a href=&#34;https://github.com/karelzak/util-linux&#34;&gt;util-linux&lt;/a&gt; and Perl module &lt;a href=&#34;http://search.cpan.org/perldoc?HTML::FromANSI&#34;&gt;HTML::FromANSI&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;Its default one-line-per-timeslice output makes it good for collecting data samples over time, as opposed to full-screen top-like utilities such as &lt;a href=&#34;https://www.atoptool.nl/&#34;&gt;atop&lt;/a&gt;, which give much more detailed information at each snapshot, but don’t show history.&lt;/p&gt;
&lt;p&gt;Since dstat is a standard package available in RHEL/CentOS and Debian/Ubuntu, it is a reasonably easy add-on to get on various systems.&lt;/p&gt;
&lt;p&gt;dstat also allows plugins, and just in the most recent release last month were added new plugins “for showing NTP time, power usage, fan speed, remaining battery time, memcache hits and misses, process count, top process total and average latency, top process total and average CPU timeslice, and per disk utilization rates.”&lt;/p&gt;
&lt;p&gt;It sounds like it’ll grow even more useful over time and is worth keeping an eye on.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>GNU Screen: follow the leader</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2009/09/gnu-screen-follow-leader/"/>
      <id>https://www.endpointdev.com/blog/2009/09/gnu-screen-follow-leader/</id>
      <published>2009-09-24T00:00:00+00:00</published>
      <author>
        <name>Kiel Christofferson</name>
      </author>
      <content type="html">
        &lt;p&gt;First of all, if you’re not using &lt;a href=&#34;http://www.gnu.org/software/screen/&#34;&gt;GNU Screen&lt;/a&gt;, start now :).&lt;/p&gt;
&lt;p&gt;Years ago, &lt;a href=&#34;/team/jon-jensen/&#34;&gt;Jon&lt;/a&gt; and I spoke of submitting patches to implement some form of “follow the leader” (like the children’s game, but with a work-specific purpose) in GNU Screen. This was around the time he was patching screen to raise the hard-coded limit of 40 windows allowed within a given session, which might give an idea of how much screen gets used around here (a lot).&lt;/p&gt;
&lt;p&gt;The basic idea was that sometimes we just want to “watch” a co-worker’s process as they’re working on something within a shared screen session. Of course, they’re going to be switching between screen windows and if they forget to announce “I’ve switched to screen 13!” on the phone, then one might quickly become lost. What if the cooperative work session doesn’t include a phone call at all?&lt;/p&gt;
&lt;p&gt;To the rescue, Screen within Screen.&lt;/p&gt;
&lt;p&gt;Accidentally arriving at one screen session within another screen session is a pretty common “problem” for new screen users. However, creative use of two (or more) levels of nested screen during a shared session allows for a “poor man’s” follow the leader.&lt;/p&gt;
&lt;p&gt;If the escape sequence of the outermost screen is changed to something other than the default, then the default escape sequence will pass through and take effect on the inner screen. In this way, anyone attached to the outermost screen will be following whomever is controlling the inner screen session as they flip between windows, grep logs, launch editors and save my &lt;a href=&#34;http://www.lightlife.com/Vegan-Food-Vegetarian-Diet/Smart-Bacon.html&#34;&gt;vegan bacon&lt;/a&gt;! To “break away” from the co-working session, a user would simply use the chosen non-default escape sequence of the outermost screen to create a new window or disconnect entirely.&lt;/p&gt;
&lt;p&gt;Sound confusing? Give some of the following commands a try. You can always just close out all the windows of a screen session and eventually you’ll make it back to your original shell.&lt;/p&gt;
&lt;p&gt;Steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;start the outermost screen session (called “followme”) with a non-default escape sequence (pick one that suits you):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;screen -S followme -e ^ee&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;from within the “followme” session, start the inner screen where actual work will be performed:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;screen -S work&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;get friends and co-workers (logged-in as the same user) to connect to your “followme” screen:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;screen -x followme&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;work as normal using the &lt;strong&gt;default&lt;/strong&gt;: &lt;em&gt;CTRL-a&lt;/em&gt; sequences (which ought to affect the inner “work” session).&lt;/li&gt;
&lt;li&gt;to “break away” from the “work” session: &lt;em&gt;CTRL-e&lt;/em&gt; sequences (which ought to affect the outer “followme” session). For example, to disconnect from the shared session, one would type &lt;em&gt;CTRL-e d&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note: If those sharing the screen session are already acclimated to screen-within-screen, you can skip the non-default escape sequences entirely and use &lt;em&gt;CTRL-a a&lt;/em&gt; as the escape sequence (another &lt;em&gt;a&lt;/em&gt; for every level of screen-within-screen). This also happens to be your evasion route for accidental screen-within-screen moments.&lt;/p&gt;
&lt;p&gt;Remember that, by default, everyone who wants to share the screen must already be logged-in as the same user (without the use of sudo or su). There are methods of allowing shared screen access between users, but those are outside the scope of this post.&lt;/p&gt;
&lt;p&gt;Have fun!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Update: Note that tmux by default has every attached viewer follow whoever is driving, and there you have to do extra work to have separate control of windows. tmux was still new and not available in most production systems at the time this article was written.)&lt;/em&gt;&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>MTU tweak: a fix for upload pain</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2009/07/mtu-tweak-fix-for-upload-pain/"/>
      <id>https://www.endpointdev.com/blog/2009/07/mtu-tweak-fix-for-upload-pain/</id>
      <published>2009-07-11T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;While traveling and staying at &lt;a href=&#34;http://tyn.prague-hostels.cz/&#34;&gt;Hostel Tyn&lt;/a&gt; in Prague’s city center, I ran into a strange problem with my laptop on their wireless network.&lt;/p&gt;
&lt;p&gt;When many people were using the network (either on the hostel’s public computers or on the wireless network), sometimes things bogged down a bit. That wasn’t a big deal and required merely a little patience.&lt;/p&gt;
&lt;p&gt;But after a while I noticed that absolutely no “uploads” worked. Not via ssh, not via browser POST, nothing. They always hung. Even when only a file upload of 10 KB or so was involved. So I started to wonder what was going on.&lt;/p&gt;
&lt;p&gt;As I considered trying some kind of rate limiting via iptables, I remembered somewhere hearing that occasionally you can run into mismatched MTU settings between the Ethernet LAN you’re on and your operating system’s network settings.&lt;/p&gt;
&lt;p&gt;I checked my setup and saw something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ifconfig wlan0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wlan0     Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          inet addr:10.x.x.x  Bcast:10.x.x.x  Mask:255.255.255.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          inet6 addr: fe80::xxx:xxxx:xxxx:xxxx/64 Scope:Link
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          RX packets:1239 errors:0 dropped:0 overruns:0 frame:0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          TX packets:20 errors:0 dropped:0 overruns:0 carrier:0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          collisions:0 txqueuelen:1000
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          RX bytes:191529 (191.5 KB)  TX bytes:4543 (4.5 KB)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The MTU 1500 stood out as being worthy of tweaking. So I tried a completely unscientific change:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo ifconfig wlan0 mtu &lt;span style=&#34;color:#00d;font-weight:bold&#34;&gt;1400&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then tried the same HTTP POST that had been consistently failing, and poof! It worked fine. Every time.&lt;/p&gt;
&lt;p&gt;I think mostly likely something more than 1400 bytes would’ve been possible, perhaps just a few short of 1500. The number 1492 rings familiar. I’ll be old-fashioned and &lt;em&gt;not&lt;/em&gt; look it up on the web. But this 1400-byte MTU worked fine and solved the problem. To my delight.&lt;/p&gt;
&lt;p&gt;As an interesting aside, before making the change, I found one web application where uploads did work fine anyway: Google’s Picasa. I’m not sure why, but maybe it sliced &amp;amp; diced the upload stream into smaller chunks on its own? A mystery for another day.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>Operating system upgrades</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2009/05/operating-system-upgrades/"/>
      <id>https://www.endpointdev.com/blog/2009/05/operating-system-upgrades/</id>
      <published>2009-05-12T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;This won’t be earth-shattering news to anyone, I hope, but I’m pleased to report that two recent operating system upgrades went very well.&lt;/p&gt;
&lt;p&gt;I upgraded a laptop from Ubuntu 8.10 to 9.04, and it’s the smoothest I’ve ever had the process go. The only problem of any kind was that the package download process stalled on the last of 1700+ files downloaded, and I had to restart the upgrade, but all the cached files were still there and on reboot everything worked including my two-monitor setup, goofy laptop audio chipset, wireless networking, crypto filesystem, and everything else.&lt;/p&gt;
&lt;p&gt;I also upgraded an OpenBSD 4.3 server that is a firewall, NAT router, DHCP server, and DNS server, to OpenBSD 4.5. It was the first time I used the in-place upgrade with no special boot media and fetching packages over the network, as per &lt;a href=&#34;https://www.openbsd.org/faq/faq4.html#bsd.rd&#34;&gt;the bsd.rd instructions&lt;/a&gt;, and it went fine. Then the extra packages that were there before had to be upgraded separately as per the &lt;a href=&#34;https://www.openbsd.org/faq/faq15.html#PkgUpdate&#34;&gt;FAQ on pkg updates&lt;/a&gt;. I initially scripted some munging of pkg_info’s output, not realizing I could simply run pkg_add -u and it updates all packages.&lt;/p&gt;
&lt;p&gt;There was one hangup upgrading zsh, which I just removed and reinstalled. Everything else went fine, and all services worked fine after reboot.&lt;/p&gt;
&lt;p&gt;How pleasant.&lt;/p&gt;

      </content>
    </entry>
  
    <entry>
      <title>TLS Server Name Indication</title>
      <link rel="alternate" href="https://www.endpointdev.com/blog/2009/05/tls-server-name-indication/"/>
      <id>https://www.endpointdev.com/blog/2009/05/tls-server-name-indication/</id>
      <published>2009-05-08T00:00:00+00:00</published>
      <author>
        <name>Jon Jensen</name>
      </author>
      <content type="html">
        &lt;p&gt;I came across a few discussions of the TLS extension “Server Name Indication”, which would allow hosting more than one “secure” (https) website per IP address/TCP port combination. The best summary of the state of things is (surprise, surprise) the &lt;a href=&#34;https://en.wikipedia.org/wiki/Server_Name_Indication&#34;&gt;Wikipedia Server Name Indication article&lt;/a&gt;. There are more details about client and server software support for SNI in &lt;a href=&#34;https://web.archive.org/web/20100507090749/http://www.sigil.us/2008/11/sni-why-not/&#34;&gt;Zachary Schneider’s blog post&lt;/a&gt; and &lt;a href=&#34;https://daniel-lange.com/archives/2-Multiple-Apache-VHosts-on-the-same-IP-and-port.html&#34;&gt;Daniel Lange’s blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I don’t recall hearing about this before, but if I did I probably dismissed as being irrelevant at the time because there would’ve been almost no support in either clients or servers. But now that all major browsers on all operating systems support SNI &lt;strong&gt;except some on Windows XP&lt;/strong&gt; it may be worth keeping an eye on this.&lt;/p&gt;
&lt;p&gt;Yes, IE on Windows XP is still a huge contingent and thus a huge hurdle. But maybe Microsoft will backport SNI support to XP. Even if just for IE 7 and later. Or maybe we’ll have to wait a few more years till the next Windows operating system (hopefully) displaces XP. Here’s a case where the low popularity of Vista (which supports SNI) is hurting the rest of us.&lt;/p&gt;
&lt;p&gt;I’m really looking forward to the flexibility of name-based virtual hosting for https that we’ve had for 10+ years with plain http. It could really change the setup and ongoing infrastructure costs for secure websites, such as ecommerce sites.&lt;/p&gt;

      </content>
    </entry>
  
</feed>
