<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <generator uri="https://gohugo.io/" version="0.169.0">Hugo</generator>
    <title>Thoughts from the DevOps world</title>
            <link href="https://www.brainware.ro/" rel="alternate" type="text/html" title="html" />
            <link href="https://www.brainware.ro/index.xml" rel="alternate" type="application/rss+xml" title="rss" />
    <updated>2026-11-11T13:07:43+00:00</updated>
    <id>https://www.brainware.ro/</id>
        <entry>
            <title>Down the Rabbit Hole: Modern Image Formats</title>
            <link href="https://www.brainware.ro/posts/modern_image_formats/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/modern_image_formats/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2025-07-20T15:42:34+00:00</published>
            <updated>2025-07-20T15:42:34+00:00</updated>
            <content type="html">
                &lt;p&gt;While browsing articles about website optimization, I came across a tip to use a modern image format like WebP. The idea is that WebP files are smaller, so pages load faster. At the time, I didn’t really understand why that would work, so I started digging into it, and I ended up going down a rabbit hole.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-introduction&#34;
    &gt;
        1. Introduction
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/modern_image_formats/#1-introduction&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Introduction&#34; aria-label=&#34;Anchor 1. Introduction&#34; href=&#34;#1-introduction&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Some background: the well-known image formats JPEG, PNG and GIF have been around for 25 years or more. They were designed when storage and processing power were expensive, so each one was built for a specific purpose. JPEG became the standard for everyday photos, PNG for icons and computer-generated images, and GIF for short animations (once the patent on its compression algorithm expired in the early 2000s).&lt;/p&gt;
&lt;p&gt;By the early 2010s, computing had become cheap, and older ideas for better image compression finally became practical. New standards were also introduced, mostly without people noticing. Engineers also began to use hardware built into phones and other portable devices to speed up encoding and decoding of images and video. The result was a confusing patchwork of new image and video formats.&lt;/p&gt;
&lt;p&gt;In the early 2020s, browsers chose which of these formats to support and which to ignore for the time being. Operating systems and image software, meanwhile, supported whatever suited their own users. HEIC/HEIF is a good example. It is the default image format on Apple devices, which have dedicated hardware to handle it. On other systems it can require paid plugins, or may not work at all. So most apps that display images have to quietly convert whatever users upload into a more widely supported format.&lt;/p&gt;
&lt;p&gt;Today, only two modern formats have broad browser support: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://developers.google.com/speed/webp&#34;
&gt;WebP&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aomedia.org/specifications/avif/&#34;
&gt;AVIF&lt;/a&gt;. Both aim to replace all the older formats, offering good quality at small file sizes for every kind of image, from photos to drawings, icons and short animations. AVIF goes a step further by also supporting HDR (high dynamic range).&lt;/p&gt;
&lt;p&gt;To sketch out some context, the well-known imge formats such as &amp;ldquo;jpeg&amp;rdquo;, &amp;ldquo;png&amp;rdquo; or &amp;ldquo;gif&amp;rdquo; are with us for 25 years or more; they were put together in a time when both storage and cpu processing power were premiums rather than commodities. That meant accepting compromises and precise product-market fits: &amp;ldquo;jpeg&amp;rdquo; became the universal format for everyday pictures, &amp;ldquo;png&amp;rdquo; for icons or computer generated images and &amp;ldquo;gif&amp;rdquo; was mostly delegated to short animated sequences once the patent covering the corresponding compression algorithm expired in the early 2000s.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-exploring-new-image-formats&#34;
    &gt;
        2. Exploring New Image Formats
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/modern_image_formats/#2-exploring-new-image-formats&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Exploring New Image Formats&#34; aria-label=&#34;Anchor 2. Exploring New Image Formats&#34; href=&#34;#2-exploring-new-image-formats&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Setting the background aside, using these formats on websites and web apps is fairly simple. You can start by saving your image in the new format (instead of the usual PNG or JPEG) from your image editing software. After that, you upload the pictures and add &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tags as you normally would.&lt;/p&gt;
&lt;p&gt;There are a few catches, though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tool support can be patchy.&lt;/strong&gt; Your image editor may not be able to save WebP or AVIF files at all, or it may save them without the best balance of quality and file size.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not every browser supports them.&lt;/strong&gt; Depending on your audience, some users may be on &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://caniuse.com/avif&#34;
&gt;browsers that don&amp;rsquo;t support AVIF&lt;/a&gt;, or &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://caniuse.com/webp&#34;
&gt;browsers that only support WebP&lt;/a&gt;. Sticking with the older, reliable formats is always a valid choice if it suits your use case better.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wider support means more storage.&lt;/strong&gt; To cover everyone, you need to keep at least two copies of each image: one in the modern format and one in an older, widely supported format. Your users get a better experience, but you pay for the extra storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-implementation-in-web-context&#34;
    &gt;
        3. Implementation in Web Context
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/modern_image_formats/#3-implementation-in-web-context&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. Implementation in Web Context&#34; aria-label=&#34;Anchor 3. Implementation in Web Context&#34; href=&#34;#3-implementation-in-web-context&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;In practice, there are a few ways to support a wide audience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use the HTML5 &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; tag with an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; fallback.&lt;/strong&gt; The browser picks the first format it supports, and the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag points to the widely supported format as a fallback. The &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; tag can also choose an image to suit the user&amp;rsquo;s screen size. The catch is &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://caniuse.com/?search=html5&#34;
&gt;browser compatibility&lt;/a&gt;: some browsers may load both the new and old image, which would make page loading slower instead of faster.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;picture&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;source&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;srcset&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;flowers.webp&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;image/webp&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;img&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;flowers.jpg&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;alt&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Flowers&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;picture&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use a JavaScript fallback with an &lt;code&gt;onerror&lt;/code&gt; handler.&lt;/strong&gt; The &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag tries the new format first. If that fails, the handler loads the older format instead. The right image does eventually appear, but the experience will probably be sluggish on older browsers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;img&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;flowers.webp&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;alt&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Flowers&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;onerror&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;this.onerror=null;this.src=&amp;#39;flowers.jpg&amp;#39;;&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Rewrite the request on the server, based on the browser&amp;rsquo;s headers.&lt;/strong&gt; This works in almost all situations: the browser always receives a format it can display, and there&amp;rsquo;s no risk of it loading two copies of the image. The only downside is that if a user saves the image, the file extension may not match its real format.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Frontend:
&amp;lt;img src=&amp;#34;flowers.jpg&amp;#34;&amp;gt;

# Backend .htaccess file for Apache httpd:
RewriteEngine On
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteRule &amp;#34;^flowers.jpg&amp;#34; &amp;#34;flowers.webp&amp;#34; [L]

# Nginx configuration:
if ($http_accept ~* &amp;#34;image/webp&amp;#34;) {
    rewrite ^flowers.jpg flowers.webp last;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Generate images dynamically in the right format.&lt;/strong&gt; For this you need to check both the browser&amp;rsquo;s &lt;code&gt;Accept&lt;/code&gt; header and whether your server can produce the format. The result isn&amp;rsquo;t always a smaller file, depending on the image content, so test it before committing to this approach. Here is a PHP example using GD:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$webp_available &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ((&lt;span style=&#34;color:#a6e22e&#34;&gt;imagetypes&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IMG_WEBP&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&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:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;is_array&lt;/span&gt;($_SERVER)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;array_key_exists&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;HTTP_ACCEPT&amp;#39;&lt;/span&gt;, $_SERVER)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;str_contains&lt;/span&gt;($_SERVER[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;HTTP_ACCEPT&amp;#39;&lt;/span&gt;], &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;image/webp&amp;#39;&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:#a6e22e&#34;&gt;header&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Content-Type: image/&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt; ($webp_available &lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;webp&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;png&amp;#39;&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:#a6e22e&#34;&gt;header&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Cache-Control: no-store, no-cache, must-revalidate, max-age=0&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:#a6e22e&#34;&gt;header&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Pragma: no-cache&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:#66d9ef&#34;&gt;if&lt;/span&gt; ($webp_available) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;ImageWEBP&lt;/span&gt;($image, &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;100&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:#66d9ef&#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:#a6e22e&#34;&gt;ImagePNG&lt;/span&gt;($image);
&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;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;4-server-side-heavy-lifting&#34;
    &gt;
        4. Server Side: Heavy Lifting
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/modern_image_formats/#4-server-side-heavy-lifting&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 4. Server Side: Heavy Lifting&#34; aria-label=&#34;Anchor 4. Server Side: Heavy Lifting&#34; href=&#34;#4-server-side-heavy-lifting&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;If your image editor doesn&amp;rsquo;t make good use of the new formats, or saving multiple copies of every picture becomes a chore, giving up can seem like the natural choice. There is help available on the server side, though, depending on your platform:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Content management systems often have plugins that do this for you.&lt;/strong&gt; They create the extra copies automatically. Plugins like this are readily available for WordPress, for example.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;You can convert images in bulk with a few Linux shell commands:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# Install the WebP and AVIF command-line tools (run as root)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dnf install libwebp-tools libavif-tools
&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:#75715e&#34;&gt;# Create WebP copies of all PNG images in the current directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;find . -maxdepth &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; -type f -name &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*.png&amp;#34;&lt;/span&gt; -exec sh -c &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;cwebp -lossless &amp;#34;$0&amp;#34; -o &amp;#34;${0%.png}.webp&amp;#34;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{}&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#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:#75715e&#34;&gt;# Create AVIF copies of all JPEG images, including subdirectories&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;find . -type f &lt;span style=&#34;color:#ae81ff&#34;&gt;\(&lt;/span&gt; -name &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*.jpg&amp;#34;&lt;/span&gt; -o -name &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*.jpeg&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\)&lt;/span&gt; -exec sh -c &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;avifenc &amp;#34;$0&amp;#34; &amp;#34;${0%.*}.avif&amp;#34;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{}&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;5-conclusion&#34;
    &gt;
        5. Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/modern_image_formats/#5-conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 5. Conclusion&#34; aria-label=&#34;Anchor 5. Conclusion&#34; href=&#34;#5-conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This exploration was an eye-opener, for me at least. My personal view is that for the average website, adopting a new image format brings only a small, not very consequential improvement. There are other use cases where it matters more, though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CDN services (content delivery networks)&lt;/strong&gt; can convert images transparently, and at their scale the bandwidth savings add up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Photo-sharing sites and social media platforms&lt;/strong&gt; can use AVIF for its HDR support, giving better-looking images to users with compatible screens, such as recent Apple devices or high-end desktop monitors.&lt;/li&gt;
&lt;/ul&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" /> 
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Migrating from Python 2 to Python 3</title>
            <link href="https://www.brainware.ro/posts/migrating_python_2_3/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/migrating_python_2_3/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2018-05-13T19:39:46+00:00</published>
            <updated>2018-05-13T19:39:46+00:00</updated>
            <content type="html">
                &lt;p&gt;Modern Python has powerful features such as &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://docs.python.org/3/library/asyncio-task.html&#34;
&gt;asynchronous programming&lt;/a&gt; (using &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt;) and memory-efficient data processing with &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do&#34;
&gt;generators and iterators&lt;/a&gt;. These capabilities, found mainly in Python 3, can noticeably improve both performance and maintainability. Taking advantage of them often means migrating existing Python 2 projects, and the effort involved ranges from a simple conversion to a major refactor. To help you plan, here are some of the most important differences between the two versions.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-print&#34;
    &gt;
        1. Print
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/migrating_python_2_3/#1-print&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Print&#34; aria-label=&#34;Anchor 1. Print&#34; href=&#34;#1-print&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This one is easy. Most of the time it&amp;rsquo;s just a matter of changing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;print &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;abcd&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;abcd&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-dictkeys-and-dictitems&#34;
    &gt;
        2. dict.keys() and dict.items()
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/migrating_python_2_3/#2-dictkeys-and-dictitems&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. dict.keys() and dict.items()&#34; aria-label=&#34;Anchor 2. dict.keys() and dict.items()&#34; href=&#34;#2-dictkeys-and-dictitems&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This works in Python 2:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;x &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;k &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; x&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;keys()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;z &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; k[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;2&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:#75715e&#34;&gt;# [1, 3]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In Python 3, &lt;code&gt;keys()&lt;/code&gt; and &lt;code&gt;items()&lt;/code&gt; return view objects that can&amp;rsquo;t be indexed or sliced, so &lt;code&gt;k[0:2]&lt;/code&gt; raises an error. A quick (though not optimal) workaround is to wrap the result in &lt;code&gt;list()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;x &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;k &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; list(x&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;keys())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;z &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; k[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;:&lt;span style=&#34;color:#ae81ff&#34;&gt;2&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:#75715e&#34;&gt;# [1, 3]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-range-and-xrange&#34;
    &gt;
        3. range() and xrange()
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/migrating_python_2_3/#3-range-and-xrange&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. range() and xrange()&#34; aria-label=&#34;Anchor 3. range() and xrange()&#34; href=&#34;#3-range-and-xrange&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;In Python 2, &lt;code&gt;xrange()&lt;/code&gt; is a lazy sequence generator, typically used in &lt;code&gt;for&lt;/code&gt; loops, while &lt;code&gt;range()&lt;/code&gt; builds a full list:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;a &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [i &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; xrange(&lt;span style=&#34;color:#ae81ff&#34;&gt;23&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:#75715e&#34;&gt;# [0, 1, ... , 22]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;b &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; range(&lt;span style=&#34;color:#ae81ff&#34;&gt;23&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:#75715e&#34;&gt;# [0, 1, ... , 22]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In Python 3, &lt;code&gt;range()&lt;/code&gt; takes over the role of &lt;code&gt;xrange()&lt;/code&gt;, and the old list-returning &lt;code&gt;range()&lt;/code&gt; no longer exists. Where you need an actual list, a list comprehension (or &lt;code&gt;list(range(...))&lt;/code&gt;) will do the job.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;4-exceptions&#34;
    &gt;
        4. Exceptions
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/migrating_python_2_3/#4-exceptions&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 4. Exceptions&#34; aria-label=&#34;Anchor 4. Exceptions&#34; href=&#34;#4-exceptions&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Exception handling in Python 2 looks cluttered:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&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:#66d9ef&#34;&gt;raise&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IOError&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;file error&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:#66d9ef&#34;&gt;except&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IOError&lt;/span&gt;, err:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print err
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Python 3 is much cleaner:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&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:#66d9ef&#34;&gt;raise&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IOError&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;file error&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:#66d9ef&#34;&gt;except&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IOError&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; err:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(err)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;5-rounding-and-division&#34;
    &gt;
        5. Rounding and Division
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/migrating_python_2_3/#5-rounding-and-division&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 5. Rounding and Division&#34; aria-label=&#34;Anchor 5. Rounding and Division&#34; href=&#34;#5-rounding-and-division&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;These changes can break programs in surprising ways:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;a &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; round(&lt;span style=&#34;color:#ae81ff&#34;&gt;122.5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;b &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&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:#75715e&#34;&gt;# Python 2:&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:#75715e&#34;&gt;# a = 123, b = 1&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:#75715e&#34;&gt;# Python 3:&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:#75715e&#34;&gt;# a = 122, b = 1.4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In short, Python 2 inspects the operand types and performs integer or floating-point division accordingly. Python 3 is more predictable: &lt;code&gt;/&lt;/code&gt; always performs floating-point division.&lt;/p&gt;
&lt;p&gt;Rounding is harder to reason about. Python 2 rounds halves away from zero, whereas Python 3 rounds halves to the nearest even number (banker&amp;rsquo;s rounding), which is why &lt;code&gt;round(122.5)&lt;/code&gt; gives 122.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;There are many more differences. For example, if your code uses &lt;code&gt;urllib&lt;/code&gt;, every call site must be updated to the new module structure. On a more encouraging note, an automated tool can handle much of this tedious work: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://docs.python.org/2/library/2to3.html#to3-reference&#34;
&gt;2to3&lt;/a&gt;.&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/python" term="python" label="Python" /> 
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/performance" term="performance" label="performance" /> 
                                <category scheme="https://www.brainware.ro/tags/python" term="python" label="python" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Hero Culture is Bad</title>
            <link href="https://www.brainware.ro/posts/hero_culture_is_bad/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/hero_culture_is_bad/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2018-01-28T13:23:32+00:00</published>
            <updated>2018-01-28T13:23:32+00:00</updated>
            <content type="html">
                &lt;p&gt;Years ago, in the country where I grew up and back when I still watched TV, a pattern kept repeating: TV stars would take their shows to rival stations, only to find themselves in a worse position a few months later.&lt;/p&gt;
&lt;p&gt;They were often offered better contracts and sometimes even managed to bring part of their original crew along. Yet they rarely held on to their audiences for more than a short while, and some were pushed out of television altogether.&lt;/p&gt;
&lt;p&gt;Tabloids occasionally asked how this could possibly happen, but never offered real answers (not that they had much insight to give). I doubt their readers could have made sense of it either.&lt;/p&gt;
&lt;p&gt;I couldn&amp;rsquo;t make sense of it back then, either. I&amp;rsquo;d heard the more thoughtful explanations, such as &amp;ldquo;the shows were simply better before the move&amp;rdquo; or &amp;ldquo;some stations have more money and can afford not to cut corners.&amp;rdquo; But that&amp;rsquo;s only the surface. It took changing jobs a couple of times myself to understand what success really depends on. In short:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It isn&amp;rsquo;t about having some special talent.&lt;/li&gt;
&lt;li&gt;It isn&amp;rsquo;t about single-handedly pulling the company uphill.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s about the entire environment that makes you succeed or fail, starting with how clean the toilets are at your workplace.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;how-does-the-environment-make-or-break-people&#34;
    &gt;
        How does the environment make or break people?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/hero_culture_is_bad/#how-does-the-environment-make-or-break-people&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor How does the environment make or break people?&#34; aria-label=&#34;Anchor How does the environment make or break people?&#34; href=&#34;#how-does-the-environment-make-or-break-people&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The most basic example is education: whether you get a good one depends on your family, neighborhood, city and society as a whole. You could argue that business is different, since people are selected through interviews rather than born into their position. I&amp;rsquo;d argue the same constraints apply everywhere: &lt;strong&gt;location&lt;/strong&gt;, &lt;strong&gt;money&lt;/strong&gt; and the &lt;strong&gt;human factor&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example from one of my earlier jobs. At the time, the only way to show slides in a meeting was with a projector. It wasn&amp;rsquo;t easy: you had to get it from IT, wrestle with the setup, and only then start your actual work. Afterwards you had to reverse the whole process so someone else could use it in another room. Finance considered this the optimal approach, because fitting every meeting room with a TV or a fixed projector would have cost far more.&lt;/p&gt;
&lt;p&gt;That money-saving strategy had two problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The setup was cumbersome.&lt;/strong&gt; Booking the projector, collecting it from IT, configuring it and returning it ate up 20 minutes or more of a meeting that lasted an hour at most. A real bottom-line &lt;em&gt;win&lt;/em&gt;, I&amp;rsquo;d say.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The projectors wore out.&lt;/strong&gt; Their heating and cooling cycles were incompatible with this process, so within a few months the lenses degraded, the image lost its sharpness and the devices were no longer fit for purpose. Another bottom-line &lt;em&gt;win&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Challenges like these create workplace heroes: people who seem to succeed against everything thrown at them, but who aren&amp;rsquo;t really winning. They&amp;rsquo;re survivors, the ones who appear to float above the water.&lt;/p&gt;
&lt;p&gt;After all these years, my conclusion is that you can&amp;rsquo;t simply transplant successful people into such environments and expect them to keep succeeding. Even if they become local heroes, their real impact will be severely limited.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;do-heroes-always-win&#34;
    &gt;
        Do heroes always win?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/hero_culture_is_bad/#do-heroes-always-win&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Do heroes always win?&#34; aria-label=&#34;Anchor Do heroes always win?&#34; href=&#34;#do-heroes-always-win&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The workplace I mentioned had a hero culture by any definition. A few engineers worked their tails off, fighting company procedures, incompetence and, ultimately, sheer craziness. But good code alone doesn&amp;rsquo;t get you anywhere, as they &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/no_route_forward/&#34;
&gt;found out the hard way&lt;/a&gt;. Such an environment simply isn&amp;rsquo;t conducive to good performance.&lt;/p&gt;
&lt;p&gt;These heroes eventually thrived professionally once they landed in genuinely good environments, much like the TV stations I described at the start, the ones that kept drawing huge audiences whether or not particular anchors were on screen.&lt;/p&gt;
&lt;p&gt;So what was the secret of the successful stations? They had hero-proofed their work environments.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;what-does-a-hero-proof-workplace-look-like&#34;
    &gt;
        What does a hero-proof workplace look like?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/hero_culture_is_bad/#what-does-a-hero-proof-workplace-look-like&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor What does a hero-proof workplace look like?&#34; aria-label=&#34;Anchor What does a hero-proof workplace look like?&#34; href=&#34;#what-does-a-hero-proof-workplace-look-like&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Culture helps to a degree: successful companies today tend to have flat structures and open-door policies. That&amp;rsquo;s the visible part. The less visible part is that in such companies, nobody can succeed alone, and everybody knows it.&lt;/p&gt;
&lt;p&gt;And yes, it really does start with clean toilets. Too few bathrooms, or mostly dirty ones, are among the most effective mood destroyers in any organization. It works like Maslow&amp;rsquo;s hierarchy of needs: the basics must be in place before anything else, and the quality of your training programs only starts to matter much later. The stations that kept their audiences after &amp;ldquo;losing&amp;rdquo; certain people were simply better at covering the basics. In essence, they:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ran a better hiring process for support staff;&lt;/li&gt;
&lt;li&gt;put the right tools in the right hands;&lt;/li&gt;
&lt;li&gt;held everyone to a high standard, with no exceptions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By offering audiences a better product, they could charge advertisers more, spend more time perfecting details and cut fewer corners than their competitors. They kept a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Virtuous_circle_and_vicious_circle&#34;
&gt;virtuous cycle&lt;/a&gt; going. Yes, it really is that simple.&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" />
        </entry>
        <entry>
            <title>Using Linux Network Namespaces</title>
            <link href="https://www.brainware.ro/posts/using_linux_network_namespaces/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/using_linux_network_namespaces/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2018-01-20T19:55:57+00:00</published>
            <updated>2018-01-20T19:55:57+00:00</updated>
            <content type="html">
                &lt;p&gt;You rarely get to work with Linux namespaces directly. Usually they sit behind the scenes in container tooling or hosting platforms that enforce hard resource limits for customers. But sometimes containers are too heavy for the job. I once needed two instances of the same service to talk to each other over the network.&lt;/p&gt;
&lt;p&gt;Why not just have them listen on different addresses or ports? Because it isn&amp;rsquo;t always that simple. If you can&amp;rsquo;t change the code and only want to replicate a certain behavior, there may be no way to make an instance use a different port. If the protocol also relies on broadcasting, it gets harder still, since you often don&amp;rsquo;t have two IP addresses on separate interfaces attached to the same network. Virtualization or containers would solve this, but they&amp;rsquo;re overkill here. A lightweight alternative is to manipulate Linux network namespaces.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Run all commands below as root.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-unshare&#34;
    &gt;
        1. Unshare
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/using_linux_network_namespaces/#1-unshare&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Unshare&#34; aria-label=&#34;Anchor 1. Unshare&#34; href=&#34;#1-unshare&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Open two terminals. Call one the &amp;ldquo;primary&amp;rdquo; and the other the &amp;ldquo;secondary&amp;rdquo;, and keep track of which is which. In the &lt;strong&gt;secondary&lt;/strong&gt;, run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# unshare -n /bin/bash&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:#75715e&#34;&gt;# echo $$&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;xxxxxx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note the PID that is printed, since you need it in the next step.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-set-up-the-network&#34;
    &gt;
        2. Set Up the Network
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/using_linux_network_namespaces/#2-set-up-the-network&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Set Up the Network&#34; aria-label=&#34;Anchor 2. Set Up the Network&#34; href=&#34;#2-set-up-the-network&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;In the &lt;strong&gt;primary&lt;/strong&gt;, create a virtual Ethernet pair and configure one end, using the PID from step 1:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# ip link add name veth0 type veth peer name veth1 netns xxxxxx&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:#75715e&#34;&gt;# ip address add 192.168.10.10/24 dev veth0&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:#75715e&#34;&gt;# ip link set veth0 up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, in the &lt;strong&gt;secondary&lt;/strong&gt;, configure the other end and test the link:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# ip address add 192.168.10.15/24 dev veth1&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:#75715e&#34;&gt;# ip link set veth1 up&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:#75715e&#34;&gt;# ping 192.168.10.10&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;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-set-up-the-services&#34;
    &gt;
        3. Set Up the Services
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/using_linux_network_namespaces/#3-set-up-the-services&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. Set Up the Services&#34; aria-label=&#34;Anchor 3. Set Up the Services&#34; href=&#34;#3-set-up-the-services&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I won&amp;rsquo;t go into detail here, since the goal was only to get a working communication path. It looks easy, and it is. Hope it helps!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" /> 
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>After 6 months at Googamaz...book</title>
            <link href="https://www.brainware.ro/posts/after_6_months_googamaz_book/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/after_6_months_googamaz_book/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2017-10-15T21:32:07+00:00</published>
            <updated>2017-10-15T21:32:07+00:00</updated>
            <content type="html">
                &lt;p&gt;Some intense months later, I&amp;rsquo;m back with fresh ideas and stories to share. &lt;em&gt;Secrets follow.&lt;/em&gt; Well, not really, but I&amp;rsquo;ve put everything in a list to make it easier to digest.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-getting-in-is-hard-staying-in-seems-even-harder&#34;
    &gt;
        1. Getting in is hard, staying in seems even harder
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/after_6_months_googamaz_book/#1-getting-in-is-hard-staying-in-seems-even-harder&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Getting in is hard, staying in seems even harder&#34; aria-label=&#34;Anchor 1. Getting in is hard, staying in seems even harder&#34; href=&#34;#1-getting-in-is-hard-staying-in-seems-even-harder&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Once the commercials are over, the movie begins: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/how_to_fail_interview/&#34;
&gt;the interview&lt;/a&gt; and then the orientation don&amp;rsquo;t prepare you for the environment you&amp;rsquo;ll be swimming in when the daily work starts. On my path to enlightenment I realized that the kitchen staff, the people who cook that good food for you three times a day, are likely evaluated on par with the people they feed. At the end of the day, nobody gets a free meal.&lt;/p&gt;
&lt;p&gt;I also found out that the photos floating around the internet, with colorful interiors, pool tables, arcades and pinball machines straight out of the &amp;rsquo;80s, are real. I also learned that an unhealthy balance between productivity and time spent having fun in the games room or napping in the library will land you on a PIP (performance improvement plan) before your first anniversary. Failing it is obviously your ticket out, but some people choose to leave on their own terms. For the company the outcome is the same, though: a (possibly lifetime) &amp;ldquo;no rehire&amp;rdquo; flag in your file.&lt;/p&gt;
&lt;p&gt;From the outside, people leave or are let go, and it&amp;rsquo;s impossible to tell the two apart. There seem to be &amp;ldquo;sweet spots&amp;rdquo; for leaving at certain intervals, like just before the 6-month mark for people who&amp;rsquo;d rather not pay too much tax to some country or, who knows, maybe it&amp;rsquo;s just a quick divorce. Another sweet spot seems to be around 1 year, when the first batch of shares vests and the payout can be significant. Seeing many people stay beyond their 5th year or so is encouraging, though.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-recruiters-tend-to-avoid-you&#34;
    &gt;
        2. Recruiters tend to avoid you
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/after_6_months_googamaz_book/#2-recruiters-tend-to-avoid-you&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Recruiters tend to avoid you&#34; aria-label=&#34;Anchor 2. Recruiters tend to avoid you&#34; href=&#34;#2-recruiters-tend-to-avoid-you&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Changing my position on my LinkedIn profile made the profile-visits counter drop by more than 30%, while InMails and connection requests went from nearly daily to maybe once every few weeks. Simply put, very few companies can offer compensation like the big ones everybody talks about. The big companies also run their own recruiting pipelines and don&amp;rsquo;t work with third parties.&lt;/p&gt;
&lt;p&gt;On a side note, some recruiters simply cold-mail every candidate in their internal database who matches certain keywords, without checking whether those people are still on the market for that kind of role. I don&amp;rsquo;t have figures to tell whether that strategy actually works for them, but I now ignore everything from recruiters with less than 5 years of experience, no exceptions.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-the-ulysses-syndrome-is-real&#34;
    &gt;
        3. The Ulysses syndrome is real
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/after_6_months_googamaz_book/#3-the-ulysses-syndrome-is-real&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. The Ulysses syndrome is real&#34; aria-label=&#34;Anchor 3. The Ulysses syndrome is real&#34; href=&#34;#3-the-ulysses-syndrome-is-real&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The path from &amp;ldquo;wow, I&amp;rsquo;m so lucky&amp;rdquo; to &amp;ldquo;what the *** did I get myself into&amp;rdquo; is &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Ulysses_syndrome&#34;
&gt;short, really short&lt;/a&gt;. In the first month or so you might consider writing angry emails to everyone who didn&amp;rsquo;t believe in you or refused to give you a position you badly wanted at some point in your career. Of course you don&amp;rsquo;t, because you realize that people, starting with you, are constantly evolving and, by definition, focused on their own needs. What others can put on the table isn&amp;rsquo;t always their top priority.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m kidding: you don&amp;rsquo;t do it because the honeymoon ends faster than you&amp;rsquo;d like, and you find yourself in a different country, in an environment governed by different rules, away from familiar places and intimately close to a very demanding workplace. If your family is with you, the challenge is multiplied, as they may struggle to adjust to local life too. This is actually the leading cause of people leaving companies in their first year after relocating to another country, or even across the ocean.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;4-there-is-light-at-the-end-of-the-tunnel&#34;
    &gt;
        4. There is light at the end of the tunnel
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/after_6_months_googamaz_book/#4-there-is-light-at-the-end-of-the-tunnel&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 4. There is light at the end of the tunnel&#34; aria-label=&#34;Anchor 4. There is light at the end of the tunnel&#34; href=&#34;#4-there-is-light-at-the-end-of-the-tunnel&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;At some point the roots start to grow and the new environment no longer feels menacing. You start meeting people and doing work that seems to make other people&amp;rsquo;s lives easier. The prospect of your first formal performance review ending in a PIP slowly fades. Maybe the whole future of humanity no longer looks so grim after all, and neither does the outlook for your career.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/sun_microsystems.webp&#34;
  alt=&#34;Sun Microsystems Sign&#34;
  title=&#34;Just the back of the sign people tend to take a lot of selfies in front of&#34;
/&gt;&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" />
        </entry>
        <entry>
            <title>Private Yum Repository with Amazon S3</title>
            <link href="https://www.brainware.ro/posts/private_yum_repository_s3/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/private_yum_repository_s3/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2017-03-20T22:26:24+00:00</published>
            <updated>2017-03-20T22:26:24+00:00</updated>
            <content type="html">
                &lt;p&gt;Setting up a public yum repository with &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html&#34;
&gt;S3&lt;/a&gt; is straightforward, but making it private takes more effort. Access control has to be handled by a plugin that fetches files from the S3 bucket through the API, typically using stored credentials. On EC2 instances with an appropriate IAM role, you can skip storing credentials, but in any other environment that isn&amp;rsquo;t an option.&lt;/p&gt;
&lt;p&gt;Either way, the first steps are the same for public and private setups.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-create-the-repository-directory-structure&#34;
    &gt;
        1. Create the repository directory structure
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/private_yum_repository_s3/#1-create-the-repository-directory-structure&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Create the repository directory structure&#34; aria-label=&#34;Anchor 1. Create the repository directory structure&#34; href=&#34;#1-create-the-repository-directory-structure&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Use the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://linux.die.net/man/8/createrepo&#34;
&gt;createrepo&lt;/a&gt; tool, which is available on both RedHat-based and Debian-based systems (e.g. Fedora/CentOS or Ubuntu). Running it creates a &lt;code&gt;repodata&lt;/code&gt; subdirectory containing several files with metadata parsed from your RPM packages.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-sync-the-local-repository-with-the-s3-bucket&#34;
    &gt;
        2. Sync the local repository with the S3 bucket
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/private_yum_repository_s3/#2-sync-the-local-repository-with-the-s3-bucket&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Sync the local repository with the S3 bucket&#34; aria-label=&#34;Anchor 2. Sync the local repository with the S3 bucket&#34; href=&#34;#2-sync-the-local-repository-with-the-s3-bucket&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;With the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cli/&#34;
&gt;AWS Command Line Interface&lt;/a&gt; installed, this takes a single command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;    $ aws s3 sync ~/localrepo s3://yumrepobucket/remoterepo --delete
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running this from cron is trickier, because the credentials may not be picked up correctly. Setting the &lt;code&gt;AWS_CONFIG_FILE&lt;/code&gt; environment variable should resolve that.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-install-a-yum-plugin&#34;
    &gt;
        3. Install a yum plugin
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/private_yum_repository_s3/#3-install-a-yum-plugin&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. Install a yum plugin&#34; aria-label=&#34;Anchor 3. Install a yum plugin&#34; href=&#34;#3-install-a-yum-plugin&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You could &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://yum.baseurl.org/wiki/WritingYumPlugins.html&#34;
&gt;write your own plugin&lt;/a&gt; if you know Python, but grabbing an existing one from GitHub is much quicker.&lt;/p&gt;
&lt;p&gt;The one that worked best for me was &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://github.com/seporaitis/yum-s3-iam&#34;
&gt;yum-s3-iam&lt;/a&gt;. Installation was simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy &lt;a
  class=&#34;gblog-markdown__link--code&#34;
  href=&#34;https://github.com/seporaitis/yum-s3-iam/blob/master/s3iam.py&#34;
&gt;&lt;code&gt;s3iam.py&lt;/code&gt;&lt;/a&gt; to &lt;code&gt;/usr/lib/yum-plugins/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy &lt;a
  class=&#34;gblog-markdown__link--code&#34;
  href=&#34;https://github.com/seporaitis/yum-s3-iam/blob/master/s3iam.conf&#34;
&gt;&lt;code&gt;s3iam.conf&lt;/code&gt;&lt;/a&gt; to &lt;code&gt;/etc/yum/pluginconf.d/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy a customized version of &lt;a
  class=&#34;gblog-markdown__link--code&#34;
  href=&#34;https://github.com/seporaitis/yum-s3-iam/blob/master/s3iam.repo&#34;
&gt;&lt;code&gt;s3iam.repo&lt;/code&gt;&lt;/a&gt; to &lt;code&gt;/etc/yum.repos.d/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Although the documentation doesn&amp;rsquo;t mention it, you can add the &lt;code&gt;key_id&lt;/code&gt; and &lt;code&gt;secret_key&lt;/code&gt; parameters to the &lt;code&gt;.repo&lt;/code&gt; file. If you&amp;rsquo;re on EC2, configuring an IAM role instead should be enough. For security, whichever identity you use (role or user, if a role isn&amp;rsquo;t possible) should have read-only access to the bucket and nothing more.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it: you now have a private yum repository hosted on an S3 bucket. Enjoy!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" /> 
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/python" term="python" label="python" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Cloud Integration – One Good Start</title>
            <link href="https://www.brainware.ro/posts/cloud_integration_good_start/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/cloud_integration_good_start/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2017-03-08T15:38:40+00:00</published>
            <updated>2017-03-08T15:38:40+00:00</updated>
            <content type="html">
                &lt;p&gt;Back in the early 2000s, many businesses offered web hosting or ran their services straight from bare-metal servers. The &amp;ldquo;cloud&amp;rdquo; only gained real traction within the last 5 to 10 years, and plenty of those older businesses are still around today.&lt;/p&gt;
&lt;p&gt;What did it take (and in many cases still takes) to provide services from a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Colocation_centre&#34;
&gt;colocated&lt;/a&gt; or on-premises bare-metal server?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hardware first.&lt;/strong&gt; The physical server had to be bought before anything else, and enclosure size requirements sometimes ruled out consumer-grade hardware.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manual OS installation.&lt;/strong&gt; The operating system had to be installed by hand from installation media.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tedious configuration.&lt;/strong&gt; Setup was a slow process, and many details kept getting fixed in the days after going live.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard-to-handle problems.&lt;/strong&gt; Unplanned issues, failures, and upgrades (hardware and software) were difficult to deal with and sometimes meant taking the whole server down. Meeting any &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/sla_slo_uptime/&#34;
&gt;SLAs&lt;/a&gt; was often a matter of luck.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite all this, things often worked just fine.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;cloud-integration&#34;
    &gt;
        Cloud Integration
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/cloud_integration_good_start/#cloud-integration&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Cloud Integration&#34; aria-label=&#34;Anchor Cloud Integration&#34; href=&#34;#cloud-integration&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The cloud introduced a different paradigm by fully separating the service from the hardware it runs on. Servers could be created on demand, and uptime could be preserved through the platform&amp;rsquo;s built-in failover features. Still, it wasn&amp;rsquo;t all smooth sailing: service performance was often much slower than the bare-metal equivalent. That leads to the problem at hand: how do you integrate bare-metal servers, colocated or on-premises, with cloud services?&lt;/p&gt;
&lt;p&gt;First, why supplement physical servers with cloud services at all? Going back to the list above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OS installation:&lt;/strong&gt; It may not be fully automated in every scenario, but you can keep versioned images that bring up an operating system with minimal intervention.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration:&lt;/strong&gt; A tool like &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.chef.io/chef/&#34;
&gt;Chef&lt;/a&gt; can manage it automatically. The Chef Server can live in the cloud and connect to existing infrastructure over a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Virtual_private_network&#34;
&gt;VPN&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backups:&lt;/strong&gt; Data backups can be stored in the cloud alongside tools that restore anything, at any time, with minimal human involvement.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These changes can mean quieter nights, far less manual work, and SLAs that become predictable.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;using-amazon-web-services&#34;
    &gt;
        Using Amazon Web Services
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/cloud_integration_good_start/#using-amazon-web-services&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Using Amazon Web Services&#34; aria-label=&#34;Anchor Using Amazon Web Services&#34; href=&#34;#using-amazon-web-services&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/&#34;
&gt;AWS&lt;/a&gt; services relevant to this scenario are &lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/s3/&#34;
&gt;S3&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ec2/&#34;
&gt;EC2&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/codecommit/&#34;
&gt;CodeCommit&lt;/a&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/opsworks/chefautomate/&#34;
&gt;OpsWorks&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;1-backups&#34;
    &gt;
        1. Backups
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/cloud_integration_good_start/#1-backups&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Backups&#34; aria-label=&#34;Anchor 1. Backups&#34; href=&#34;#1-backups&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Backups can be stored in one or more S3 buckets. Options include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A specialized tool such as &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.amanda.org/&#34;
&gt;Amanda&lt;/a&gt;, which integrates well with AWS.&lt;/li&gt;
&lt;li&gt;A classic approach combining &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://linux.die.net/man/1/tar&#34;
&gt;tar&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://linux.die.net/man/1/find&#34;
&gt;find&lt;/a&gt; to handle incrementals.&lt;/li&gt;
&lt;li&gt;Mirroring data into a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html&#34;
&gt;versioned S3 bucket&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;2-configuration&#34;
    &gt;
        2. Configuration
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/cloud_integration_good_start/#2-configuration&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Configuration&#34; aria-label=&#34;Anchor 2. Configuration&#34; href=&#34;#2-configuration&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;There are two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OpsWorks&lt;/strong&gt;, where Amazon sets up a Chef Server for you. This is simple, but monthly costs can climb quickly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A standard EC2 instance&lt;/strong&gt;, where you  can install a Chef Server yourself. Even a t2.micro from the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/free/&#34;
&gt;free tier&lt;/a&gt; will do.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whichever you choose, the Chef Server must be connected to the on-premises or colocated servers through a VPN solution (for example, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://openvpn.net/&#34;
&gt;OpenVPN&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Development files (cookbooks, node attributes, data bags) can be stored easily in AWS CodeCommit, a git repository that should cost nothing under &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/codecommit/pricing/&#34;
&gt;typical usage&lt;/a&gt;. Alternatively, you can host a git repository on a separate EC2 instance, distinct from the Chef Server, to avoid a single point of failure.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;conclusion&#34;
    &gt;
        Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/cloud_integration_good_start/#conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Conclusion&#34; aria-label=&#34;Anchor Conclusion&#34; href=&#34;#conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This is only the beginning of the journey to the cloud. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" /> 
                                <category scheme="https://www.brainware.ro/categories/backup" term="backup" label="Backup" /> 
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" />
        </entry>
        <entry>
            <title>Leaving in Anger? No.</title>
            <link href="https://www.brainware.ro/posts/leaving_in_anger/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/leaving_in_anger/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2017-02-24T15:57:32+00:00</published>
            <updated>2017-02-24T15:57:32+00:00</updated>
            <content type="html">
                &lt;p&gt;Suppose you ignored &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/how_to_fail_interview/&#34;
&gt;my advice from a few months ago&lt;/a&gt; and actually landed that job. That&amp;rsquo;s a real achievement, but it isn&amp;rsquo;t what I want to write about. In most cases, what you leave behind matters more than what lies ahead of you.&lt;/p&gt;
&lt;p&gt;Your current job probably doesn&amp;rsquo;t compare with the likes of &lt;em&gt;Googamazbook&lt;/em&gt;, and that&amp;rsquo;s fine. Or maybe you feel you didn&amp;rsquo;t accomplish everything you hoped for when you signed up for the role you&amp;rsquo;re about to leave. That&amp;rsquo;s fine too. Let&amp;rsquo;s go through some common frustrations.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-promotions-or-the-lack-of-them&#34;
    &gt;
        1. Promotions (or the lack of them)
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/leaving_in_anger/#1-promotions-or-the-lack-of-them&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Promotions (or the lack of them)&#34; aria-label=&#34;Anchor 1. Promotions (or the lack of them)&#34; href=&#34;#1-promotions-or-the-lack-of-them&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You feel you deserved more, and you were passed over for reasons that seemed unclear or even unprofessional. That may well be true, but it isn&amp;rsquo;t always about you as an individual. It&amp;rsquo;s about how companies work.&lt;/p&gt;
&lt;p&gt;In the companies I&amp;rsquo;ve worked for, most employees sat somewhere in the middle of a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Gaussian_function&#34;
&gt;Gaussian curve&lt;/a&gt; when ranked by seniority. On the left were people in their first jobs, such as recent graduates, who tended to move up quickly toward the bulk in the middle. On the right were senior managers and people with &amp;ldquo;principal&amp;rdquo; in their titles. Middle management sat in the middle too. The name says it all.&lt;/p&gt;
&lt;p&gt;In short, there isn&amp;rsquo;t much room for natural movement if that shape is to be preserved, and it has to be preserved if the company wants to survive in the market. Add the people hired from outside, and there are always more candidates than seats at the front of the room. That&amp;rsquo;s why you need to prepare to secure a promotion: you have to look better than the others competing for the same seat. Professionally better? Probably not, but that&amp;rsquo;s how it works.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-raises-smaller-than-expected&#34;
    &gt;
        2. Raises (smaller than expected)
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/leaving_in_anger/#2-raises-smaller-than-expected&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Raises (smaller than expected)&#34; aria-label=&#34;Anchor 2. Raises (smaller than expected)&#34; href=&#34;#2-raises-smaller-than-expected&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You think your latest 3% raise was dreadful and didn&amp;rsquo;t reflect your performance. Complaining openly about it just before you leave will fix&amp;hellip; well, nothing. Companies operate by different rules.&lt;/p&gt;
&lt;p&gt;From the company&amp;rsquo;s perspective, pay should reflect an employee&amp;rsquo;s market value: what no other employer would beat, plus the risk your employer is willing to accept. That figure is only loosely tied to the internal ranking described above, because some people care more about their title than their salary. Companies know this and act accordingly.&lt;/p&gt;
&lt;p&gt;Overall, companies pay the minimum needed to keep a particular person. &lt;em&gt;Normal&lt;/em&gt; companies are for-profit businesses and follow market rules. Public-sector organizations are different. They pay in close relation to internal rank, because individual performance almost never brings in more business, only bigger budgets.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-bosses-poor-management-quality&#34;
    &gt;
        3. Bosses (poor management quality)
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/leaving_in_anger/#3-bosses-poor-management-quality&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. Bosses (poor management quality)&#34; aria-label=&#34;Anchor 3. Bosses (poor management quality)&#34; href=&#34;#3-bosses-poor-management-quality&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Bosses are judged within the company&amp;rsquo;s internal management policy. Very few companies act on individual complaints from the &lt;em&gt;minions&lt;/em&gt;, but all of them watch trends, statistics and overall scores gathered through anonymous surveys.&lt;/p&gt;
&lt;p&gt;Since your direct boss is your main point of contact with the company, they end up absorbing everything positive and negative the company projects. They rarely decide how promotions and pay adjustments are handed out. They can &lt;em&gt;propose&lt;/em&gt; changes and fill in positive feedback on forms, but as individuals they are judged on end results alone, and those results are always capped by the company&amp;rsquo;s budget.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;4-culture-meaningless-words&#34;
    &gt;
        4. Culture (meaningless words)
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/leaving_in_anger/#4-culture-meaningless-words&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 4. Culture (meaningless words)&#34; aria-label=&#34;Anchor 4. Culture (meaningless words)&#34; href=&#34;#4-culture-meaningless-words&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You may leave feeling disgusted by the company culture, but the culture itself usually isn&amp;rsquo;t the cause. Many companies paint slogans on walls and doors so that people won&amp;rsquo;t forget them.&lt;/p&gt;
&lt;p&gt;The unspoken problem is that culture isn&amp;rsquo;t passed on by wall messages. It spreads more subtly, from managers to employees and between colleagues of different tenures. Periods of rapid expansion promote managers who aren&amp;rsquo;t properly grounded in the founders&amp;rsquo; vision, and before long ideas like &amp;ldquo;the sole purpose of this company is to fill the owner&amp;rsquo;s bank accounts&amp;rdquo; become universally accepted. Then again, making money is one of the core purposes of any company.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;5-conclusion&#34;
    &gt;
        5. Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/leaving_in_anger/#5-conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 5. Conclusion&#34; aria-label=&#34;Anchor 5. Conclusion&#34; href=&#34;#5-conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;If any of this sounds familiar, remember that it isn&amp;rsquo;t about one person casting spells from an ivory tower, and you weren&amp;rsquo;t singled out. And if things really don&amp;rsquo;t work out, leaving &lt;em&gt;is&lt;/em&gt; sometimes the only option.&lt;/p&gt;
&lt;p&gt;So why not vent your anger on the way out? Because it only upsets individuals instead of fixing procedures or redistributing budgets. You may need one of those individuals as a good reference when you pass the onsite at &lt;em&gt;Googamazbook&lt;/em&gt;, or even to get considered for an interview in the first place. Be human, and respect the humanity of others.&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" />
        </entry>
        <entry>
            <title>FOSDEM 2017</title>
            <link href="https://www.brainware.ro/posts/fosdem_2017/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/fosdem_2017/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2017-02-09T15:07:07+00:00</published>
            <updated>2017-02-09T15:07:07+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://fosdem.org/&#34;
&gt;FOSDEM&lt;/a&gt;&lt;/strong&gt; is an annual event for open source software developers, held in Brussels on the first weekend of February.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This year&amp;rsquo;s event was the 5th FOSDEM I have attended since 2010. Over that time I have watched it evolve: the talks followed the industry&amp;rsquo;s shifting focus, and some topics disappeared to make room for newer ones. Many of those newcomers never gained real traction and faded away as well.&lt;/p&gt;
&lt;p&gt;The biggest shift I have noticed is a move away from abstract or general subjects (such as Linux Kernel discussions or C/C++ performance tricks) and towards finished products and near-mature technologies applied to achieve concrete results.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/fosdem-present2.webp&#34;
  alt=&#34;FOSDEM 2017 Presentation&#34;
  
/&gt;&lt;/p&gt;
&lt;p&gt;The quality of the sessions varied. Even when the slides were genuinely interesting, some speakers could have used better presentation skills, and their job title made no difference. A few good ideas were spoiled because the presenter could not keep the audience focused on the topic.&lt;/p&gt;
&lt;p&gt;I also noticed that all the non-technical talks and discussions had been moved to the smaller &amp;ldquo;developer&amp;rdquo; and &amp;ldquo;community&amp;rdquo; rooms. Unless you grabbed a seat early in the morning, you could not get in, and the queues at the doors grew long because interest often exceeded the room capacity.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/fosdem-present1.webp&#34;
  alt=&#34;FOSDEM 2017 Presentation&#34;
  
/&gt;&lt;/p&gt;
&lt;p&gt;The event as a whole was busier than last year&amp;rsquo;s, continuing a trend of several years. The hallways and common areas were packed at times, and lunch took a long while, with 20-30 people queuing at every vendor.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/fosdem-busy.webp&#34;
  alt=&#34;FOSDEM 2017 Courtyard&#34;
  
/&gt;&lt;/p&gt;
&lt;p&gt;I had also hoped the closing keynote would be interesting and innovative: a peek into the future, a look back at the previous year&amp;rsquo;s events, or achievements that made the world a better place. Unfortunately, it was a dull talk that many attendees stopped following before the end. Unsurprisingly, no questions were taken from the audience.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/fosdem-present3.webp&#34;
  alt=&#34;FOSDEM 2017 Presentation&#34;
  
/&gt;&lt;/p&gt;
&lt;p&gt;That was FOSDEM 2017. I expect the organizers to spread the topics over more days or introduce some form of registration, because the venue, large as it is, is reaching its limits.&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/architecture" term="architecture" label="architecture" /> 
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" />
        </entry>
        <entry>
            <title>XFS Corruption: Repairing</title>
            <link href="https://www.brainware.ro/posts/xfs_corruption/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/xfs_corruption/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2017-01-24T18:48:57+00:00</published>
            <updated>2017-01-24T18:48:57+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The go-to tool for &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/XFS&#34;
&gt;XFS&lt;/a&gt; repairs is, unsurprisingly, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://linux.die.net/man/8/xfs_repair&#34;
&gt;xfs_repair&lt;/a&gt;. Getting it to run, however, can sometimes be the hard part.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;introduction&#34;
    &gt;
        Introduction
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/xfs_corruption/#introduction&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Introduction&#34; aria-label=&#34;Anchor Introduction&#34; href=&#34;#introduction&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;How does filesystem corruption happen? There are several likely causes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Kernel bugs:&lt;/strong&gt; Rare, but they have happened many times in the past and will happen again. Little can be done beyond applying patches and keeping the kernel up to date.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Memory issues:&lt;/strong&gt; For example, memory errors that propagate into the filesystem&amp;rsquo;s control structures. ECC memory mitigates this, but it can never be fully ruled out.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Underlying storage problems:&lt;/strong&gt; Quite unlikely, but still possible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hitting the reset button on a running server:&lt;/strong&gt; Journaling filesystems can almost always recover from this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;RAID controller issues:&lt;/strong&gt; Possibly the leading cause, and not easy to mitigate, even though a firmware upgrade is sometimes available.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any filesystem type can be affected by any of these causes. XFS simply appears more often in corruption-related search results because it is so widely used.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;disaster&#34;
    &gt;
        Disaster?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/xfs_corruption/#disaster&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Disaster?&#34; aria-label=&#34;Anchor Disaster?&#34; href=&#34;#disaster&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You wake up in the morning, happy, with the whole day planned out. Then an error pops up on your pager:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Corruption of in-memory data detected. Shutting down filesystem&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This one is bad. If the filesystem holds databases or web server files, things will go south within minutes: services will go down or stop serving users. That is why smart people replicate their services, use load balancers, or run a hot-replica architecture.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;repairing&#34;
    &gt;
        Repairing
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/xfs_corruption/#repairing&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Repairing&#34; aria-label=&#34;Anchor Repairing&#34; href=&#34;#repairing&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The only complicated part is that you need to be on the server&amp;rsquo;s real keyboard and video (for example via a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/KVM_switch&#34;
&gt;KVM switch&lt;/a&gt;). That may mean a trip to the server&amp;rsquo;s physical location.&lt;/p&gt;
&lt;p&gt;Assuming that requirement is met, the repair itself is straightforward:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Boot into single-user mode.&lt;/strong&gt; For example, edit the kernel line in GRUB and add the keyword &lt;em&gt;single&lt;/em&gt; at the very end. This gives you a root console with no password prompt and no services running.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Unmount the corrupted filesystem&lt;/strong&gt; using &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://linux.die.net/man/8/umount&#34;
&gt;umount&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Run &lt;code&gt;xfs_repair&lt;/code&gt;&lt;/strong&gt; against that filesystem.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Minutes later, since &lt;code&gt;xfs_repair&lt;/code&gt; is usually quite fast, a normal reboot should bring the system back to its former glory. Some files may be missing, and some content or database tables may be corrupted, but that&amp;rsquo;s life. At least everything starts up normally again for now.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;conclusion&#34;
    &gt;
        Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/xfs_corruption/#conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Conclusion&#34; aria-label=&#34;Anchor Conclusion&#34; href=&#34;#conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Easy? It is. Well, until the next time&amp;hellip;&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Angry Birds: Following on your Passion</title>
            <link href="https://www.brainware.ro/posts/angry_birds_passion/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/angry_birds_passion/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2017-01-15T10:55:57+00:00</published>
            <updated>2017-01-15T10:55:57+00:00</updated>
            <content type="html">
                &lt;p&gt;This is meant to be a text about following your passion. Some people set out to save the world, while others go for seemingly simpler things, like &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Angry_Birds&#34;
&gt;popping green pigs&lt;/a&gt;. Don&amp;rsquo;t get me wrong: it&amp;rsquo;s not about the purpose &lt;em&gt;per se&lt;/em&gt;, but about the way you get there. It always comes down to work, and a lot of it.&lt;/p&gt;
&lt;p&gt;Looking at the screenshot below, you could easily conclude that at some point I became very, very efficient in the pig-popping business. After all, some of these golden eggs only unlock after winning 3 stars in around 60 different levels.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/screenshot-172807.webp&#34;
  alt=&#34;Golden Eggs&#34;
  
/&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The original &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Angry_Birds_%28video_game%29&#34;
&gt;Angry Birds&lt;/a&gt; game currently has about 500 different levels.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;How many hours did I spend on this game? Many? A lot? Days? Nights? Did I do anything else? (Is that even a &lt;em&gt;valid&lt;/em&gt; passion?)&lt;/p&gt;
&lt;p&gt;I know what everybody is thinking: that I either have no life, or that I cheated by tampering with the data on my phone&amp;rsquo;s storage. Both are false, by the way. I&amp;rsquo;m also not sure you could reach the state shown below by cheating. Of course, you can&amp;rsquo;t complete the Master League without power-ups, but &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Rovio_Entertainment&#34;
&gt;Rovio&lt;/a&gt; has a business to run, so that&amp;rsquo;s quite understandable.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/screenshot-215435.webp&#34;
  alt=&#34;Master League&#34;
  
/&gt;&lt;/p&gt;
&lt;p&gt;What if I told you I never spent a single penny on any of the in-game purchases? If you don&amp;rsquo;t use power-ups in the regular levels, they pile up, because the game hands some out from time to time. Everything up to the Silver League can be won comfortably without power-ups. The Gold League is hard to win without them, and the Master League is hard to win even with plenty. As for tickets, you can collect more than you&amp;rsquo;ll ever need through good old patience: open the game every day and don&amp;rsquo;t play any level for about 2 months.&lt;/p&gt;
&lt;p&gt;But let&amp;rsquo;s take a step back. What we&amp;rsquo;re really talking about here is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Passion&lt;/li&gt;
&lt;li&gt;A strong desire to win&lt;/li&gt;
&lt;li&gt;Starting early&lt;/li&gt;
&lt;li&gt;Many hours of work&lt;/li&gt;
&lt;li&gt;Patience&lt;/li&gt;
&lt;li&gt;Resource management&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope you now see that this text isn&amp;rsquo;t really about Angry Birds. It&amp;rsquo;s about following your passion all the way to the end. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" />
        </entry>
        <entry>
            <title>The &#34;Debugging&#34; Interview – a Few Pointers</title>
            <link href="https://www.brainware.ro/posts/debugging_interview/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/debugging_interview/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-12-28T10:32:57+00:00</published>
            <updated>2016-12-28T10:32:57+00:00</updated>
            <content type="html">
                &lt;p&gt;The long interview day is almost over. &lt;em&gt;Googamazbook&lt;/em&gt; has drawn out the best and the worst of you (well, neither, but I&amp;rsquo;m trying to sneak in some literature). The last interviewer walks in, smirks, and says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Time for the easy interview, heh?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You have every reason to worry that you&amp;rsquo;re one step from &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/how_to_fail_interview/&#34;
&gt;failure&lt;/a&gt;. Why didn&amp;rsquo;t you spend the day by the pool in the basement of that many-starred hotel they booked for you? Without further ado, the questions start coming.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-1&#34;
    &gt;
        Question 1
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/debugging_interview/#question-1&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 1&#34; aria-label=&#34;Anchor Question 1&#34; href=&#34;#question-1&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;How do you figure out whether a process is CPU bound or I/O bound?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is trickier than it looks. Two variables give four possibilities:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The process is CPU bound.&lt;/li&gt;
&lt;li&gt;The process is I/O bound.&lt;/li&gt;
&lt;li&gt;The process is both CPU and I/O bound.&lt;/li&gt;
&lt;li&gt;The process is neither.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the real world, most processes fall into the last category. They spend nearly their whole life in the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://man7.org/linux/man-pages/man1/ps.1.html&#34;
&gt;&lt;strong&gt;S&lt;/strong&gt; state&lt;/a&gt; (sleeping).&lt;/p&gt;
&lt;p&gt;Processes also rarely run one operation, or one fixed set of operations, and then exit. Over its lifetime, a process can be CPU bound at some moments and I/O bound at others, even if those moments are a tiny fraction of its run time. Watching &lt;strong&gt;top&lt;/strong&gt; or &lt;strong&gt;ps&lt;/strong&gt; for long stretches in state &lt;strong&gt;R&lt;/strong&gt; (running) or &lt;strong&gt;D&lt;/strong&gt; (uninterruptible sleep / I/O wait) may therefore tell you nothing useful.&lt;/p&gt;
&lt;p&gt;The conclusion: if you treat the process as a black box, you cannot answer the question. With access to the source code, you can find the relevant code blocks or add tracing. Otherwise, the best you can say is one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The process uses CPU in a way that would probably benefit from more computing power, at least for some operations.&lt;/li&gt;
&lt;li&gt;The process reads or writes large amounts of data and would probably benefit from faster storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The real trick is verifying either statement for an arbitrary black-box process. It isn&amp;rsquo;t hard, but you have to look under the operating system&amp;rsquo;s hood:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;High CPU usage&lt;/strong&gt; shows up in &lt;code&gt;/proc/pid/sched&lt;/code&gt;. Check &lt;code&gt;nr_involuntary_switches&lt;/code&gt; and &lt;code&gt;nr_voluntary_switches&lt;/code&gt;. If involuntary switches outnumber voluntary ones, the kernel is forcibly taking the process off the CPU, which suggests a CPU-intensive process.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High I/O&lt;/strong&gt; also shows up in &lt;code&gt;/proc/pid/sched&lt;/code&gt;, in the &lt;code&gt;se.statistics.iowait_sum&lt;/code&gt; attribute. This is an absolute figure, so correlate it with the process&amp;rsquo;s running time and compare it with other processes. Monitoring with &lt;strong&gt;ps&lt;/strong&gt; or &lt;strong&gt;top&lt;/strong&gt; is still the best approach for I/O.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Done? Yes. On to the next one.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-2&#34;
    &gt;
        Question 2
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/debugging_interview/#question-2&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 2&#34; aria-label=&#34;Anchor Question 2&#34; href=&#34;#question-2&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;How do you debug an unresponsive service?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is too general. First ask which service it is, and whether the node is still reachable some other way (for example, over ssh). The scenario usually involves a single unusable service on a node that is up and accessible. Otherwise, &amp;ldquo;reboot the node&amp;rdquo; would be the answer, and the bar can&amp;rsquo;t be that low for an interview like this.&lt;/p&gt;
&lt;p&gt;A typical exchange goes like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What service is it? &lt;em&gt;HTTP.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Is it accessed by IP or by name? &lt;em&gt;By name, via DNS.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Does DNS resolve the name to an IP? &lt;em&gt;Yes.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Is that the IP of the node with the unresponsive service? &lt;em&gt;Yes.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;On the node itself, is the service listening on the expected port? &lt;em&gt;Yes.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Is any firewall filtering that port? &lt;em&gt;No.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All the trivial explanations are now ruled out, so it&amp;rsquo;s time for the big guns. The scenario continues:&lt;/p&gt;
&lt;ol start=&#34;7&#34;&gt;
&lt;li&gt;Is the service up and running? &lt;em&gt;Yes.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;How many processes does the service have? &lt;em&gt;About 50.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;(Getting smart) What is the service&amp;rsquo;s process limit? &lt;em&gt;Around that number.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;(Eureka!) The service is overloaded, so raise the limits and do a graceful restart. &lt;em&gt;After doubling the limit, the service is still unresponsive.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can smell failure, as many candidates have before you. That&amp;rsquo;s a pity, because you could simply inspect individual processes and see where they&amp;rsquo;re blocked.&lt;/p&gt;
&lt;ol start=&#34;11&#34;&gt;
&lt;li&gt;Run &lt;code&gt;strace -p&lt;/code&gt; on individual processes to see what they&amp;rsquo;re doing. &lt;em&gt;They&amp;rsquo;re blocked in a &lt;code&gt;read()&lt;/code&gt; call on some file descriptor.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;(Past the mountain&amp;rsquo;s peak) Check &lt;code&gt;ls -la /proc/pid/fd/xx&lt;/code&gt;. &lt;em&gt;It&amp;rsquo;s a file under &lt;code&gt;/www/service&lt;/code&gt;.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;How is that path mounted? &lt;em&gt;It&amp;rsquo;s an NFS directory.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Is the NFS server reachable, e.g. via ping? &lt;em&gt;Yes.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Go to that server and run top, ps, and so on. &lt;em&gt;top reports 99% wa.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;(The cause is identified, now for the fix) Run &lt;code&gt;ps&lt;/code&gt; and look for processes in state &lt;strong&gt;D&lt;/strong&gt;. &lt;em&gt;&lt;code&gt;/usr/local/bin/maintenance.sh&lt;/code&gt; is in state D.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;What does it do? &lt;em&gt;It should prune some logs, but because of a bug it keeps repeating the job.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Try &lt;code&gt;kill -9&lt;/code&gt;, remove it from cron, and &lt;code&gt;chmod a-x&lt;/code&gt; the script. &lt;em&gt;That fixed it.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Crazy, wasn&amp;rsquo;t it? I made this scenario up myself, but it is a plausible interview exercise. A few pointers to remember:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The solution is never trivial (no client error, no external service error).&lt;/li&gt;
&lt;li&gt;The problem isn&amp;rsquo;t immediately visible with the usual tools (ps, top, df).&lt;/li&gt;
&lt;li&gt;The cause is almost never on the node where the symptoms appear, and the relationship between the nodes is rarely easy to work out.&lt;/li&gt;
&lt;li&gt;System call tracing is almost always needed to uncover that relationship.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On to the next question.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-3&#34;
    &gt;
        Question 3
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/debugging_interview/#question-3&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 3&#34; aria-label=&#34;Anchor Question 3&#34; href=&#34;#question-3&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;How would you deal with a &amp;ldquo;disk full&amp;rdquo; situation?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;First, two kinds of resources can run out and cause a &amp;ldquo;disk full&amp;rdquo; condition:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File system blocks (the actual storage of contents).&lt;/li&gt;
&lt;li&gt;Inodes (metadata).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So diagnosing the problem takes two commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# df&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:#75715e&#34;&gt;# df -i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The approach depends on the cause. Running out of space can usually be traced to one or a few very large files, while running out of inodes is caused by huge numbers of small files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Finding the largest files&lt;/strong&gt; is a job for &lt;code&gt;find&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# find / -type f -size +10M -printf &amp;#39;%k\t%p\n&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This prints the on-disk size (in KB) and path of every file larger than 10 MB. There are usually a few outliers of several gigabytes or more. Deleting them is easy but doesn&amp;rsquo;t always fix the problem, because a program may still have them open and be writing into them.&lt;/p&gt;
&lt;p&gt;To check, use &lt;code&gt;lsof&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# lsof | grep file_name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you can&amp;rsquo;t stop or restart the program after deleting the file, &lt;code&gt;truncate&lt;/code&gt; may help:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# truncate -s 0 file_name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You may also meet the opposite case: a very large file was deleted but is still held open by a program. The &lt;code&gt;find&lt;/code&gt; command above won&amp;rsquo;t show it, but &lt;code&gt;lsof&lt;/code&gt; will, and &lt;code&gt;truncate&lt;/code&gt; then finishes the job:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# lsof | grep &amp;#34;deleted&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:#75715e&#34;&gt;# truncate -s 0 /proc/pid/fd/xx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Inode exhaustion&lt;/strong&gt; is harder to fix. There are no outliers, just hundreds of thousands of files that may need deleting. Locating them takes some detective work: figure out what software runs on the node and whether anything changed in the last few days. &lt;code&gt;find&lt;/code&gt; helps again:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# find / -mtime -1 -print&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This lists files created or modified in the last day. For a more complex deletion example, see the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_4/&#34;
&gt;second question in this interview series&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for today. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/interview" term="interview" label="Interview" /> 
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" />
        </entry>
        <entry>
            <title>The &#34;Networking&#34; Interview - a few Pointers</title>
            <link href="https://www.brainware.ro/posts/networking_interview/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/networking_interview/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-12-21T11:07:57+00:00</published>
            <updated>2016-12-21T11:07:57+00:00</updated>
            <content type="html">
                &lt;p&gt;You&amp;rsquo;re sitting in a tiny room at &lt;em&gt;Googamazbook&lt;/em&gt;. The interviewer comes in, says hi (if you&amp;rsquo;re lucky), introduces themselves (they act like they&amp;rsquo;re doing you a favor) and starts with what seems like an easy question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What happens when you run &lt;strong&gt;&lt;code&gt;telnet www.brainware.ro 80&lt;/code&gt;&lt;/strong&gt;? Please go through all the layers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Warmed up by the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/systems_interview/&#34;
&gt;systems interview pointers&lt;/a&gt;, you start with &lt;em&gt;/etc/hosts&lt;/em&gt; and &lt;em&gt;/etc/resolv.conf&lt;/em&gt;: name resolution first, then the actual connection to the HTTP port. If your knowledge stops there, keep reading. If it doesn&amp;rsquo;t, keep reading anyway, in case something was missed.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-name-resolution&#34;
    &gt;
        1. Name Resolution
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/networking_interview/#1-name-resolution&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Name Resolution&#34; aria-label=&#34;Anchor 1. Name Resolution&#34; href=&#34;#1-name-resolution&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Name resolution works by sending a &lt;strong&gt;UDP&lt;/strong&gt; packet to &lt;em&gt;each&lt;/em&gt; resolver listed in &lt;strong&gt;/etc/resolv.conf&lt;/strong&gt;. The UDP header is small and contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Source port and destination port;&lt;/li&gt;
&lt;li&gt;Packet length (header + payload);&lt;/li&gt;
&lt;li&gt;Checksum.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The checksum is computed over a so-called UDP pseudoheader (which includes data from the protocol above it, such as the source and destination IP addresses) plus the payload. This is a tricky protocol detail.&lt;/p&gt;
&lt;p&gt;The IP address needed for the next stage is taken from the first response received (the exact response format is out of scope for an interview).&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-tcp-connection&#34;
    &gt;
        2. TCP Connection
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/networking_interview/#2-tcp-connection&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. TCP Connection&#34; aria-label=&#34;Anchor 2. TCP Connection&#34; href=&#34;#2-tcp-connection&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Everybody knows the &lt;strong&gt;SYN&lt;/strong&gt; / &lt;strong&gt;SYN-ACK&lt;/strong&gt; / &lt;strong&gt;ACK&lt;/strong&gt; sequence. But what is actually exchanged when the connection is initiated?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sequence numbers;&lt;/li&gt;
&lt;li&gt;MSS (maximum segment size: if a TCP payload larger than the MSS arrives in a single packet, the other side drops it);&lt;/li&gt;
&lt;li&gt;Receive window size (how much data the other side is able to receive).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From here, questions can escalate quickly, for example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;How does TCP detect that packets were lost in transit?&lt;/strong&gt; It doesn&amp;rsquo;t directly; a retransmission timer is used. The other side may also send packets from time to time with the ACK field set to the last sequence number received.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What is silly window syndrome?&lt;/strong&gt; The receiver keeps advertising tiny window sizes while the sender tries to push out as much data as it can. It is usually mitigated by both the sender (delaying data) and the receiver.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What is TCP Cork?&lt;/strong&gt; It delays data for up to a timer value (around 200 milliseconds) so that larger payloads can be sent when appropriate and possible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What are SYN cookies?&lt;/strong&gt; A defense against a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/SYN_flood&#34;
&gt;SYN flood&lt;/a&gt;. The initial sequence number is a specially crafted value that encodes the MSS and a connection signature.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What is a congestion window?&lt;/strong&gt; The amount of data one side may send without waiting for an ACK; it is dynamically resized up and down. In practice it is represented as a &amp;ldquo;window&amp;rdquo; over a circular buffer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why are there many TIME_WAIT connections in netstat that can&amp;rsquo;t be closed or removed?&lt;/strong&gt; This comes from the inner workings of TCP: connections can&amp;rsquo;t be guaranteed to close cleanly before a timeout. During those few minutes, any stray ACK packets belonging to the connection can still be received and handled properly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The discussion will soon move down to layer 3 (IP).&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-ip-connection&#34;
    &gt;
        3. IP Connection
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/networking_interview/#3-ip-connection&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. IP Connection&#34; aria-label=&#34;Anchor 3. IP Connection&#34; href=&#34;#3-ip-connection&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;As soon as you mention &lt;strong&gt;MSS&lt;/strong&gt;, the interviewer will probably ask how it differs from &lt;strong&gt;MTU&lt;/strong&gt;. They are distinct concepts: one applies to the TCP payload, the other to the total IP packet size. Exceeding one causes packets to be dropped; exceeding the other causes fragmentation. &lt;strong&gt;MSS&lt;/strong&gt; is communicated, while &lt;strong&gt;MTU&lt;/strong&gt; is discovered.&lt;/p&gt;
&lt;p&gt;An important topic is &lt;strong&gt;MTU&lt;/strong&gt; discovery. On both IPv4 and IPv6, this is done by sending maximum-size packets and listening for &amp;ldquo;fragmentation needed&amp;rdquo; ICMP replies. With IPv4, the &amp;ldquo;do not fragment&amp;rdquo; flag must be set for this to work. The ICMP responses (if any) carry the &lt;strong&gt;MTU&lt;/strong&gt; accepted by that node on the route.&lt;/p&gt;
&lt;p&gt;Some points worth mentioning about &lt;strong&gt;MTU&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The standard Ethernet value is 1500 bytes;&lt;/li&gt;
&lt;li&gt;Every transmission protocol (e.g. &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Wireless_LAN&#34;
&gt;WLAN&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Point-to-point_protocol_over_Ethernet&#34;
&gt;PPPoE&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Fiber_Distributed_Data_Interface&#34;
&gt;FDDI&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Token_ring&#34;
&gt;Token ring&lt;/a&gt;) has its own maximum value;&lt;/li&gt;
&lt;li&gt;IPv6 forbids fragmentation by intermediate nodes (only the source may fragment data as needed).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mentioning &amp;ldquo;Ethernet&amp;rdquo; leads the discussion to layer 2.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;4-data-link&#34;
    &gt;
        4. Data Link
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/networking_interview/#4-data-link&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 4. Data Link&#34; aria-label=&#34;Anchor 4. Data Link&#34; href=&#34;#4-data-link&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This layer is simpler to describe: the payload (most likely an IP datagram, but possibly ARP) is encapsulated in a frame with a header and a footer. The header usually holds the source and destination MAC addresses, an optional &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/IEEE_802.1Q&#34;
&gt;VLAN&lt;/a&gt; field, and a field indicating either the length or the payload type. The footer holds the checksum.&lt;/p&gt;
&lt;p&gt;The conversation may then turn to ARP, which is simply an IP-to-MAC resolution protocol. It works by broadcasting messages like &amp;ldquo;who has ip_address?&amp;rdquo; and answering with unicast messages like &amp;ldquo;ip_address is at mac_address&amp;rdquo;. Every node keeps a cache of the associations it knows about; entries expire within minutes, so ARP messages are sent regularly. Such a simple protocol is open to attacks, but that&amp;rsquo;s getting a bit far afield.&lt;/p&gt;
&lt;p&gt;Very few candidates get asked about the next layer, the physical link.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;5-physical-link&#34;
    &gt;
        5. Physical Link
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/networking_interview/#5-physical-link&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 5. Physical Link&#34; aria-label=&#34;Anchor 5. Physical Link&#34; href=&#34;#5-physical-link&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Layer 1: it can&amp;rsquo;t get any lower than this. With an Ethernet connection, the 1524 bytes (maximum MTU plus the Ethernet header) are placed between a header (the preamble) and a footer (the frame check sequence). These are handled by the firmware of the Ethernet device.&lt;/p&gt;
&lt;p&gt;Is that all? Not necessarily. There may still be time for variations.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;6-more-questions&#34;
    &gt;
        6. More Questions
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/networking_interview/#6-more-questions&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 6. More Questions&#34; aria-label=&#34;Anchor 6. More Questions&#34; href=&#34;#6-more-questions&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You still have 10 minutes left, and the interviewer wants to end on a high note:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How does &lt;strong&gt;DHCP&lt;/strong&gt; work?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can&amp;rsquo;t help thinking of &lt;em&gt;Dora the Explorer&lt;/em&gt;, and that&amp;rsquo;s actually a good thing: it means you read the docs! There are 4 steps before the client gets an IP address, two initiated by the client and two by the server:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;D&lt;/strong&gt;iscover;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;O&lt;/strong&gt;ffer;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;R&lt;/strong&gt;equest;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;/strong&gt;cknowledge.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Communication uses &lt;strong&gt;UDP&lt;/strong&gt; on port &lt;strong&gt;67&lt;/strong&gt; (server) and &lt;strong&gt;68&lt;/strong&gt; (client). The client has no IP address yet, so &lt;strong&gt;0.0.0.0&lt;/strong&gt; is used as the source address. The first packet is a broadcast, which means any device on the local network can receive it and possibly return an offer. The remaining 3 packets are unicast (sent to a specific MAC address).&lt;/p&gt;
&lt;p&gt;Follow-up:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why 4 packets? Wouldn&amp;rsquo;t the first 2 be enough?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Two would be enough if the protocol guaranteed that only a single DHCP server exists on the network. That isn&amp;rsquo;t the case, so the client must choose one of the offers to proceed with.&lt;/p&gt;
&lt;p&gt;As the next interviewer knocks on the door, the current one still has one last question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How does &lt;strong&gt;traceroute&lt;/strong&gt; work?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&amp;rsquo;s simple: it sends packets with increasing &lt;strong&gt;TTL&lt;/strong&gt; values and records the responses. All the usual protocols (ICMP, TCP, UDP) are supported. The &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://linux.die.net/man/8/traceroute&#34;
&gt;traceroute&lt;/a&gt; program also offers handy features such as &lt;strong&gt;MTU&lt;/strong&gt; discovery and gateway testing. There is also a simpler tool worth checking out: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://linux.die.net/man/8/tracepath&#34;
&gt;tracepath&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Even at this point the interview may not be over, but these pointers should help you make a good impression, or at least there&amp;rsquo;s hope. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/interview" term="interview" label="Interview" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" />
        </entry>
        <entry>
            <title>Crazy DevOps Interview Questions (4)</title>
            <link href="https://www.brainware.ro/posts/crazy_devops_interview_4/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/crazy_devops_interview_4/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-12-06T20:10:57+00:00</published>
            <updated>2016-12-06T20:10:57+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is the fourth article of the series. The others are: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_1/&#34;
&gt;part 1&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_2/&#34;
&gt;part 2&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/&#34;
&gt;part 3&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-1&#34;
    &gt;
        Question 1
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_4/#question-1&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 1&#34; aria-label=&#34;Anchor Question 1&#34; href=&#34;#question-1&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You have a shared document open when the phone rings. The interviewer, speaking with a thick accent, asks:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;What does &lt;code&gt;ls *&lt;/code&gt; do?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It sounds far too easy to be true. You say it lists all the files in the current directory. The interviewer asks a couple of follow-ups about how it works, and you explain that the star is passed to &lt;code&gt;ls&lt;/code&gt; as an argument, which somehow makes the binary walk the whole directory and print its contents. Simple!&lt;/p&gt;
&lt;p&gt;The interviewer thanks you and hangs up, and you&amp;rsquo;re left grinning. That lasts until the recruiter calls to suggest you try again in a year or two.&lt;/p&gt;
&lt;p&gt;So what actually happens when you run it in a Linux shell? You&amp;rsquo;d see something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ ls *
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1file 2file 3file
&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;4dir:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a b c d
&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;5file 6file
&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;7dir:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;e f g h
&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;8file 9file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that &lt;code&gt;ls&lt;/code&gt; descended one level into the subdirectories. That would be impossible if it only listed the current directory, so something else must be going on.&lt;/p&gt;
&lt;p&gt;There is no magic here. The &lt;strong&gt;shell&lt;/strong&gt; expands the star into a list of matching files and directories &lt;em&gt;before&lt;/em&gt; &lt;code&gt;ls&lt;/code&gt; runs, then hands that list to &lt;code&gt;ls&lt;/code&gt; as arguments. &lt;code&gt;ls&lt;/code&gt; then processes each argument in turn, listing files as they are and showing the contents of directories. This is the &amp;ldquo;trick&amp;rdquo; the interviewer is after, but a few more details are worth mentioning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hidden names are skipped.&lt;/strong&gt; The star expands only to names that don&amp;rsquo;t begin with a dot. Dot-files aren&amp;rsquo;t truly invisible. By convention, dot-prefixed names are reserved for local configuration files.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The argument list has a size limit.&lt;/strong&gt; If the expanded list has too many entries or is too long, you get a &amp;ldquo;too many files&amp;rdquo; style error. The limit is high and varies between systems, but it is finite. You could hit it if, say, a program writes status files into a single directory for a long time. The &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.gnu.org/software/coreutils/faq/#Argument-list-too-long&#34;
&gt;GNU Core Utilities FAQ&lt;/a&gt; explains this in more detail.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Empty directories behave differently.&lt;/strong&gt; If there is nothing for the star to match, the shell leaves it alone and passes a literal &lt;code&gt;*&lt;/code&gt; to &lt;code&gt;ls&lt;/code&gt;, which then reports a &amp;ldquo;not found&amp;rdquo; error.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you answered along these lines, expect follow-up questions about handling &amp;ldquo;too many files&amp;rdquo; errors. These are usually solved with &lt;a
  class=&#34;gblog-markdown__link--code&#34;
  href=&#34;https://linux.die.net/man/1/find&#34;
&gt;&lt;code&gt;find&lt;/code&gt;&lt;/a&gt;, which brings us to the next question.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-2&#34;
    &gt;
        Question 2
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_4/#question-2&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 2&#34; aria-label=&#34;Anchor Question 2&#34; href=&#34;#question-2&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The interviewer presents this scenario:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I tried to delete everything in the current folder with &lt;code&gt;rm -f *&lt;/code&gt; and got an &amp;lsquo;argument list too long&amp;rsquo; error. I really need those files gone.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As noted above, &lt;code&gt;find&lt;/code&gt; is the right tool because it enumerates files one at a time instead of building one giant argument list. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ find . -type f -print
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On its own this not very useful, but it is easy to turn into a scalable equivalent of &lt;code&gt;rm -f *&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ find . -maxdepth &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; -type f -delete
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you&amp;rsquo;d rather call &lt;code&gt;rm&lt;/code&gt; explicitly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ find . -maxdepth &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; -type f -exec rm -f &lt;span style=&#34;color:#f92672&#34;&gt;{}&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or you can pipe the results to &lt;code&gt;xargs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ find . -maxdepth &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; -type f -print0 | xargs -0 rm -f
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;-print0&lt;/code&gt; separates file names with a null character, and &lt;code&gt;xargs -0&lt;/code&gt; reads them back in that format. This is necessary for file names containing unusual characters such as spaces, tabs or newlines.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-3&#34;
    &gt;
        Question 3
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_4/#question-3&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 3&#34; aria-label=&#34;Anchor Question 3&#34; href=&#34;#question-3&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Having solved a hard problem, you get an easier one to finish the interview: rename every &lt;code&gt;.htm&lt;/code&gt; file in a directory tree to &lt;code&gt;.html&lt;/code&gt;. Sounds easy, right?&lt;/p&gt;
&lt;p&gt;Your first instinct is correct: use &lt;code&gt;find&lt;/code&gt; to locate the files.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ find . -type f -name &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*.htm&amp;#34;&lt;/span&gt; -print
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now what? You could pipe the output into a script, but the interviewer probably wants a one-liner. Here is the simplest approach:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ find . -type f -name &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*.htm&amp;#34;&lt;/span&gt; -exec mv -f &lt;span style=&#34;color:#f92672&#34;&gt;{}&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{}&lt;/span&gt;l &lt;span style=&#34;color:#ae81ff&#34;&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Did you spot the trick? &lt;code&gt;find&lt;/code&gt; replaces &lt;code&gt;{}&lt;/code&gt; with the current file name, so &lt;code&gt;{}l&lt;/code&gt; is the same name with an &lt;code&gt;l&lt;/code&gt; appended.&lt;/p&gt;
&lt;p&gt;The follow-up is harder: do the reverse and rename every &lt;code&gt;.html&lt;/code&gt; file to &lt;code&gt;.htm&lt;/code&gt;. This calls for some shell string manipulation using the &lt;code&gt;%&lt;/code&gt; operator:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ find . -type f -name &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*.html&amp;#34;&lt;/span&gt; -exec sh -c &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;f=&amp;#34;{}&amp;#34;; mv -f $f ${f%l}&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notes on the command above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-exec&lt;/code&gt; launches a shell with an inline script, and &lt;code&gt;find&lt;/code&gt; substitutes &lt;code&gt;{}&lt;/code&gt; with the file name.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The script is in &lt;strong&gt;single quotes&lt;/strong&gt; so the calling shell doesn&amp;rsquo;t expand &lt;code&gt;$f&lt;/code&gt; before the inline script runs. Without them, the assignment just before it would effectively be ignored. This is a tricky point. Try the following and compare what gets printed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ a&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;outside&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sh -c &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;a=&amp;#34;inside&amp;#34;; echo $a&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ sh -c &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;a=\&amp;#34;inside\&amp;#34;; echo &lt;/span&gt;$a&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;${f%l}&lt;/code&gt; looks odd, but it simply strips the trailing &lt;code&gt;l&lt;/code&gt; from the value stored in &lt;code&gt;$f&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m curious how many people could solve this in an interview without having worked through all these pitfalls first. Not many, I suspect.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for today. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/interview" term="interview" label="Interview" /> 
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>The &#34;Systems&#34; Interview - a Few Pointers</title>
            <link href="https://www.brainware.ro/posts/systems_interview/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/systems_interview/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-12-03T13:20:57+00:00</published>
            <updated>2016-12-03T13:20:57+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article is about Systems Programming on Linux platforms.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This kind of interview checks what &lt;em&gt;you&lt;/em&gt; know about what happens beneath the command-line surface. Down there, processes are created and terminated, output is collected, and system calls are made. Things get complicated quickly for anyone who is unprepared.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-what-happens-when-you-run&#34;
    &gt;
        Question: What happens when you run&amp;hellip;?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/systems_interview/#question-what-happens-when-you-run&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question: What happens when you run&amp;hellip;?&#34; aria-label=&#34;Anchor Question: What happens when you run&amp;hellip;?&#34; href=&#34;#question-what-happens-when-you-run&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ ls
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This classic interview question has been asked for more than 15 years. It may not come up much anymore (as of 2016), but the answer is still instructive. The question is not about the file listing that appears on screen, but about everything that happens to produce it.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;step-by-step&#34;
    &gt;
        Step by step
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/systems_interview/#step-by-step&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Step by step&#34; aria-label=&#34;Anchor Step by step&#34; href=&#34;#step-by-step&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;The shell parses the command line and identifies the command and its arguments (none here).&lt;/li&gt;
&lt;li&gt;The shell works out whether the command is:
&lt;ul&gt;
&lt;li&gt;a built-in (internal) command,&lt;/li&gt;
&lt;li&gt;an alias, or&lt;/li&gt;
&lt;li&gt;an external binary that must be located.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;On most systems, &lt;code&gt;ls&lt;/code&gt; is an alias for the real binary plus an option such as &lt;code&gt;--color=auto&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;As a safety step, the current directory is validated with &lt;code&gt;stat(&amp;quot;.&amp;quot;)&lt;/code&gt; before anything is executed.&lt;/li&gt;
&lt;li&gt;The shell searches for the binary by walking through each directory in the &lt;code&gt;PATH&lt;/code&gt; environment variable. It appends the command name to each one and calls &lt;code&gt;stat()&lt;/code&gt; on the result. &lt;code&gt;ls&lt;/code&gt; is usually in &lt;code&gt;/bin&lt;/code&gt;, so the search stops once &lt;code&gt;/bin/ls&lt;/code&gt; is confirmed as executable.&lt;/li&gt;
&lt;li&gt;The shell creates a new process with &lt;code&gt;fork()&lt;/code&gt;, then calls an &lt;code&gt;exec()&lt;/code&gt;-family function to run the binary with the arguments determined earlier.&lt;/li&gt;
&lt;li&gt;Boilerplate startup code runs: shared libraries are loaded, memory is allocated, signal masks are set, signal handlers are installed, and so on.&lt;/li&gt;
&lt;li&gt;Now the interesting part begins:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ls&lt;/code&gt; reads &lt;code&gt;/proc/filesystems&lt;/code&gt; and loads the current locale.&lt;/li&gt;
&lt;li&gt;It opens the current directory with &lt;code&gt;opendir()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It enumerates the entries with &lt;code&gt;readdir()&lt;/code&gt; and closes the directory with &lt;code&gt;closedir()&lt;/code&gt; (more memory may be allocated along the way).&lt;/li&gt;
&lt;li&gt;It writes the directory contents to standard output with &lt;code&gt;write(1, ...)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Finally, &lt;code&gt;ls&lt;/code&gt; releases its memory and exits.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It&amp;rsquo;s more involved than it first looks, isn&amp;rsquo;t it?&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;follow-up-what-about&#34;
    &gt;
        Follow-up: What about&amp;hellip;?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/systems_interview/#follow-up-what-about&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Follow-up: What about&amp;hellip;?&#34; aria-label=&#34;Anchor Follow-up: What about&amp;hellip;?&#34; href=&#34;#follow-up-what-about&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ ls | tee list.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The basic idea is simple: the standard output of &lt;code&gt;ls&lt;/code&gt; is piped into the standard input of &lt;code&gt;tee&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; stderr is not redirected in this case, so error messages will most likely go straight to the console.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;what-happens-behind-the-scenes&#34;
    &gt;
        What happens behind the scenes?
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/systems_interview/#what-happens-behind-the-scenes&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor What happens behind the scenes?&#34; aria-label=&#34;Anchor What happens behind the scenes?&#34; href=&#34;#what-happens-behind-the-scenes&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The shell still parses and executes everything. The earlier details still apply: built-in vs. alias vs. external command, and a &lt;code&gt;stat()&lt;/code&gt; in each &lt;code&gt;PATH&lt;/code&gt; directory until the binary is found. The difference is that the shell now identifies and launches &lt;strong&gt;two&lt;/strong&gt; external commands (&lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;tee&lt;/code&gt;), each in its own process.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;magic&amp;rdquo; happens &lt;em&gt;before&lt;/em&gt; &lt;code&gt;fork()&lt;/code&gt; and &lt;code&gt;exec()&lt;/code&gt;. Roughly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The shell asks the kernel for an unnamed pipe with the &lt;code&gt;pipe()&lt;/code&gt; system call, which returns a read end and a write end.&lt;/li&gt;
&lt;li&gt;The write end of the pipe is duplicated with &lt;code&gt;dup2()&lt;/code&gt; onto the stdout of the process that will run &lt;code&gt;ls&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The read end of the same pipe is duplicated with &lt;code&gt;dup2()&lt;/code&gt; onto the stdin of the process that will run &lt;code&gt;tee&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The shell collects the exit codes of both child processes. Even if the first one produces no output, the second one still runs, with empty input.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;digging-deeper&#34;
    &gt;
        Digging deeper:
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/systems_interview/#digging-deeper&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Digging deeper:&#34; aria-label=&#34;Anchor Digging deeper:&#34; href=&#34;#digging-deeper&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;An interviewer who knows this area well will probe how &lt;code&gt;fork()&lt;/code&gt; and &lt;code&gt;exec()&lt;/code&gt; behave at the kernel level. A strong candidate should be able to explain the following.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;fork()&lt;/code&gt;&lt;/strong&gt; duplicates the current process. Logically, nearly everything is copied: memory, file descriptors, and kernel resources such as references to shared memory segments or semaphores. Only the PID differs. If the process has several threads, only the thread that calls &lt;code&gt;fork()&lt;/code&gt; is duplicated, which can cause many hard-to-find bugs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copy-on-write:&lt;/strong&gt; the memory is not actually copied up front. Pages are marked read-only, and if either parent or child tries to modify one, a page fault occurs. The kernel then quietly duplicates the page and lets the write proceed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;exec()&lt;/code&gt;&lt;/strong&gt; replaces the process image with that of the new binary, and the kernel frees the previously allocated memory. File descriptors without the close-on-exec flag (&lt;code&gt;O_CLOEXEC&lt;/code&gt;) stay open and are available to the new program. By default, stdin, stdout, and stderr do not have this flag set.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;closing-thoughts&#34;
    &gt;
        Closing thoughts
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/systems_interview/#closing-thoughts&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Closing thoughts&#34; aria-label=&#34;Anchor Closing thoughts&#34; href=&#34;#closing-thoughts&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;As you can see, this kind of interview can get tough quickly. Fortunately, only a few companies run such &amp;ldquo;systems interviews,&amp;rdquo; and only for certain roles. If you have one coming up and spent a few minutes reading this, you&amp;rsquo;re likely better prepared than before. At least, that&amp;rsquo;s the hope. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/interview" term="interview" label="Interview" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" />
        </entry>
        <entry>
            <title>Amazon CloudFormation (an Introduction)</title>
            <link href="https://www.brainware.ro/posts/amazon_cloud_formation/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/amazon_cloud_formation/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-11-20T14:22:07+00:00</published>
            <updated>2016-11-20T14:22:07+00:00</updated>
            <content type="html">
                &lt;p&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudformation/&#34;
&gt;CloudFormation&lt;/a&gt; is Amazon Web Services&amp;rsquo; core tool for expressing &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Infrastructure_as_Code&#34;
&gt;infrastructure as code&lt;/a&gt;. Infrastructure is described in either JSON or YAML (the keywords are nearly identical), and a template designer can help assemble resources and their dependencies. The specifics of each resource still have to be written out by hand.&lt;/p&gt;
&lt;p&gt;From what I&amp;rsquo;ve seen, there is no limit on the kinds of resources you can define. Every resource type AWS offers can be coded, created and provisioned. You can set an explicit creation order (e.g. resource A before resource B) on top of the implicit order CloudFormation works out itself (e.g. an IAM role attached to an EC2 instance is always created first). Rollback is clean too: deleting a stack removes everything the stack created, and nothing is left behind.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;a-limitation-pre-existing-resources&#34;
    &gt;
        A Limitation: Pre-existing Resources
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_formation/#a-limitation-pre-existing-resources&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor A Limitation: Pre-existing Resources&#34; aria-label=&#34;Anchor A Limitation: Pre-existing Resources&#34; href=&#34;#a-limitation-pre-existing-resources&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;That same design has a downside: working with resources that already exist is awkward. For example, if you define a policy for an existing S3 bucket, it completely overwrites any policy already on the bucket, and deleting the stack leaves the bucket with no policy at all. There are workarounds using &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/lambda/latest/dg/welcome.html&#34;
&gt;Lambda functions&lt;/a&gt;, which are not covered here.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;template-structure&#34;
    &gt;
        Template Structure
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_formation/#template-structure&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Template Structure&#34; aria-label=&#34;Anchor Template Structure&#34; href=&#34;#template-structure&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;A stack file, in JSON or YAML, has three main sections:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parameters&lt;/strong&gt;: the inputs, e.g. the SSH key pair to use with newly provisioned EC2 servers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resources&lt;/strong&gt;: the contents of the stack (EC2 servers, security groups, Route 53 DNS entries, RDS databases, etc.).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Outputs&lt;/strong&gt;: typically public IP addresses, but possibly other values depending on the resources created.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; According to the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html&#34;
&gt;template anatomy documentation&lt;/a&gt;, &lt;strong&gt;Resources&lt;/strong&gt; is the only section that is strictly required. A template with no inputs and no outputs seems very limiting, though.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Constants (AMI IDs, node names, etc.) can be placed in a &lt;strong&gt;Mappings&lt;/strong&gt; section. &lt;strong&gt;Conditions&lt;/strong&gt; let you make decisions, such as creating or skipping certain resources, based on things like the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/general/latest/gr/rande.html&#34;
&gt;AWS Region&lt;/a&gt; or user-supplied &lt;strong&gt;Parameters&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;programmatic-constructs&#34;
    &gt;
        Programmatic Constructs
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_formation/#programmatic-constructs&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Programmatic Constructs&#34; aria-label=&#34;Anchor Programmatic Constructs&#34; href=&#34;#programmatic-constructs&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;As a coder at heart, I was drawn to the programmatic features CloudFormation offers. Here are a few JSON examples.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;using-user-inputs-ref&#34;
    &gt;
        Using user inputs (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html&#34;
&gt;Ref&lt;/a&gt;)
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_formation/#using-user-inputs-ref&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Using user inputs (Ref)&#34; aria-label=&#34;Anchor Using user inputs (Ref)&#34; href=&#34;#using-user-inputs-ref&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#f92672&#34;&gt;&amp;#34;Parameters&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:#f92672&#34;&gt;&amp;#34;KeyName&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:#f92672&#34;&gt;&amp;#34;Description&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Name of an existing EC2 KeyPair to enable SSH access to the instances&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:#f92672&#34;&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AWS::EC2::KeyPair::KeyName&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:#f92672&#34;&gt;&amp;#34;ConstraintDescription&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;must be the name of an existing EC2 KeyPair.&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:#f92672&#34;&gt;&amp;#34;InstanceType&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:#f92672&#34;&gt;&amp;#34;Description&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EC2 instances type&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:#f92672&#34;&gt;&amp;#34;Type&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;String&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:#f92672&#34;&gt;&amp;#34;Default&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;t2.micro&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:#f92672&#34;&gt;&amp;#34;AllowedValues&amp;#34;&lt;/span&gt; : [ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;t2.micro&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;m4.large&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;c4.large&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;r3.2xlarge&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:#f92672&#34;&gt;&amp;#34;ConstraintDescription&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;must be a valid EC2 instance type.&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:#e6db74&#34;&gt;&amp;#34;Resources&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:#f92672&#34;&gt;&amp;#34;MyEC2Instance&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:#f92672&#34;&gt;&amp;#34;Type&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AWS::EC2::Instance&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:#f92672&#34;&gt;&amp;#34;Properties&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:#f92672&#34;&gt;&amp;#34;InstanceType&amp;#34;&lt;/span&gt; : { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Ref&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;InstanceType&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:#f92672&#34;&gt;&amp;#34;KeyName&amp;#34;&lt;/span&gt; : { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Ref&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;KeyName&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;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;looking-up-constants-fnfindinmap&#34;
    &gt;
        Looking up constants (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html&#34;
&gt;Fn::FindInMap&lt;/a&gt;)
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_formation/#looking-up-constants-fnfindinmap&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Looking up constants (Fn::FindInMap)&#34; aria-label=&#34;Anchor Looking up constants (Fn::FindInMap)&#34; href=&#34;#looking-up-constants-fnfindinmap&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#f92672&#34;&gt;&amp;#34;Mappings&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:#f92672&#34;&gt;&amp;#34;InstanceValues&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:#f92672&#34;&gt;&amp;#34;Names&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;MyInstanceName&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;myec2.environment.local&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:#e6db74&#34;&gt;&amp;#34;Resources&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:#f92672&#34;&gt;&amp;#34;MyEC2Instance&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:#f92672&#34;&gt;&amp;#34;Type&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AWS::EC2::Instance&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:#f92672&#34;&gt;&amp;#34;Properties&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:#f92672&#34;&gt;&amp;#34;Tags&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:#f92672&#34;&gt;&amp;#34;Key&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;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:#f92672&#34;&gt;&amp;#34;Value&amp;#34;&lt;/span&gt; : { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Fn::FindInMap&amp;#34;&lt;/span&gt; : [ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;InstanceValues&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Names&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;MyInstanceName&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;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;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;joining-text-fnjoin&#34;
    &gt;
        Joining text (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html&#34;
&gt;Fn::Join&lt;/a&gt;)
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_formation/#joining-text-fnjoin&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Joining text (Fn::Join)&#34; aria-label=&#34;Anchor Joining text (Fn::Join)&#34; href=&#34;#joining-text-fnjoin&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#f92672&#34;&gt;&amp;#34;Parameters&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:#f92672&#34;&gt;&amp;#34;S3BucketName&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:#f92672&#34;&gt;&amp;#34;Description&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Name of an existing S3 bucket&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:#f92672&#34;&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;String&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:#e6db74&#34;&gt;&amp;#34;Resources&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:#f92672&#34;&gt;&amp;#34;EC2RolePolicy&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:#f92672&#34;&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AWS::IAM::Policy&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:#f92672&#34;&gt;&amp;#34;Properties&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:#f92672&#34;&gt;&amp;#34;PolicyName&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;MyEC2RolePolicy&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:#f92672&#34;&gt;&amp;#34;PolicyDocument&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:#f92672&#34;&gt;&amp;#34;Statement&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:#f92672&#34;&gt;&amp;#34;Effect&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Allow&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:#f92672&#34;&gt;&amp;#34;Action&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:#e6db74&#34;&gt;&amp;#34;s3:GetObject&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:#f92672&#34;&gt;&amp;#34;Resource&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Fn::Join&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arn:aws:s3:::&amp;#34;&lt;/span&gt;, { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Ref&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;S3BucketName&amp;#34;&lt;/span&gt; }, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/*&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;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;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;getting-the-arn-for-another-resource-fngetatt&#34;
    &gt;
        Getting the ARN for another resource (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html&#34;
&gt;Fn::GetAtt&lt;/a&gt;)
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_formation/#getting-the-arn-for-another-resource-fngetatt&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Getting the ARN for another resource (Fn::GetAtt)&#34; aria-label=&#34;Anchor Getting the ARN for another resource (Fn::GetAtt)&#34; href=&#34;#getting-the-arn-for-another-resource-fngetatt&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#f92672&#34;&gt;&amp;#34;Resources&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:#f92672&#34;&gt;&amp;#34;EC2Role&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:#f92672&#34;&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AWS::IAM::Role&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:#f92672&#34;&gt;&amp;#34;Properties&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:#f92672&#34;&gt;&amp;#34;AssumeRolePolicyDocument&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:#f92672&#34;&gt;&amp;#34;Statement&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:#f92672&#34;&gt;&amp;#34;Effect&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Allow&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:#f92672&#34;&gt;&amp;#34;Principal&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Service&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ec2.amazonaws.com&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:#f92672&#34;&gt;&amp;#34;Action&amp;#34;&lt;/span&gt;: [ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sts:AssumeRole&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:#f92672&#34;&gt;&amp;#34;Path&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/&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:#f92672&#34;&gt;&amp;#34;MyBucketPolicy&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:#f92672&#34;&gt;&amp;#34;DependsOn&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EC2Role&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:#f92672&#34;&gt;&amp;#34;Type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AWS::S3::BucketPolicy&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:#f92672&#34;&gt;&amp;#34;Properties&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:#f92672&#34;&gt;&amp;#34;Bucket&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Ref&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;MyBucketName&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:#f92672&#34;&gt;&amp;#34;PolicyDocument&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:#f92672&#34;&gt;&amp;#34;Statement&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:#f92672&#34;&gt;&amp;#34;Action&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;s3:GetObject&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:#f92672&#34;&gt;&amp;#34;Effect&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Allow&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:#f92672&#34;&gt;&amp;#34;Resource&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Fn::Join&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arn:aws:s3:::&amp;#34;&lt;/span&gt;, { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Ref&amp;#34;&lt;/span&gt; : &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;S3BucketName&amp;#34;&lt;/span&gt; } , &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/*&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:#f92672&#34;&gt;&amp;#34;Principal&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;AWS&amp;#34;&lt;/span&gt;: [ { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Fn::GetAtt&amp;#34;&lt;/span&gt; : [ &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;EC2Role&amp;#34;&lt;/span&gt; , &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Arn&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;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;More functions are available in CloudFormation templates; see the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html&#34;
&gt;intrinsic function reference&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;integrating-with-configuration-management-tools&#34;
    &gt;
        Integrating with Configuration Management Tools
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_formation/#integrating-with-configuration-management-tools&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Integrating with Configuration Management Tools&#34; aria-label=&#34;Anchor Integrating with Configuration Management Tools&#34; href=&#34;#integrating-with-configuration-management-tools&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;There are two main points of contact with tools such as &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.chef.io/chef/&#34;
&gt;Chef&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.ansible.com/&#34;
&gt;Ansible&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://puppet.com/&#34;
&gt;Puppet&lt;/a&gt; or &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://saltstack.com/&#34;
&gt;Salt&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html&#34;
&gt;Instance user data&lt;/a&gt;&lt;/strong&gt;: the bash provisioning script passed to newly created instances. With the constructs above, you can inject node names, fixed IP addresses, S3 bucket names, public SSH keys and more.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html&#34;
&gt;Security groups&lt;/a&gt;&lt;/strong&gt;: you can open ports for configuration management engines that use protocols other than SSH (e.g. HTTPS for Chef).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The recommended practice is to keep CloudFormation focused on defining infrastructure, including installing and configuring base system packages, and then hand control over to your configuration management tool of choice. That tool should take care of installing and configuring the services themselves.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for now. Thanks for reading!&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article was written by an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/amazon_certified_architect/&#34;
&gt;AWS Certified Solutions Architect (Associate)&lt;/a&gt;. Always work with an expert when setting up production environments.&lt;/p&gt;
&lt;/blockquote&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" /> 
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>When There’s no Route Forward (Or So You Fear)</title>
            <link href="https://www.brainware.ro/posts/no_route_forward/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/no_route_forward/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-11-14T20:08:07+00:00</published>
            <updated>2016-11-14T20:08:07+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is a reflection on project work done at one of my previous employers, covering a period from late 2000s to early 2010s.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;introduction&#34;
    &gt;
        Introduction
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/no_route_forward/#introduction&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Introduction&#34; aria-label=&#34;Anchor Introduction&#34; href=&#34;#introduction&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Agile, automation, DevOps and &amp;ldquo;continuous everything&amp;rdquo; are on everyone&amp;rsquo;s lips these days, yet very few people stop to ask why the industry moved this way. For many years, software projects followed a then- familiar routine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Thorough upfront planning, repeated before each major milestone.&lt;/li&gt;
&lt;li&gt;Long stretches of development behind closed doors.&lt;/li&gt;
&lt;li&gt;Mostly manual QA, with some automation likely built on a custom testing framework that one of the developers wrote from scratch.&lt;/li&gt;
&lt;li&gt;Rare releases, perhaps once a year or even every two years, preceded by careful testing and code freezes that sometimes lasted months.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We now know this was far from ideal, but it worked for a long time because it matched what the world expected. The constraints of that era explain a lot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hardware limits:&lt;/strong&gt; multi-core CPUs only reached consumers about 10 years ago (mid 2000s).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unreliable connectivity:&lt;/strong&gt; I was an early broadband adopter in my country 14 years ago (2002), when &amp;ldquo;broadband&amp;rdquo; meant roughly three times dial-up speed or about 16 KB/s.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Slow provisioning:&lt;/strong&gt; setting up test environments meant manual installs (yes, from CDs or DVDs), and only after management approved the hardware expense.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Immature virtualization:&lt;/strong&gt; VMs had existed since early 2000s, but until recently VMs were barely easier to configure than physical machines, and their performance was underwhelming.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was how things were done across our project and most others in the company. Nobody questioned the process until after we actually went live with the product and that&amp;rsquo;s when things began to fall apart.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;disaster&#34;
    &gt;
        Disaster?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/no_route_forward/#disaster&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Disaster?&#34; aria-label=&#34;Anchor Disaster?&#34; href=&#34;#disaster&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;For roughly two years, things went from bad to worse. The tension between the development and operations teams escalated into something close to open war, and management&amp;rsquo;s attempted fixes alienated people on both sides. In the end, most members of both teams left for other companies.&lt;/p&gt;
&lt;p&gt;With a few years of distance now, it&amp;rsquo;s clear that with the way things were going the collapse was inevitable, but then it could also have been avoided. So what went wrong?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Feature planning:&lt;/strong&gt; Before every major milestone, we spent 3-4 consecutive days discussing features, and we developers built most of what was agreed. About a year later, when the updated product shipped, the problems started to show. Some features weren&amp;rsquo;t needed at all, because Ops had requested them without knowing how the product would really work. Others were &amp;ldquo;buggy&amp;rdquo;: not from careless coding, but because the product behaved the way the developer imagined, not the way the operations person expected.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test automation:&lt;/strong&gt; We blamed the lack of QA time for the buggy releases and tried to introduce automation. We built a full high-level testing engine that ran command-line calls and checked the responses. It could never cover the product&amp;rsquo;s complexity, and by the time it was mostly finished, the product had moved on. Eventually QA spent most of its time maintaining the engine instead of testing new features.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance problems:&lt;/strong&gt; We initially took the blame for several performance issues. Later root-cause analysis pointed elsewhere: reporting scripts that dumped entire databases at once, and a badly configured monitoring setup that effectively amounted to a denial-of-service attack. Different members of the operations team had installed these without telling anyone.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open conflict:&lt;/strong&gt; At the peak, emails flew daily claiming that our software was buggy and unreliable. Meanwhile we were helping to fight fires and growing more frustrated, convinced we were doing our best to no avail. Looking back, I think everyone had a point, but at the time there was no quick or easy path to peace.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;management-response&#34;
    &gt;
        Management response
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/no_route_forward/#management-response&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Management response&#34; aria-label=&#34;Anchor Management response&#34; href=&#34;#management-response&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Eventually management stepped in and made things worse. They decided the root cause was our project management process, so we were told to move from &amp;ldquo;Waterfall&amp;rdquo; to Agile, with Sprints and regular &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Scrum_%28software_development%29&#34;
&gt;Scrum&lt;/a&gt; meetings.&lt;/p&gt;
&lt;p&gt;This was a step in the right direction in principle, but the execution was poor. We were already in firefighting mode, constantly reviewing, fixing and working around problems, and now we spent an hour or more every day in stand-ups that added little value. As the development team shrank with departures, this became the new normal.&lt;/p&gt;
&lt;p&gt;What did Agile actually change for us?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We had Sprints, but the workload stayed the same. Priorities may have become a little clearer, but tasks were still handled whenever a developer was free, and the backlog kept growing.&lt;/li&gt;
&lt;li&gt;We released no more features than before, because Operations &amp;ldquo;could not handle them&amp;rdquo;. The goal of a deliverable at the end of each Sprint was never met. We did ship frequent emergency fixes, but they had nothing to do with Sprint timing.&lt;/li&gt;
&lt;li&gt;We still held week-long planning sessions about the next year&amp;rsquo;s tasks, which undermined the whole point of Agile.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In short, Agile did little for us, given how we adopted it and how we kept interacting with Operations. The development team took the change as an undeserved punishment, and most people resigned within the following year.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;in-an-alternate-reality&#34;
    &gt;
        In an alternate reality
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/no_route_forward/#in-an-alternate-reality&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor In an alternate reality&#34; aria-label=&#34;Anchor In an alternate reality&#34; href=&#34;#in-an-alternate-reality&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;What should have been done? I&amp;rsquo;m convinced now that we should have adopted &lt;strong&gt;DevOps&lt;/strong&gt;. With the right mindset, many things were within reach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Merge Development and Operations so that they shared ownership of the production environment, in the literal sense of being in the same office and under the same manager.&lt;/li&gt;
&lt;li&gt;Set up a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Continuous_integration&#34;
&gt;Continuous Integration&lt;/a&gt; pipeline to free up QA time.&lt;/li&gt;
&lt;li&gt;Build a fast, frequent, automated deployment process.&lt;/li&gt;
&lt;li&gt;Replace manually configured servers and patchy scripting with proper configuration management.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We could have saved the project if management had made better decisions. Instead, everyone fell into &amp;ldquo;saving face&amp;rdquo; and &amp;ldquo;shifting blame&amp;rdquo; modes, and they probably just didn&amp;rsquo;t know of better ways of working.&lt;/p&gt;
&lt;p&gt;Until our very last day, we developers believed that writing the best possible code was the key to a good product. We also felt that even if we did our jobs well, management and Operations might sabotage the result, so the fight couldn&amp;rsquo;t be won. A few years on, I&amp;rsquo;ve learned that good code can only take you so far.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it for today. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" />
        </entry>
        <entry>
            <title>AWSome Day Bucharest 2016</title>
            <link href="https://www.brainware.ro/posts/awsome_day_2016/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/awsome_day_2016/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-11-08T12:46:57+00:00</published>
            <updated>2016-11-08T12:46:57+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You can find my comments on the similar event held in 2015 &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/awsome_day_2015/&#34;
&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another year, another &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com&#34;
&gt;AWS&lt;/a&gt; event. The venue changed and more speakers were brought in, but unfortunately they were of lower quality than &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.linkedin.com/in/sebastienstormacq&#34;
&gt;Sebastien Stormacq&lt;/a&gt;, the sole speaker in 2015. Registration doubled this year, with roughly 500 people queuing for the early-morning check-in.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/awsome-slide1.webp&#34;
  alt=&#34;Introduction slide from the event&#34;
  
/&gt;&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h2 id=&#34;two-tracks&#34;
    &gt;
        Two Tracks
    &lt;/h2&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/awsome_day_2016/#two-tracks&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Two Tracks&#34; aria-label=&#34;Anchor Two Tracks&#34; href=&#34;#two-tracks&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The biggest change from last year was that the content was split into two tracks, a &amp;ldquo;technical&amp;rdquo; room and a &amp;ldquo;business&amp;rdquo; room, each with their own focus.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Technical track topics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storage and content delivery (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/s3/&#34;
&gt;S3&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudfront/&#34;
&gt;CloudFront&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Compute and networking (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ec2/&#34;
&gt;EC2&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/vpc/&#34;
&gt;VPC&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Managed services and databases (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/rds/&#34;
&gt;RDS&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Elasticity and management services (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/elasticloadbalancing/&#34;
&gt;ELB&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Business track topics&lt;/strong&gt; (centered on the benefits of moving to the Cloud, such as flexibility and cost savings):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Benefits of Cloud Computing and defining a Cloud Strategy&lt;/li&gt;
&lt;li&gt;AWS Security&lt;/li&gt;
&lt;li&gt;Cloud Economics (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Total_cost_of_ownership&#34;
&gt;TCO&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;AWS partner programs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/awsome-slide2.webp&#34;
  alt=&#34;Business track slide&#34;
  
/&gt;&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h2 id=&#34;my-experience-in-the-business-track&#34;
    &gt;
        My Experience in the Business Track
    &lt;/h2&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/awsome_day_2016/#my-experience-in-the-business-track&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor My Experience in the Business Track&#34; aria-label=&#34;Anchor My Experience in the Business Track&#34; href=&#34;#my-experience-in-the-business-track&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I have attended the Business Track because I already knew the presented technical content well enough (I&amp;rsquo;m &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/amazon_certified_architect/&#34;
&gt;AWS CSA(A) certified&lt;/a&gt;), so my choice came down to curiosity. This led to a couple of unsettling observations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Very low interest in the business track.&lt;/strong&gt; Business attendees were outnumbered by technical ones by more than 15 to 1. Beyond the small turnout, the lack of engagement was obvious: many people were on their phones (possibly answering e-mails), and very few questions were asked at the end of each session. One attendee in my row, dressed in a full suit and tie, simply fell asleep.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. No apparent plans for a nearby Edge Location.&lt;/strong&gt; Amazon doesn&amp;rsquo;t seem in a hurry to expand its offering by opening an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/about-aws/global-infrastructure/&#34;
&gt;Edge Location&lt;/a&gt; closer, latency-wise, to Eastern (South-Eastern) Europe. Serving presentation content from 60-80 ms away may not be a problem, but moving internal real-time applications to the Cloud with that latency could make the user experience worse than a previous local data center solution, even if the Cloud is better on reliability and cost.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h2 id=&#34;conclusion&#34;
    &gt;
        Conclusion
    &lt;/h2&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/awsome_day_2016/#conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Conclusion&#34; aria-label=&#34;Anchor Conclusion&#34; href=&#34;#conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Until these two issues are somehow fixed, AWS technical expertise in my country will continue to be sold by the hour to external customers.&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/architecture" term="architecture" label="architecture" /> 
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" />
        </entry>
        <entry>
            <title>How to Fail a Big Company Interview (a Short Guide)</title>
            <link href="https://www.brainware.ro/posts/how_to_fail_interview/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/how_to_fail_interview/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-11-02T12:09:07+00:00</published>
            <updated>2016-11-02T12:09:07+00:00</updated>
            <content type="html">
                &lt;p&gt;So you&amp;rsquo;ve landed this incoming interview with &lt;em&gt;Googamazbook&lt;/em&gt;, and you&amp;rsquo;re determined to fail it. Or maybe you&amp;rsquo;re not determined, you just don&amp;rsquo;t trust the 99.9%+ rejection rate these companies are known for and would like some say in how you fail. Either way, you&amp;rsquo;re in the right place.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;stage-1-the-recruiter-screening&#34;
    &gt;
        Stage 1: The Recruiter Screening
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/how_to_fail_interview/#stage-1-the-recruiter-screening&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Stage 1: The Recruiter Screening&#34; aria-label=&#34;Anchor Stage 1: The Recruiter Screening&#34; href=&#34;#stage-1-the-recruiter-screening&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The recruiter screening is surprisingly hard to fail, especially if school had trained you to give the expected, correct answers. &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/pierre_gaulthier_failed_interview/&#34;
&gt;Some people&lt;/a&gt; do stumble here because they don&amp;rsquo;t &amp;ldquo;speak the same language&amp;rdquo; as the company&amp;rsquo;s current employees, but they&amp;rsquo;re a minority.&lt;/p&gt;
&lt;p&gt;So if:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;you&amp;rsquo;re set on failing the recruiter screening;&lt;/li&gt;
&lt;li&gt;you have plenty of experience;&lt;/li&gt;
&lt;li&gt;you were good at quizzes in school&amp;hellip;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;hellip;you&amp;rsquo;re practically guaranteed to pass. Sure, you could invent wrong answers, but that&amp;rsquo;s cheap. Let&amp;rsquo;s skip ahead.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;stage-2-the-phone-interview&#34;
    &gt;
        Stage 2: The Phone Interview
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/how_to_fail_interview/#stage-2-the-phone-interview&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Stage 2: The Phone Interview&#34; aria-label=&#34;Anchor Stage 2: The Phone Interview&#34; href=&#34;#stage-2-the-phone-interview&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Now you&amp;rsquo;re talking to an engineer, maybe two. No more quizzes, just problems to solve.&lt;/p&gt;
&lt;p&gt;Failing here is easier: solve the problem using a different method than the one your interviewer had in mind. You could offer a brute-force solution as a quick exit, but if you take pride in doing things well, that&amp;rsquo;s a real struggle. You&amp;rsquo;ll probably find the optimal solution and fail at failing. Fortunately, a few things can help:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Call quality:&lt;/strong&gt; If you can&amp;rsquo;t really understand the interviewer, failure is almost guaranteed. Even if you catch the rough ideas, you&amp;rsquo;ll miss on nuance and tone. Pray for a bad line, and firmly refuse any callback.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interviewer benevolence:&lt;/strong&gt; Sometimes you get a genuinely kind interviewer who wants to help you solve the problem. That makes failing very hard. You need to hope for someone with a radically different attitude.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open-ended questions:&lt;/strong&gt; Dive straight into the immediate problem as you see it. Never ask what&amp;rsquo;s actually needed or expected. If you ask clarifying questions first, you&amp;rsquo;re likely doomed to pass.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Questions at the end:&lt;/strong&gt; Ask only about perks and work/life balance. It&amp;rsquo;s no guaranteed fail, but you&amp;rsquo;re on the right track.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;stage-3-the-onsite&#34;
    &gt;
        Stage 3: The Onsite
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/how_to_fail_interview/#stage-3-the-onsite&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Stage 3: The Onsite&#34; aria-label=&#34;Anchor Stage 3: The Onsite&#34; href=&#34;#stage-3-the-onsite&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Against your wishes, you&amp;rsquo;ve made it to the onsite. Time to bring out the big guns.&lt;/p&gt;
&lt;p&gt;The lazy way to fail is not showing up. If they flew you to a new city, you could enjoy a free mini-vacation with most expenses covered. But you&amp;rsquo;re not that lazy: you show up on time, sober and prepared for the long day.&lt;/p&gt;
&lt;p&gt;The classic way to fail is not solving the interviewer&amp;rsquo;s problem, whether it&amp;rsquo;s a coding challenge or a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/debugging_interview/&#34;
&gt;debugging task&lt;/a&gt;. But some problems seem easy or average, which makes failing tough. A few ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Debugging scenario:&lt;/strong&gt; Stop as soon as you&amp;rsquo;ve found the issue the interviewer had in mind. They expect you to carry it through to a conclusion, such as a definitive fix. Leaving it without closure is an easy way to fail.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Architecture design scenario:&lt;/strong&gt; Propose &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Round-robin_DNS&#34;
&gt;round-robin DNS&lt;/a&gt; as the load-balancing strategy for your service. It&amp;rsquo;s a lightning-fast failure, so make a note of it. At some companies it may even shorten your interview day. More free time!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logging:&lt;/strong&gt; If logging comes up, stick to internal (local) logging and refuse to consider any alternatives.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If nothing works, trust the stats: at this stage, more than 90% of candidates don&amp;rsquo;t get an offer, so put your hopes to that.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;stage-4-the-references&#34;
    &gt;
        Stage 4: The References
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/how_to_fail_interview/#stage-4-the-references&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Stage 4: The References&#34; aria-label=&#34;Anchor Stage 4: The References&#34; href=&#34;#stage-4-the-references&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;A few days or weeks after the onsite, the recruiter asks for several people to vouch for you. That&amp;rsquo;s bad news, because even a lukewarm reference from someone who barely knows you could push you to an offer.&lt;/p&gt;
&lt;p&gt;Your best bet is to develop a multiple personality disorder, get phone numbers from another country, and answer the reference calls yourself, though that only works if you&amp;rsquo;re good at faking voices. Otherwise, try convincing someone to say something along the lines of &lt;em&gt;&amp;ldquo;Who? Don&amp;rsquo;t get me started on that lazy pr1ck!&amp;rdquo;&lt;/em&gt; That should do it.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;stage-5-the-offer&#34;
    &gt;
        Stage 5: The Offer
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/how_to_fail_interview/#stage-5-the-offer&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Stage 5: The Offer&#34; aria-label=&#34;Anchor Stage 5: The Offer&#34; href=&#34;#stage-5-the-offer&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Tough luck: at this point, you have to turn the offer down. But you won&amp;rsquo;t get here by following the advice in this article, so don&amp;rsquo;t give it too much thought.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for today. Thanks for reading!&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; This text is not necessarily based on my personal experiences, so please take any advice here with a grain of salt.&lt;/p&gt;
&lt;/blockquote&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" />
        </entry>
        <entry>
            <title>Pierre Gauthier’s Google Interview: My Opinion</title>
            <link href="https://www.brainware.ro/posts/pierre_gaulthier_failed_interview/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/pierre_gaulthier_failed_interview/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-10-18T15:11:07+00:00</published>
            <updated>2016-10-18T15:11:07+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;The original post, published in April 2016, is available &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://goo.gl/eIdw1R&#34;
&gt;here&lt;/a&gt; (original blog post by Pierre Gauthier). Business Insider had recently picked it up (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.businessinsider.com/google-engineer-interview-questions-2016-10&#34;
&gt;link&lt;/a&gt;) and sparked a lot of debate. My thoughts are below.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;First, the questions are typical of a recruiter screening stage at any large company. Some candidates know the answers, while others lack even the basic concepts and struggle through the whole test. At its core, the screening exists to reduce the &amp;ldquo;load&amp;rdquo; on later &amp;ldquo;interview layers&amp;rdquo;: phone interviews with engineers, followed by on-site interviews. No company can afford to have a highly trained engineer run this kind of test. Engineer time is expensive, it takes a mental toll, and it is likely to breed frustration given how large a share of candidates turn out to be unsuitable.&lt;/p&gt;
&lt;p&gt;Beyond the technical assessment, the screening also serves to catch a possible culture mismatch early. Does the candidate speak the same language? Not in the sense of English, but in the sense of whether they use the same words to describe technical concepts. Knowledge can be expressed in many forms, and not all of them are useful to everyone. For example, the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.openpcap.com/wireshark/tcp-3-way-handshake&#34;
&gt;0x02 SYN representation&lt;/a&gt; is certainly handy for low-level debugging, but it is of no use in a normal conversation, even with an engineer who knows the TCP stack well.&lt;/p&gt;
&lt;p&gt;Pierre seems to have failed the second layer of such screening, but also another one as well. There is a concept called &amp;ldquo;technical humility&amp;rdquo;, which is roughly the opposite of an inflated ego. Google in particular appears to have no use for such egos and places a very high value on technical humility: knowing when you don&amp;rsquo;t know enough, listening, respecting colleagues as human beings, and striving to become a better person and a better engineer every day.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Later edit:&lt;/strong&gt; Business Insider claims that Pierre gave a better answer to one of the questions, the one about counting bits in an array of integers:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At one point, on a question about how to most efficiently count data, he suggests a method that might be faster than the answer the recruiter wants, but the recruiter rejects it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is actually incorrect. The recruiter expected a &amp;ldquo;theoretical&amp;rdquo; answer, independent of any optimization a particular CPU may or may not offer. Counting bits by right-shifting is the brute-force solution to this problem, and it is roughly 8 times more expensive than using an 8-bit lookup table, or &lt;em&gt;k&lt;/em&gt; times more expensive than a &lt;em&gt;k&lt;/em&gt;-bit lookup table, assuming you have enough memory and the right computing architecture to implement it.&lt;/p&gt;
&lt;p&gt;In any case, this looks to me like a symptom of the &amp;ldquo;entrenching condition&amp;rdquo; I described in &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/companies_career_paths/&#34;title=&#34;On Companies and Career Paths: a personal overview&#34;
&gt;this earlier post&lt;/a&gt;.&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" />
        </entry>
        <entry>
            <title>Crazy DevOps Interview Questions (3)</title>
            <link href="https://www.brainware.ro/posts/crazy_devops_interview_3/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/crazy_devops_interview_3/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-09-11T14:32:57+00:00</published>
            <updated>2016-09-11T14:32:57+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is the third article of the series. The others are: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_1/&#34;
&gt;part 1&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_2/&#34;
&gt;part 2&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_4/&#34;
&gt;part 4&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-1&#34;
    &gt;
        Question 1
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/#question-1&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 1&#34; aria-label=&#34;Anchor Question 1&#34; href=&#34;#question-1&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The interviewer hands you this &lt;code&gt;ls -la&lt;/code&gt; listing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;ls -la
&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;total &lt;span style=&#34;color:#ae81ff&#34;&gt;108&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dr-xr-x---. &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;4096&lt;/span&gt; Sep &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; 07:16 .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dr-xr-xr-x. &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;4096&lt;/span&gt; Sep &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; 17:43 ..
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-------. &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;15432&lt;/span&gt; Sep &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; 06:36 .bash_history
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r--. &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;18&lt;/span&gt; May &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2009&lt;/span&gt; .bash_logout
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r--. &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;176&lt;/span&gt; May &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2009&lt;/span&gt; .bash_profile
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r--. &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;176&lt;/span&gt; Sep &lt;span style=&#34;color:#ae81ff&#34;&gt;23&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2004&lt;/span&gt; .bashrc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r--r-- &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; Sep &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; 07:16 -f
&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;They tell you the &lt;code&gt;-f&lt;/code&gt; file has to go. Can you delete it?&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;common-failed-attempts&#34;
    &gt;
        Common (failed) attempts:
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/#common-failed-attempts&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Common (failed) attempts:&#34; aria-label=&#34;Anchor Common (failed) attempts:&#34; href=&#34;#common-failed-attempts&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Quoting&lt;/strong&gt; (&lt;code&gt;rm &amp;quot;-f&amp;quot;&lt;/code&gt;): The shell strips the quotes, so &lt;code&gt;rm&lt;/code&gt; receives &lt;code&gt;-f&lt;/code&gt; as an option. It reports no error, because &lt;code&gt;-f&lt;/code&gt; tells &lt;code&gt;rm&lt;/code&gt; to ignore missing files, but nothing gets deleted.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escaping the minus&lt;/strong&gt; (&lt;code&gt;rm \-f&lt;/code&gt;): The shell processes the backslash, and &lt;code&gt;rm&lt;/code&gt; again receives a plain &lt;code&gt;-f&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Double-escaping&lt;/strong&gt; (&lt;code&gt;rm \\-f&lt;/code&gt;): &lt;code&gt;rm&lt;/code&gt; receives the literal string &lt;code&gt;\-f&lt;/code&gt;, which fails because a file named &lt;code&gt;\-f&lt;/code&gt; doesn&amp;rsquo;t exist (only &lt;code&gt;-f&lt;/code&gt; does).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many candidates give up here, which does not bode well for their employment chances.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;working-solutions&#34;
    &gt;
        Working solutions:
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/#working-solutions&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Working solutions:&#34; aria-label=&#34;Anchor Working solutions:&#34; href=&#34;#working-solutions&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Both are found in &lt;code&gt;man rm&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;--&lt;/code&gt; to mark the end of options:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;rm -- -f
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Prefix the filename with the current directory:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;rm ./-f
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;follow-up-question&#34;
    &gt;
        Follow-up question:
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/#follow-up-question&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Follow-up question:&#34; aria-label=&#34;Anchor Follow-up question:&#34; href=&#34;#follow-up-question&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Which characters are forbidden in filenames?&lt;/p&gt;
&lt;p&gt;The answer is that on Linux, only &lt;code&gt;\0&lt;/code&gt; (null, the string terminator) and &lt;code&gt;/&lt;/code&gt; are disallowed. Windows has a longer list.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-2&#34;
    &gt;
        Question 2:
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/#question-2&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 2:&#34; aria-label=&#34;Anchor Question 2:&#34; href=&#34;#question-2&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;At the whiteboard, write a cron definition for a file in &lt;code&gt;/etc/cron.d&lt;/code&gt; that appends the date/time to a file every Wednesday at 5 PM, using the format &lt;code&gt;%Y-%m-%d %H:%M:%S&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;An experienced candidate might quickly write:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;17&lt;/span&gt; * * &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; root date +’%Y-%m-%d %H:%M:%S’ &amp;gt;&amp;gt; /tmp/logfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Looks right, but it isn&amp;rsquo;t. Things you might check:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cron runs commands with the shell configured in &lt;code&gt;/etc/crontab&lt;/code&gt;, not your favorite one (irrelevant for such a simple command).&lt;/li&gt;
&lt;li&gt;Local &lt;code&gt;PATH&lt;/code&gt; changes aren&amp;rsquo;t visible, though &lt;code&gt;/bin&lt;/code&gt; is usually included.&lt;/li&gt;
&lt;li&gt;Local environment variables aren&amp;rsquo;t visible (none are used here).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, none of these is the culprit. &lt;strong&gt;The real problem is the &lt;code&gt;%&lt;/code&gt; character.&lt;/strong&gt; Cron treats it as a newline. The command gets split at each &lt;code&gt;%&lt;/code&gt; and passed to &lt;code&gt;/bin/sh&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;date +’
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Y-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;H:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;M:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;S’ &amp;gt;&amp;gt; /tmp/logfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This obviously produces an error. The fix is to escape every percent sign:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;17&lt;/span&gt; * * &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; root date +’&lt;span style=&#34;color:#ae81ff&#34;&gt;\%&lt;/span&gt;Y-&lt;span style=&#34;color:#ae81ff&#34;&gt;\%&lt;/span&gt;m-&lt;span style=&#34;color:#ae81ff&#34;&gt;\%&lt;/span&gt;d &lt;span style=&#34;color:#ae81ff&#34;&gt;\%&lt;/span&gt;H:&lt;span style=&#34;color:#ae81ff&#34;&gt;\%&lt;/span&gt;M:&lt;span style=&#34;color:#ae81ff&#34;&gt;\%&lt;/span&gt;S’ &amp;gt;&amp;gt; /tmp/logfile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-3&#34;
    &gt;
        Question 3
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/#question-3&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 3&#34; aria-label=&#34;Anchor Question 3&#34; href=&#34;#question-3&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;A mission-critical process is writing to a file whose contents must be preserved, but a junior admin just ran &lt;code&gt;rm -f&lt;/code&gt; on it. The process is still running, but in a few hours log rotation will send a &lt;code&gt;HUP&lt;/code&gt; signal to said process.&lt;/p&gt;
&lt;p&gt;Now, it&amp;rsquo;s less scary than it sounds:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find the process&amp;rsquo;s PID and inspect &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/fd&lt;/code&gt; to locate the deleted file&amp;rsquo;s descriptor:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;ls -la /proc/966/fd/10
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lrwx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; Sep &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; 08:56 /proc/966/fd/10 -&amp;gt; /var/lib/critical/process.out &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;deleted&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Copy out the contents:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;dd &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/proc/966/fd/10 of&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/tmp/recovered.out
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;But what about data written after &lt;code&gt;dd&lt;/code&gt; finishes?&lt;/strong&gt; Possible approaches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Send &lt;code&gt;SIGSTOP&lt;/code&gt; to freeze the process, copy the data with &lt;code&gt;dd&lt;/code&gt;, then kill or restart the service.&lt;/li&gt;
&lt;li&gt;Copy the data, then immediately send &lt;code&gt;SIGHUP&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Neither guarantees full preservation if the application buffers its output. (A mission-critical application should flush after every write, which is a good point to raise in the interview.)&lt;/p&gt;
&lt;p&gt;A cleaner solution uses &lt;a
  class=&#34;gblog-markdown__link--code&#34;
  href=&#34;http://man7.org/linux/man-pages/man1/tail.1.html&#34;
&gt;&lt;code&gt;tail&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;tail -f -n +0 /proc/966/fd/10 &amp;gt; /tmp/recovered.out
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This captures the whole file from the beginning and keeps following new writes. You can leave it running until the log rotation event if a faster restart isn&amp;rsquo;t desirable.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-4&#34;
    &gt;
        Question 4
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/#question-4&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 4&#34; aria-label=&#34;Anchor Question 4&#34; href=&#34;#question-4&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;A node has hit 100% storage. An administrator investigated but all visible file sizes look normal. The node can&amp;rsquo;t be restarted because of mission-critical software.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Diagnosis:&lt;/strong&gt; If no visible file is large enough, some process is probably holding a reference to a very large deleted file (or several deleted files that add up). &lt;a
  class=&#34;gblog-markdown__link--code&#34;
  href=&#34;http://linux.die.net/man/8/lsof&#34;
&gt;&lt;code&gt;lsof&lt;/code&gt;&lt;/a&gt; helps find it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;lsof | grep deleted | awk ‘&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;print $2,$4,$8,$9&lt;span style=&#34;color:#f92672&#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:#ae81ff&#34;&gt;2006&lt;/span&gt; 34w &lt;span style=&#34;color:#ae81ff&#34;&gt;24967&lt;/span&gt; /tmp/vteAIZ4MY
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2006&lt;/span&gt; 35u &lt;span style=&#34;color:#ae81ff&#34;&gt;28708&lt;/span&gt; /tmp/vteXJZ4MY
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2006&lt;/span&gt; 36w &lt;span style=&#34;color:#ae81ff&#34;&gt;28985&lt;/span&gt; /tmp/vteYU9XMY
&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 filters &lt;code&gt;lsof&lt;/code&gt; output for deleted files and prints four fields:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;PID&lt;/strong&gt; of the process holding the deleted file open;&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;file descriptor&lt;/strong&gt; (with access mode);&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;file size&lt;/strong&gt;, the field to look for;&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;file name&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once identified, there are two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reload or restart the process, e.g. &lt;code&gt;kill -HUP &amp;lt;pid&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Truncate the file, e.g. &lt;code&gt;truncate -s 0 /proc/&amp;lt;pid&amp;gt;/fd/&amp;lt;fd&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s it for today. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/interview" term="interview" label="Interview" /> 
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Book Review: How Google does SRE</title>
            <link href="https://www.brainware.ro/posts/book_review_google_sre/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/book_review_google_sre/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-09-04T20:02:57+00:00</published>
            <updated>2016-09-04T20:02:57+00:00</updated>
            <content type="html">
                &lt;p&gt;I&amp;rsquo;d like to share a book I&amp;rsquo;ve been working through for a while now. It&amp;rsquo;s a very dense read, packed with good practices and interesting details on how a team of exceptionally well-prepared people keeps planet-scale systems up and running.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/google-sre.webp&#34;
  alt=&#34;Site Reliability Engineering: How Google Runs Production Systems (SRE)&#34;
  
/&gt;&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h2 id=&#34;key-lessons-from-this-book&#34;
    &gt;
        Key lessons from this book
    &lt;/h2&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/book_review_google_sre/#key-lessons-from-this-book&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Key lessons from this book&#34; aria-label=&#34;Anchor Key lessons from this book&#34; href=&#34;#key-lessons-from-this-book&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SRE engineers should be software engineers at heart.&lt;/strong&gt; Infrastructure is now expressed as code, so the role demands strong engineering skills. Operational work should stay below 50% of an SRE&amp;rsquo;s time, because they have a dual mission: keeping today&amp;rsquo;s systems running while building tomorrow&amp;rsquo;s.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Going on call is the &amp;ldquo;rite of passage&amp;rdquo; for an SRE.&lt;/strong&gt; It follows naturally from the thorough preparation during the first months on the job. There is also a sweet spot for how often an engineer gets paged each week: too few incidents and they start to lose touch with production, too many and they may begin ignoring alerts or burn out.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The environment is designed to bring out the best in people and deliver the best results for the company.&lt;/strong&gt; Google looks for specific qualities in prospective SREs, which is a world of its own, but the core values that come through in the book are collaboration, mutual support, continuous improvement, and blameless post-incident analysis.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h2 id=&#34;technical-content&#34;
    &gt;
        Technical content
    &lt;/h2&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/book_review_google_sre/#technical-content&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Technical content&#34; aria-label=&#34;Anchor Technical content&#34; href=&#34;#technical-content&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Several chapters cover the technologies Google uses to run services at planetary scale (and beyond). The technical detail can get confusing at times. I personally found the chapter on &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Consensus_%28computer_science%29&#34;
&gt;consensus algorithms&lt;/a&gt; hard to follow. On the other hand, the chapters on load balancing are essential reading for anyone aiming to enter this field, whether or not they want to work at Google.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h2 id=&#34;where-to-get-it&#34;
    &gt;
        Where to get it
    &lt;/h2&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/book_review_google_sre/#where-to-get-it&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Where to get it&#34; aria-label=&#34;Anchor Where to get it&#34; href=&#34;#where-to-get-it&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Google has made the book freely available online (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://landing.google.com/sre/book/&#34;
&gt;link&lt;/a&gt;).&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/interview" term="interview" label="Interview" />  
                                <category scheme="https://www.brainware.ro/tags/architecture" term="architecture" label="architecture" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" />
        </entry>
        <entry>
            <title>Publishing to Atlassian Confluence (with Python)</title>
            <link href="https://www.brainware.ro/posts/atlassian_confluence_python/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/atlassian_confluence_python/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-08-19T18:32:57+00:00</published>
            <updated>2016-08-19T18:32:57+00:00</updated>
            <content type="html">
                &lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;introduction&#34;
    &gt;
        Introduction
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/atlassian_confluence_python/#introduction&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Introduction&#34; aria-label=&#34;Anchor Introduction&#34; href=&#34;#introduction&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This article shows how to automate the interaction with &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.atlassian.com/software/confluence&#34;
&gt;Atlassian Confluence&lt;/a&gt;, a commercial product widely used in companies to publish documentation and other content for a team, a department or the whole organization. It is usually integrated with other Atlassian tools such as &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.atlassian.com/software/bamboo&#34;
&gt;Bamboo&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.atlassian.com/software/jira&#34;
&gt;JIRA&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By &amp;ldquo;automating the interaction&amp;rdquo; I mean automated document publishing: you extract data from other systems with automated tools, then publish it in a readable format. This is possible through the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Representational_state_transfer&#34;
&gt;REST&lt;/a&gt; interface that Atlassian provides for its products. REST does not cover every feature, but it is enough for this scenario. The reference for Confluence Cloud is &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://docs.atlassian.com/atlassian-confluence/REST/latest/&#34;
&gt;here&lt;/a&gt;. The interface can differ between versions, so check the API reference for your own Confluence version.&lt;/p&gt;
&lt;p&gt;Now that we have the tools and the method, let&amp;rsquo;s get to the implementation, and to some code.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;prerequisites&#34;
    &gt;
        Prerequisites
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/atlassian_confluence_python/#prerequisites&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Prerequisites&#34; aria-label=&#34;Anchor Prerequisites&#34; href=&#34;#prerequisites&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;First, create the document the classic way, with the &amp;ldquo;Create&amp;rdquo; button in the web interface. A document &lt;em&gt;can&lt;/em&gt; be created through REST calls, but you would need to supply the &amp;ldquo;page key&amp;rdquo; and the &amp;ldquo;parent page id&amp;rdquo;, which are easy to read from the interface. Once the document exists, note down its &lt;strong&gt;page key&lt;/strong&gt; and &lt;strong&gt;page id&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;page key&lt;/strong&gt; is visible in the page URL.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;page id&lt;/strong&gt; becomes visible when you edit the page.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;document-retrieval&#34;
    &gt;
        Document Retrieval
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/atlassian_confluence_python/#document-retrieval&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Document Retrieval&#34; aria-label=&#34;Anchor Document Retrieval&#34; href=&#34;#document-retrieval&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;All the code below assumes a dictionary holding the credentials and the document identifiers:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;confluence_data &lt;span style=&#34;color:#f92672&#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:#e6db74&#34;&gt;&amp;#34;server&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;xxx&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:#e6db74&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;xxx&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:#e6db74&#34;&gt;&amp;#34;pass&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;xxx&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:#e6db74&#34;&gt;&amp;#34;page_key&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;xxx&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:#e6db74&#34;&gt;&amp;#34;page_id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;xxx&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Confluence does not accept an update unless the version number (an integer) is incremented. So you must first retrieve the document (as JSON, here) to read the current version, then increment it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; requests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; json
&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:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;confluence_retrieve&lt;/span&gt;(confluence_data):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;:&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;pass&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#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:#e6db74&#34;&gt;&amp;#39;@&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;server&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/confluence/rest/api/content/&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;page_id&amp;#39;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    headers &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;X-Atlassian-Token&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;no-check&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;content-type&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; requests&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get(url, headers&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;headers, verify&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;False&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:#66d9ef&#34;&gt;return&lt;/span&gt; int(response&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;json()[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;version&amp;#39;&lt;/span&gt;][&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;number&amp;#39;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;document-update&#34;
    &gt;
        Document Update
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/atlassian_confluence_python/#document-update&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Document Update&#34; aria-label=&#34;Anchor Document Update&#34; href=&#34;#document-update&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Updating a document takes a few steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Format the content in a representation Confluence accepts (details below).&lt;/li&gt;
&lt;li&gt;Generate a new version number by incrementing the old one.&lt;/li&gt;
&lt;li&gt;Build the payload (JSON here; XML also works).&lt;/li&gt;
&lt;li&gt;Send the PUT request and hope for the best.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;confluence_update&lt;/span&gt;(confluence_data, new_title, new_content):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    old_version &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; confluence_retrieve(confluence_data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    new_version &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; old_version &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&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;    url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;:&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;pass&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#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:#e6db74&#34;&gt;&amp;#39;@&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;server&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/confluence/rest/api/content/&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;page_id&amp;#39;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data &lt;span style=&#34;color:#f92672&#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:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;page_id&amp;#39;&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:#e6db74&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;page&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:#e6db74&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: new_title,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;space&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: confluence_data[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;page_key&amp;#39;&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:#e6db74&#34;&gt;&amp;#34;body&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:#e6db74&#34;&gt;&amp;#34;storage&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:#e6db74&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;: new_content,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;representation&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;wiki&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:#e6db74&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;number&amp;#34;&lt;/span&gt;: str(new_version)}
&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;    headers &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;X-Atlassian-Token&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;no-check&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;content-type&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; requests&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;put(url, headers&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;headers, data&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;json&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;dumps(data), verify&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;False&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:#66d9ef&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Confluence accepts several content representations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;plain&lt;/strong&gt;: plain text, used as provided with no special formatting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;wiki&lt;/strong&gt;: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://support.atlassian.com/confluence-cloud/docs/insert-confluence-wiki-markup/&#34;
&gt;Confluence wiki markup&lt;/a&gt;. This is &lt;em&gt;not&lt;/em&gt; the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Help:Wiki_markup&#34;
&gt;Wikipedia wiki markup&lt;/a&gt; but a different format. It is the easiest way to get nicely formatted documents.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;storage&lt;/strong&gt;: an HTML document, as it is meant to be displayed in the browser.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;conclusion&#34;
    &gt;
        Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/atlassian_confluence_python/#conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Conclusion&#34; aria-label=&#34;Anchor Conclusion&#34; href=&#34;#conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Automated document updating is a powerful way to distribute up-to-date information, such as service versions or usage patterns. As infrastructure grows, it may be the only way to keep support effort scaling sub-linearly with infrastructure size. That&amp;rsquo;s it for today. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/python" term="python" label="Python" />  
                                <category scheme="https://www.brainware.ro/tags/python" term="python" label="python" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Amazon EBS (Storage) Performance Limitation</title>
            <link href="https://www.brainware.ro/posts/amazon_ebs_limitation/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/amazon_ebs_limitation/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-08-07T15:23:07+00:00</published>
            <updated>2016-08-07T15:23:07+00:00</updated>
            <content type="html">
                &lt;p&gt;I have mentioned before that standard EBS storage in AWS runs on a credit system. Credits build up while a volume sits idle and are spent whenever the requested I/O rate rises above a predefined baseline. The details are covered in the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html&#34;title=&#34;EBS Volume Types&#34;
&gt;AWS documentation&lt;/a&gt;. This limitation caught me off guard during the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/going_cloud_failure/&#34;
&gt;failed project&lt;/a&gt; I had worked on 18 months ago.&lt;/p&gt;
&lt;p&gt;A few days ago I got the same problem while syncing data between 2 volumes, so I decided to capture what happened and share it here for anyone following this blog.&lt;/p&gt;
&lt;p&gt;The &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudwatch/&#34;
&gt;CloudWatch&lt;/a&gt; &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/ebs-metricscollected.html&#34;
&gt;read throughput&lt;/a&gt; graph (metric name: &lt;em&gt;VolumeReadOps&lt;/em&gt;) looked like this during the sync:&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/capture-diskperf.webp&#34;
  alt=&#34;Volume Performance&#34;
  
/&gt;&lt;/p&gt;
&lt;p&gt;I have marked the three areas that need explaining:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Credit consumption.&lt;/strong&gt; The volume was in &amp;ldquo;Credit Consumption&amp;rdquo; mode here. While credits lasted, performance stayed close to the maximum Amazon allows for this instance and volume type.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Credits exhausted.&lt;/strong&gt; Once credits ran out, this volume dropped back to its low baseline of 3 IOPS per GB, which works out to 150 for this 50GB volume.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Short idle period.&lt;/strong&gt; A brief pause let some credits accrue, which allowed a small burst before performance fell back to the low baseline again. Here it is in more detail:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/capture-diskperf2.webp&#34;
  alt=&#34;Volume Performance, detail&#34;
  
/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion?&lt;/strong&gt; Plan your AWS workloads carefully. Always monitor your CloudWatch metrics, and be ready to move to &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html&#34;
&gt;Provisioned IOPS&lt;/a&gt; volumes if needed.&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This post was written by an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/amazon_certified_architect/&#34;
&gt;AWS Certified Solutions Architect (Associate)&lt;/a&gt;. Please always work with an expert when setting up production environments.&lt;/p&gt;
&lt;/blockquote&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" /> 
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/architecture" term="architecture" label="architecture" /> 
                                <category scheme="https://www.brainware.ro/tags/performance" term="performance" label="performance" />
        </entry>
        <entry>
            <title>MySQL Monitoring with Amazon CloudWatch</title>
            <link href="https://www.brainware.ro/posts/amazon_cloudwatch_mysql/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/amazon_cloudwatch_mysql/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-06-24T18:49:07+00:00</published>
            <updated>2016-06-24T18:49:07+00:00</updated>
            <content type="html">
                &lt;p&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudwatch/&#34;
&gt;Amazon CloudWatch&lt;/a&gt; is the monitoring service for the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com&#34;
&gt;Amazon Cloud&lt;/a&gt;. It supports both &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/White_box_%28software_engineering%29&#34;
&gt;white box&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Black_box&#34;
&gt;black box&lt;/a&gt; monitoring of AWS-managed services, and it can also ingest custom monitoring data that you generate yourself.&lt;/p&gt;
&lt;p&gt;This guide shows how to integrate a simple &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/MySQL&#34;
&gt;MySQL&lt;/a&gt; monitoring script with CloudWatch.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;mysql-monitoring&#34;
    &gt;
        MySQL Monitoring
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloudwatch_mysql/#mysql-monitoring&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor MySQL Monitoring&#34; aria-label=&#34;Anchor MySQL Monitoring&#34; href=&#34;#mysql-monitoring&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Suppose you want to track the number of active connections to your MySQL server and get a signal when that number approaches the limit set by &lt;code&gt;max_connections&lt;/code&gt; in the configuration file. For portability, it&amp;rsquo;s also worth reporting the limit itself to the monitoring system, even though it rarely changes without someone editing the configuration.&lt;/p&gt;
&lt;p&gt;MySQL exposes three numeric values that are useful here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;max_connections&lt;/code&gt;&lt;/strong&gt;: a server variable, read with &lt;code&gt;SHOW VARIABLES&lt;/code&gt;. It is the maximum number of connections allowed, either as set in the config file or the default.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;threads_connected&lt;/code&gt;&lt;/strong&gt;: a status value, read with &lt;code&gt;SHOW STATUS&lt;/code&gt;. It is the number of connections open right now.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;max_used_connections&lt;/code&gt;&lt;/strong&gt;: also a status value from &lt;code&gt;SHOW STATUS&lt;/code&gt;. It is a high-water mark of the most connections ever used since the last server restart, so it never decreases.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All three are valuable, and you may want them plotted together on a single graph.&lt;/p&gt;
&lt;p&gt;Here is a simple shell script (&lt;code&gt;mysqlmon.sh&lt;/code&gt;) that retrieves them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#75715e&#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&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MYSQL_USER&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;xxxxx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;MYSQL_PASS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;xxxxx
&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:#66d9ef&#34;&gt;case&lt;/span&gt; $1 in
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	max_connections&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		mysql --user&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$MYSQL_USER --password&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$MYSQL_PASS -e &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;show variables like &amp;#39;max_connections&amp;#39;&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null | grep -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;max_connections&amp;#34;&lt;/span&gt; | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&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;	max_used_connections&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		mysql --user&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$MYSQL_USER --password&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$MYSQL_PASS -e &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;show status like &amp;#39;max_used_connections&amp;#39;&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null | grep -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;max_used_connections&amp;#34;&lt;/span&gt; | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&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;	threads_connected&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		mysql --user&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$MYSQL_USER --password&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;$MYSQL_PASS -e &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;show status like &amp;#39;threads_connected&amp;#39;&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null | grep -i &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;threads_connected&amp;#34;&lt;/span&gt; | awk &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{print $2}&amp;#39;&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:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Please provide one of max_connections, max_used_connections, threads_connected&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		exit &lt;span style=&#34;color:#ae81ff&#34;&gt;1&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:#66d9ef&#34;&gt;esac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With these point-in-time values available, the next step is to push them to CloudWatch.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;publishing-to-cloudwatch&#34;
    &gt;
        Publishing to CloudWatch
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloudwatch_mysql/#publishing-to-cloudwatch&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Publishing to CloudWatch&#34; aria-label=&#34;Anchor Publishing to CloudWatch&#34; href=&#34;#publishing-to-cloudwatch&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;To submit a custom metric, you need to supply a few details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Timestamp&lt;/strong&gt;: the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/cloudwatch_concepts.html#about_timestamp&#34;
&gt;time&lt;/a&gt; the reading applies to.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Metric name&lt;/strong&gt;: free text that will appear in the CloudWatch console.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Namespace&lt;/strong&gt;: also free text, but it must not collide with the reserved &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/aws-namespaces.html&#34;
&gt;AWS namespaces&lt;/a&gt;, which only Amazon&amp;rsquo;s own services may write to.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To tie the data to a specific instance, you also need to pass the instance ID, which is easy to obtain from the instance &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-data-retrieval&#34;
&gt;metadata&lt;/a&gt;. A minimal publishing script (&lt;code&gt;aws_mysql_pub.sh&lt;/code&gt;) looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#75715e&#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&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;max_connections&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;/usr/local/bin/mysqlmon.sh max_connections&lt;span style=&#34;color:#66d9ef&#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;max_used_connections&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;/usr/local/bin/mysqlmon.sh max_used_connections&lt;span style=&#34;color:#66d9ef&#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;threads_connected&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;/usr/local/bin/mysqlmon.sh threads_connected&lt;span style=&#34;color:#66d9ef&#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;cdate&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;date -u +%Y-%m-%dT%H:%M:00.000Z&lt;span style=&#34;color:#66d9ef&#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;instanceid&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;curl http://169.254.169.254/latest/meta-data/instance-id 2&amp;gt;/dev/null&lt;span style=&#34;color:#66d9ef&#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;aws cloudwatch put-metric-data --metric-name MySQLMaxConnections --namespace &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CustomMySQLMetrics&amp;#34;&lt;/span&gt; --dimensions&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;InstanceId=&lt;/span&gt;$instanceid&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; --value $max_connections --timestamp $cdate
&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;aws cloudwatch put-metric-data --metric-name MySQLMaxUsedConnections --namespace &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CustomMySQLMetrics&amp;#34;&lt;/span&gt; --dimensions&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;InstanceId=&lt;/span&gt;$instanceid&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; --value $max_used_connections --timestamp $cdate
&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;aws cloudwatch put-metric-data --metric-name MySQLThreadsConnected --namespace &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CustomMySQLMetrics&amp;#34;&lt;/span&gt; --dimensions&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;InstanceId=&lt;/span&gt;$instanceid&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; --value $threads_connected --timestamp $cdate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Installing and configuring the AWS CLI is outside the scope of this guide. Amazon&amp;rsquo;s &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/cli/latest/userguide/installing.html&#34;
&gt;installation tutorial&lt;/a&gt; covers it, and you&amp;rsquo;ll need an access key pair ready for the configuration. The key should belong to either the root user (a poor choice for &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/general/latest/gr/aws-access-keys-best-practices.html#root-password&#34;
&gt;many reasons&lt;/a&gt;) or, preferably, an IAM user with &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/UsingIAM.html&#34;
&gt;full CloudWatch access&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;how-often-should-it-run&#34;
    &gt;
        How often should it run?
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloudwatch_mysql/#how-often-should-it-run&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor How often should it run?&#34; aria-label=&#34;Anchor How often should it run?&#34; href=&#34;#how-often-should-it-run&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;That depends on your needs. Timestamps have a one-minute resolution, but that doesn&amp;rsquo;t restrict you: if you send several readings within the same sampling period, CloudWatch can compute statistics over them, such as minimum, maximum, average, and sum.&lt;/p&gt;
&lt;p&gt;For a one-minute interval, a basic cron entry is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;* * * * * /usr/local/bin/aws_mysql_pub.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;example-cloudwatch-graph&#34;
    &gt;
        Example CloudWatch Graph
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloudwatch_mysql/#example-cloudwatch-graph&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Example CloudWatch Graph&#34; aria-label=&#34;Anchor Example CloudWatch Graph&#34; href=&#34;#example-cloudwatch-graph&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The end result should look something like this:&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/cloudwatch-mysql-1p.webp&#34;
  alt=&#34;CloudWatch Custom Metrics&#34;
  
/&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The display can be tidied up, for example by scaling the right Y axis to match the left. You can also create alarms on the graphed values, but CloudWatch currently cannot trigger an alarm by comparing one metric against another.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Looking at the graph, you may wonder about cost. CloudWatch is one of the few AWS services whose &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/free/&#34;
&gt;free tier&lt;/a&gt; doesn&amp;rsquo;t expire after the first year. Full details are on the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudwatch/pricing/&#34;
&gt;pricing page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for now. Thanks for reading!&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This text was written by an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/amazon_certified_architect/&#34;
&gt;AWS Certified Solutions Architect (Associate)&lt;/a&gt;. Always consult an expert when setting up production environments.&lt;/p&gt;
&lt;/blockquote&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" /> 
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>On SLAs and Uptime Guarantees</title>
            <link href="https://www.brainware.ro/posts/sla_slo_uptime/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/sla_slo_uptime/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-06-15T10:55:07+00:00</published>
            <updated>2016-06-15T10:55:07+00:00</updated>
            <content type="html">
                &lt;p&gt;In this article, I look at the practical side of the &amp;ldquo;multiple nines&amp;rdquo; reliability figures that vendors love to advertise, and explain why a true 100% uptime is not something you can achieve.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;definitions&#34;
    &gt;
        Definitions
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/sla_slo_uptime/#definitions&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Definitions&#34; aria-label=&#34;Anchor Definitions&#34; href=&#34;#definitions&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;SLA&lt;/strong&gt; (Service Level Agreement) is a binding contract between a vendor and a customer. It is typically expressed as the percentage of a reference period (for example, a year) during which the service must work normally and deliver its intended output.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Uptime&lt;/strong&gt; is the numeric part of that agreement, expressed either as a percentage or as a unit of time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; These definitions don&amp;rsquo;t fully apply when a service is delivered from multiple infrastructure sets, such as different data centers serving different geographic regions. An outage in one region doesn&amp;rsquo;t mean every customer is affected, so a different calculation approach is needed. One option is to estimate the number of requests that went unserved during the outage, based on historical traffic data, and derive the availability figure from that.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;how-many-nines&#34;
    &gt;
        How Many Nines?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/sla_slo_uptime/#how-many-nines&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor How Many Nines?&#34; aria-label=&#34;Anchor How Many Nines?&#34; href=&#34;#how-many-nines&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;To run the numbers yourself, you can use &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://uptime.is/&#34;
&gt;this calculator&lt;/a&gt;. As a rough guide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;99.9%&lt;/strong&gt; allows about 9 hours of downtime per year.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;99.95%&lt;/strong&gt; allows just over 4 hours of downtime per year.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;99.99%&lt;/strong&gt; allows a little under 1 hour of downtime per year.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;99.999%&lt;/strong&gt; allows about 5 minutes of downtime per year.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com&#34;
&gt;Amazon Web Services&lt;/a&gt; offers a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ec2/sla/&#34;
&gt;99.95% SLA&lt;/a&gt; for &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ec2/&#34;
&gt;EC2&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ebs/&#34;
&gt;EBS&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;what-causes-downtime&#34;
    &gt;
        What Causes Downtime?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/sla_slo_uptime/#what-causes-downtime&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor What Causes Downtime?&#34; aria-label=&#34;Anchor What Causes Downtime?&#34; href=&#34;#what-causes-downtime&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Downtime causes fall into two broad categories: &lt;strong&gt;planned&lt;/strong&gt; and &lt;strong&gt;unplanned&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Planned downtime should be explicitly accounted for so that it fits within the SLA, possibly by using what&amp;rsquo;s known as an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.networkworld.com/article/936112/how-google-avoids-downtime.html&#34;
&gt;&amp;ldquo;error budget&amp;rdquo;&lt;/a&gt;. Unplanned downtime should also be anticipated and mitigated, though not every risk can be eliminated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Planned outages&lt;/strong&gt;, for example on a Linux web server, include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Operating system updates:&lt;/strong&gt; If a kernel upgrade requires a reboot, a single restart can cost roughly 2 minutes. Three such restarts in a year are enough to rule out 99.999% uptime.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service updates:&lt;/strong&gt; Depending on the service, downtime can be a few seconds, but it can also stretch to several minutes or even a significant fraction of an hour.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Unplanned outages&lt;/strong&gt; range from hardware failures (such as a server dying) to software problems (such as a critical bug in the latest release). You should have mitigation plans for these scenarios to protect your SLA. Be aware, though, that in some situations the SLA simply can&amp;rsquo;t be preserved no matter how much effort you invest, and that possibility needs to be factored in too.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Availability should also take into account the infrastructure between the end user and the service. Even if the service itself is perfectly available, a given user only experiences the uptime of their internet provider combined with that of every other component along the path. From that standpoint, offering an SLA above 99.9% may not bring much practical benefit to the average user, although it may still matter from a revenue-loss perspective.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;mitigating-unplanned-outages&#34;
    &gt;
        Mitigating Unplanned Outages
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/sla_slo_uptime/#mitigating-unplanned-outages&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Mitigating Unplanned Outages&#34; aria-label=&#34;Anchor Mitigating Unplanned Outages&#34; href=&#34;#mitigating-unplanned-outages&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;When the unexpected happens, consider approaches like these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rollback procedures:&lt;/strong&gt; Have a way to revert to the last known good software version, such as restoring a snapshot or re-running deployment scripts pointed at the previous version. The DevOps team should be able to do this without developer assistance, and ideally it should be automated so anyone can trigger it at any hour.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Failover architecture:&lt;/strong&gt; Replicate the service across multiple nodes. This is the approach Amazon recommends for achieving an SLA above 99.95%.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cold standby or rapid redeployment:&lt;/strong&gt; Keep a standby ready, or have procedures to quickly spin up a new node with the failed node&amp;rsquo;s configuration. This can be fully automated and triggered by a health check.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;conclusion&#34;
    &gt;
        Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/sla_slo_uptime/#conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Conclusion&#34; aria-label=&#34;Anchor Conclusion&#34; href=&#34;#conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;A 100% SLA is not achievable in any real-world scenario. That said, a failover architecture, such as multiple nodes serving the same service across different &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html&#34;
&gt;availability zones or regions&lt;/a&gt;, can go a long way toward earning those extra nines.&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article was written by an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/amazon_certified_architect/&#34;
&gt;AWS Certified Solutions Architect (Associate)&lt;/a&gt;. Always work with an expert when setting up production environments.&lt;/p&gt;
&lt;/blockquote&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" /> 
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" />  
                                <category scheme="https://www.brainware.ro/tags/architecture" term="architecture" label="architecture" /> 
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Instance Performance Monitoring in AWS</title>
            <link href="https://www.brainware.ro/posts/amazon_instance_monitoring/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/amazon_instance_monitoring/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-06-10T18:50:07+00:00</published>
            <updated>2016-06-10T18:50:07+00:00</updated>
            <content type="html">
                &lt;p&gt;AWS CloudWatch is Amazon&amp;rsquo;s built-in monitoring service. It collects metrics (including custom ones you define) and can trigger alarms when a metric crosses a threshold. It is the main tool for performance monitoring inside AWS.&lt;/p&gt;
&lt;p&gt;This guide covers a typical scenario: you&amp;rsquo;ve deployed an application to the cloud and need to work out whether performance problems come from the application code or from limits that Amazon enforces.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;scenario&#34;
    &gt;
        Scenario
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#scenario&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Scenario&#34; aria-label=&#34;Anchor Scenario&#34; href=&#34;#scenario&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You&amp;rsquo;ve just started with AWS and are running applications on the free tier or on general-purpose &lt;strong&gt;T2&lt;/strong&gt; instances. These instances use a &lt;strong&gt;CPU credit&lt;/strong&gt; system: credits let the instance burst through short load spikes, but once they run out, performance drops back to a low, fixed baseline. The details of the credit mechanics may seem obscure, but you still need to know whether your application can meet its service targets with this setup.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;prerequisites&#34;
    &gt;
        Prerequisites
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#prerequisites&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Prerequisites&#34; aria-label=&#34;Anchor Prerequisites&#34; href=&#34;#prerequisites&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;If you&amp;rsquo;re responsible for meeting service targets, you need control over the cloud environment. Treat the following as red flags:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You don&amp;rsquo;t have full access to the &lt;strong&gt;AWS Console&lt;/strong&gt;, so you can&amp;rsquo;t experiment with instance and storage volume types.&lt;/li&gt;
&lt;li&gt;You don&amp;rsquo;t have access to the monitoring engine (&lt;strong&gt;CloudWatch&lt;/strong&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;rsquo;re only handed a bare cloud server and told to deploy the application and hit service targets, walk away. You&amp;rsquo;re being set up for failure through no fault of your own.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;internal-monitoring&#34;
    &gt;
        Internal Monitoring?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#internal-monitoring&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Internal Monitoring?&#34; aria-label=&#34;Anchor Internal Monitoring?&#34; href=&#34;#internal-monitoring&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;AWS doesn&amp;rsquo;t expose hypervisor metrics from inside the instance. This is standard industry practice: monitoring should be external. From within the instance, enforced resource caps show up only as general slowness or timeouts.&lt;/p&gt;
&lt;p&gt;You can, however, retrieve static &lt;strong&gt;instance metadata&lt;/strong&gt; from inside the instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#f92672&#34;&gt;[&lt;/span&gt;root@ec2instance ~&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# curl http://169.254.169.254/latest/meta-data/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ami-id
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ami-launch-index
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ami-manifest-path
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;block-device-mapping/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hostname
&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;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;monitoring-with-cloudwatch&#34;
    &gt;
        Monitoring with CloudWatch
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#monitoring-with-cloudwatch&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Monitoring with CloudWatch&#34; aria-label=&#34;Anchor Monitoring with CloudWatch&#34; href=&#34;#monitoring-with-cloudwatch&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Every instance and volume has a console tab with graphs of hypervisor-generated metrics: CPU utilization, network traffic and I/O statistics. By default, nothing OS-level (memory, disk usage) is included, so you must define custom metrics for those. Amazon provides helper tools, such as the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://github.com/shinesolutions/aws-scripts-mon&#34;
&gt;CloudWatch Monitoring Scripts for Linux&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For an application on a performance-capped general-purpose instance, watch these metrics:&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;instance-metrics-cpu-credit-usage-and-cpu-credit-balance&#34;
    &gt;
        Instance metrics: CPU Credit Usage and CPU Credit Balance
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#instance-metrics-cpu-credit-usage-and-cpu-credit-balance&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Instance metrics: CPU Credit Usage and CPU Credit Balance&#34; aria-label=&#34;Anchor Instance metrics: CPU Credit Usage and CPU Credit Balance&#34; href=&#34;#instance-metrics-cpu-credit-usage-and-cpu-credit-balance&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Credit usage is a prime indicator of compute spikes.&lt;/li&gt;
&lt;li&gt;An exhausted balance means the hypervisor throttled your instance&amp;rsquo;s CPU.&lt;/li&gt;
&lt;li&gt;A constantly zero balance means a compute-intensive application is on the wrong instance type for the expected load. It can also point to a problem in the application itself. (The same behavior can be reproduced easily with a cryptocurrency miner or a fork bomb.)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;volume-metrics-average-queue-length&#34;
    &gt;
        Volume metrics: Average Queue Length
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#volume-metrics-average-queue-length&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Volume metrics: Average Queue Length&#34; aria-label=&#34;Anchor Volume metrics: Average Queue Length&#34; href=&#34;#volume-metrics-average-queue-length&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;If the value doesn&amp;rsquo;t return to 0 over extended periods, read or write operations routinely exceed the IOPS limits Amazon enforces.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read Throughput&lt;/strong&gt; and &lt;strong&gt;Write Throughput&lt;/strong&gt; give additional detail.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ways to address I/O pressure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Excessive reads:&lt;/strong&gt; use instances with more memory so caching absorbs them (common for web servers).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Excessive writes:&lt;/strong&gt; check for misconfigured logging and reduce the data written to the volume.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Otherwise:&lt;/strong&gt; use larger volumes (for gp2, the IOPS quota scales with volume size) or switch to provisioned IOPS (io1) volumes.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note 1:&lt;/strong&gt; The CPU credit system applies only to &amp;ldquo;T&amp;rdquo; (general-purpose) instance types. Other types deliver their nominal performance at all times.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note 2:&lt;/strong&gt; IOPS limits apply only to &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html&#34;
&gt;EBS (SSD) volumes&lt;/a&gt;. Some instance types include &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html&#34;
&gt;local instance storage&lt;/a&gt; with performance closer to raw hardware limits. Newer HDD types (st1, sc1) are throughput-limited rather than operation-limited.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;advanced-monitoring&#34;
    &gt;
        Advanced Monitoring
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#advanced-monitoring&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Advanced Monitoring&#34; aria-label=&#34;Anchor Advanced Monitoring&#34; href=&#34;#advanced-monitoring&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You can pull CloudWatch data with the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cli/&#34;
&gt;AWS CLI&lt;/a&gt;, which is useful for deeper analysis such as examining specific time periods. Installing the CLI is out of scope here; you&amp;rsquo;ll need a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html&#34;
&gt;key pair&lt;/a&gt; to use it.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;1-find-the-instance-and-volume-ids&#34;
    &gt;
        1. Find the instance and volume IDs
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#1-find-the-instance-and-volume-ids&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Find the instance and volume IDs&#34; aria-label=&#34;Anchor 1. Find the instance and volume IDs&#34; href=&#34;#1-find-the-instance-and-volume-ids&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You can also get these from the AWS Console, e.g. by instance name (if the &lt;code&gt;Name&lt;/code&gt; tag is set):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;aws ec2 describe-instances --filter Name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;tag:Name,Values&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;myinstance.local
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or by instance ID:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;aws ec2 describe-instances --instance-ids i-abcd1234
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the large JSON response, identify:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The instance ID&lt;/li&gt;
&lt;li&gt;The volume ID(s), if there is more than one&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;2-check-the-cpu-credit-balance&#34;
    &gt;
        2. Check the CPU credit balance
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#2-check-the-cpu-credit-balance&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Check the CPU credit balance&#34; aria-label=&#34;Anchor 2. Check the CPU credit balance&#34; href=&#34;#2-check-the-cpu-credit-balance&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;aws cloudwatch get-metric-statistics &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --metric-name CPUCreditBalance &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --start-time 2016-06-05T23:18:00 &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --end-time 2016-06-06T23:18:00 &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --period &lt;span style=&#34;color:#ae81ff&#34;&gt;3600&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --namespace AWS/EC2 &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --statistics Maximum &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --dimensions Name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;InstanceId,Value&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;i-abcd1234
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#f92672&#34;&gt;&amp;#34;Datapoints&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:#f92672&#34;&gt;&amp;#34;Timestamp&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2016-06-06T21:18:00Z&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:#f92672&#34;&gt;&amp;#34;Maximum&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;287.74&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:#f92672&#34;&gt;&amp;#34;Unit&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Count&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:#f92672&#34;&gt;&amp;#34;Timestamp&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2016-06-06T09:18:00Z&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:#f92672&#34;&gt;&amp;#34;Maximum&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;287.81&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:#f92672&#34;&gt;&amp;#34;Unit&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Count&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This example requests the &lt;em&gt;maximum&lt;/em&gt;, but &lt;em&gt;minimum&lt;/em&gt; may give better insight. Experiment with parameters to find the best combination. Datapoints are returned &lt;strong&gt;unsorted&lt;/strong&gt;, so import the JSON into another tool for analysis.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;3-list-the-metrics-available-for-each-volume&#34;
    &gt;
        3. List the metrics available for each volume
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#3-list-the-metrics-available-for-each-volume&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. List the metrics available for each volume&#34; aria-label=&#34;Anchor 3. List the metrics available for each volume&#34; href=&#34;#3-list-the-metrics-available-for-each-volume&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;aws cloudwatch list-metrics &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --namespace AWS/EBS &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --dimensions Name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;VolumeId,Value&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;vol-abcd1234
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#f92672&#34;&gt;&amp;#34;Metrics&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:#f92672&#34;&gt;&amp;#34;Namespace&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AWS/EBS&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:#f92672&#34;&gt;&amp;#34;Dimensions&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:#f92672&#34;&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;VolumeId&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vol-abcd1234&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:#f92672&#34;&gt;&amp;#34;MetricName&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;VolumeQueueLength&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:#f92672&#34;&gt;&amp;#34;Namespace&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AWS/EBS&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:#f92672&#34;&gt;&amp;#34;Dimensions&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:#f92672&#34;&gt;&amp;#34;Name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;VolumeId&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vol-abcd1234&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:#f92672&#34;&gt;&amp;#34;MetricName&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;VolumeReadOps&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that the metric names differ from the graph titles in the AWS Console.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h4 id=&#34;4-check-queue-length-per-volume&#34;
    &gt;
        4. Check queue length per volume
    &lt;/h4&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#4-check-queue-length-per-volume&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 4. Check queue length per volume&#34; aria-label=&#34;Anchor 4. Check queue length per volume&#34; href=&#34;#4-check-queue-length-per-volume&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;aws cloudwatch get-metric-statistics &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --metric-name VolumeQueueLength &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --start-time 2016-06-05T23:18:00 &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --end-time 2016-06-06T23:18:00 &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --period &lt;span style=&#34;color:#ae81ff&#34;&gt;3600&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --namespace AWS/EBS &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --statistics Sum &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --dimensions Name&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;VolumeId,Value&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;vol-abcd1234
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#f92672&#34;&gt;&amp;#34;Datapoints&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:#f92672&#34;&gt;&amp;#34;Timestamp&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2016-06-06T21:18:00Z&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:#f92672&#34;&gt;&amp;#34;Sum&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0643&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:#f92672&#34;&gt;&amp;#34;Unit&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Count&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:#f92672&#34;&gt;&amp;#34;Timestamp&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2016-06-06T09:18:00Z&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:#f92672&#34;&gt;&amp;#34;Sum&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0066&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:#f92672&#34;&gt;&amp;#34;Unit&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Count&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Every operation passes through the queue on its way to or from storage, so the sum is never exactly 0. What matters is how long requests wait in the queue: small values indicate healthy performance. As before, datapoints are unsorted, so you may need to import the JSON elsewhere to analyze it.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;conclusion&#34;
    &gt;
        Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_instance_monitoring/#conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Conclusion&#34; aria-label=&#34;Anchor Conclusion&#34; href=&#34;#conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;AWS instances don&amp;rsquo;t behave like physical servers: the hypervisor enforces various resource limits. Always monitor instance behavior through CloudWatch.&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article was written by an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/amazon_certified_architect/&#34;
&gt;AWS Certified Solutions Architect (Associate)&lt;/a&gt;. Always work with an expert when setting up production environments.&lt;/p&gt;
&lt;/blockquote&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" /> 
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/performance" term="performance" label="performance" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Cloud Distribution with AWS</title>
            <link href="https://www.brainware.ro/posts/amazon_cloud_distribution/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/amazon_cloud_distribution/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-06-02T10:20:07+00:00</published>
            <updated>2016-06-02T10:20:07+00:00</updated>
            <content type="html">
                &lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;when-do-you-need-cloud-distribution&#34;
    &gt;
        When Do You Need Cloud Distribution?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_distribution/#when-do-you-need-cloud-distribution&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor When Do You Need Cloud Distribution?&#34; aria-label=&#34;Anchor When Do You Need Cloud Distribution?&#34; href=&#34;#when-do-you-need-cloud-distribution&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Think of cloud distribution as a form of caching. You need it once your website passes a certain threshold of users and outgoing data volume. The exact figure depends entirely on your setup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You may serve large files, and sending them from your own server can use up your available bandwidth.&lt;/li&gt;
&lt;li&gt;You may have many users and want to ease the load on your server by pushing part of it elsewhere.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article shows how to do this with &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudfront/&#34;
&gt;AWS CloudFront&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;creating-the-cloudfront-distribution&#34;
    &gt;
        Creating the CloudFront Distribution
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_distribution/#creating-the-cloudfront-distribution&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Creating the CloudFront Distribution&#34; aria-label=&#34;Anchor Creating the CloudFront Distribution&#34; href=&#34;#creating-the-cloudfront-distribution&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;In the AWS Console, open &lt;strong&gt;CloudFront&lt;/strong&gt; and create a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-overview.html&#34;
&gt;Web distribution&lt;/a&gt;. On the creation page, first enter your domain name as the &lt;strong&gt;distribution origin&lt;/strong&gt; (the primary source of your content).&lt;/p&gt;
&lt;p&gt;Scroll down and pay attention to two more fields:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Price class&lt;/strong&gt;: Using only the US and Europe edge locations is cheaper. Choose this if your customers are located only in those regions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alternate domain name&lt;/strong&gt;: This is the address used to access content served by CloudFront. In this example, the subdomain is &lt;code&gt;cdn&lt;/code&gt; (short for &lt;strong&gt;c&lt;/strong&gt;ontent &lt;strong&gt;d&lt;/strong&gt;elivery &lt;strong&gt;n&lt;/strong&gt;etwork).&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The form has many other configurable fields. The three above are the ones that matter for this setup. Every field has its use, so you may want to come back later to fine-tune parameters.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When you&amp;rsquo;re done, click &lt;strong&gt;Create distribution&lt;/strong&gt; and wait about 10 to 15 minutes. When the status shows &lt;strong&gt;Deployed&lt;/strong&gt;, the distribution is ready.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h2 id=&#34;dns-record&#34;
    &gt;
        DNS Record
    &lt;/h2&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_distribution/#dns-record&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor DNS Record&#34; aria-label=&#34;Anchor DNS Record&#34; href=&#34;#dns-record&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Next, make the alternate domain name reachable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;If you use &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/route53/&#34;
&gt;Route 53&lt;/a&gt;:&lt;/strong&gt; create an alias record pointing to the distribution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If you manage DNS elsewhere:&lt;/strong&gt; create a CNAME record that resolves the alternate name (e.g. &lt;code&gt;cdn.brainware.ro&lt;/code&gt;) to the distribution domain name shown in the distribution&amp;rsquo;s properties (e.g. &lt;code&gt;xxx1234.cloudfront.net&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;updating-your-website-links&#34;
    &gt;
        Updating Your Website Links
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_distribution/#updating-your-website-links&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Updating Your Website Links&#34; aria-label=&#34;Anchor Updating Your Website Links&#34; href=&#34;#updating-your-website-links&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;With the AWS side configured, update your website so the resources you want distributed use the CDN-based URL.&lt;/p&gt;
&lt;p&gt;There is no way around this with URL rewriting or &lt;code&gt;.htaccess&lt;/code&gt; tricks, because those only act on requests that already arrive at your server. The goal is to avoid those requests altogether. With a cloud distribution, the first request for a resource is served by your own server, and subsequent requests (up to the TTL) are served by the cloud endpoints.&lt;/p&gt;
&lt;p&gt;For WordPress sites, plugins can handle this for you, for example &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://wordpress.org/plugins/w3-total-cache/&#34;
&gt;W3 Total Cache&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;practical-details&#34;
    &gt;
        Practical Details
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_cloud_distribution/#practical-details&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Practical Details&#34; aria-label=&#34;Anchor Practical Details&#34; href=&#34;#practical-details&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The full list of edge locations (data centers used by CloudFront) is on the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://aws.amazon.com/cloudfront/details/&#34;
&gt;AWS CloudFront Details page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Check the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html#limits_cloudfront&#34;
&gt;CloudFront service limits&lt;/a&gt;, such as the number of requests served per second, even though a typical website is unlikely to exceed them.&lt;/li&gt;
&lt;li&gt;See the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudfront/pricing/&#34;
&gt;detailed pricing&lt;/a&gt; on the AWS website. You are charged by usage only, not for simply setting up a distribution. Costs combine traffic volume and number of requests. Because the next bill can&amp;rsquo;t be fully predicted, setting up a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/free-tier-alarms.html&#34;
&gt;Billing Alarm&lt;/a&gt; is advised.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This text was written by an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/amazon_certified_architect/&#34;
&gt;AWS Certified Solutions Architect (Associate)&lt;/a&gt;. Always work with an expert when setting up production environments.&lt;/p&gt;
&lt;/blockquote&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" /> 
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/performance" term="performance" label="performance" />
        </entry>
        <entry>
            <title>Amazon Certified Solutions Architect (Associate)</title>
            <link href="https://www.brainware.ro/posts/amazon_certified_architect/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/amazon_certified_architect/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-05-27T19:50:07+00:00</published>
            <updated>2016-05-27T19:50:07+00:00</updated>
            <content type="html">
                &lt;p&gt;As of today, I&amp;rsquo;m officially an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://aws.amazon.com/certification/certified-solutions-architect-associate/&#34;
&gt;AWS Certified Solutions Architect – Associate&lt;/a&gt;. Certification numbers are issued sequentially, so I can infer that I&amp;rsquo;m the 16,891st person worldwide to earn this title. Since certifications must be renewed every two years, though, many of those who certified earlier might have probably let theirs lapse.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;starting-on-the-path&#34;
    &gt;
        Starting on the Path
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_certified_architect/#starting-on-the-path&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Starting on the Path&#34; aria-label=&#34;Anchor Starting on the Path&#34; href=&#34;#starting-on-the-path&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I have opened a personal AWS account in the second half of 2014, around the time I was assigned to the project I wrote about in my &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/going_cloud_failure/&#34;
&gt;previous post&lt;/a&gt;. I have barely used it, and still only use it for cloud backups. Without a professional reason to dig in, this path won&amp;rsquo;t take anyone very far.&lt;/p&gt;
&lt;p&gt;The turning point came when I started doing DevOps work for a customer of &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.endava.com/&#34;
&gt;my employer at the time&lt;/a&gt;. They had a fully configured AWS environment and gave me unrestricted access to that. Amazon recommends a year of hands-on experience before attempting the certification, and that is no arbitrary requirement: there&amp;rsquo;s a whole system to master before you can use it well.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;preparation&#34;
    &gt;
        Preparation
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_certified_architect/#preparation&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Preparation&#34; aria-label=&#34;Anchor Preparation&#34; href=&#34;#preparation&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;My certification journey began about a month ago, when I read &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://goo.gl/UVHfbY&#34;
&gt;this Reddit post&lt;/a&gt;. The timezone difference meant I couldn&amp;rsquo;t claim the free month of study that was on offer, but the idea had already taken some roots. Here&amp;rsquo;s what followed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Confusion at first.&lt;/strong&gt; For the first few days I didn&amp;rsquo;t know where to look or what to read. I didn&amp;rsquo;t want to pay for expensive courses and labs when I already had access to AWS environments where I could try everything myself or watch how it was done. I also wasn&amp;rsquo;t sure which certification to pursue (Architect, Developer or SysOps), especially since they overlap so much.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Course recordings.&lt;/strong&gt; Through an &amp;ldquo;alternate channel&amp;rdquo; (don&amp;rsquo;t ask), I obtained recordings of courses from two years earlier, first for SysOps, then for Architecture. I decided to do the Architecture track first, get certified, and then move on to SysOps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CloudAcademy.&lt;/strong&gt; After finishing the recordings (about 14 hours), I signed up for &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://cloudacademy.com/learning-paths/aws-solutions-architect-associate-2016-11/&#34;
&gt;CloudAcademy&lt;/a&gt; and used its free 7-day trial to the fullest. I worked through all the quizzes and the 157-question sample exam several times. Whenever I scored poorly on a topic, I opened the matching lab and followed along (for example, creating tables and indexes and working with &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/documentation/dynamodb/&#34;
&gt;DynamoDB&lt;/a&gt;). My goal was to score above 90% consistently on every quiz and on the final exam of that learning path.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blogs, forums and apps.&lt;/strong&gt; Once the trial ended, I searched blogs and forum posts for more material. Some recommended Android quiz apps, so I installed four. I returned the two paid ones within the two-hour refund window, but only after answering most, if not all, of their questions. By then I was already scoring above 90% consistently.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Whitepapers.&lt;/strong&gt; I then read Amazon whitepapers on key services (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ebs/&#34;
&gt;EBS&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/vpc/&#34;
&gt;VPC&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/route53/&#34;
&gt;Route 53&lt;/a&gt;). They cover details, such as EBS RAID configurations and special Route 53 record types, that aren&amp;rsquo;t found elsewhere, and the exam may include a few questions on them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Practice exam.&lt;/strong&gt; Feeling confident, I took the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.webassessor.com/aws&#34;
&gt;$20 practice exam&lt;/a&gt; and scored 90%. I then booked the real exam in the first available slot at the testing center.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The real thing.&lt;/strong&gt; A little stressed, I sat the exam and passed with an overall score of 83%.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;the-exam-itself&#34;
    &gt;
        The Exam Itself
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_certified_architect/#the-exam-itself&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor The Exam Itself&#34; aria-label=&#34;Anchor The Exam Itself&#34; href=&#34;#the-exam-itself&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I can&amp;rsquo;t share any exam questions, and I don&amp;rsquo;t remember many anyway. Some people take exams specifically to memorize questions or record them with devices, then sell the &amp;ldquo;dumps&amp;rdquo; to buyers. That&amp;rsquo;s a viable business, I suppose, but I suspect Amazon has hundreds of possible questions and gives each test taker a random 60 out of way too many.&lt;/p&gt;
&lt;p&gt;A few observations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You may get at least one question from the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://awstrainingandcertification.s3.amazonaws.com/production/AWS_certified_sysops_associate_examsample.pdf&#34;
&gt;sample questions&lt;/a&gt; on Amazon&amp;rsquo;s certification page, though those are on the easier side.&lt;/li&gt;
&lt;li&gt;You may also get one or more questions from the practice exam.&lt;/li&gt;
&lt;li&gt;Up to 33% of the questions fall into the &amp;ldquo;true or false: water is wet?&amp;rdquo; category, though they can still be hard if you&amp;rsquo;re not fully familiar with the topic.&lt;/li&gt;
&lt;li&gt;Another 33% are somewhat trickier, along the lines of &amp;ldquo;what feels more wet, water or oil?&amp;rdquo;&lt;/li&gt;
&lt;li&gt;The rest are frankly tough. They cover service internals or architecture decisions, such as which service to use for a given scenario. Often all or all but one option could legitimately work, but you must pick the one Amazon &lt;em&gt;recommends&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;About half the questions are multiple-answer, with no partial credit.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;logistics-and-costs&#34;
    &gt;
        Logistics and Costs
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_certified_architect/#logistics-and-costs&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Logistics and Costs&#34; aria-label=&#34;Anchor Logistics and Costs&#34; href=&#34;#logistics-and-costs&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The practice exam can be taken at home on your own computer. The real exam must be taken at a dedicated testing center. In my country there is only one such center for the entire country.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Total cost:&lt;/strong&gt; $20 for the practice exam + $150 for the certification exam.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;whats-next&#34;
    &gt;
        What&amp;rsquo;s Next
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/amazon_certified_architect/#whats-next&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor What&amp;rsquo;s Next&#34; aria-label=&#34;Anchor What&amp;rsquo;s Next&#34; href=&#34;#whats-next&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The future is still unwritten, but I&amp;rsquo;m considering the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://aws.amazon.com/certification/certified-sysops-admin-associate/&#34;
&gt;SysOps certification&lt;/a&gt; and one of the Professional-level certifications.&lt;/p&gt;
&lt;p&gt;Until then, thanks for reading!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/solutions-architect-associate.webp&#34;
  alt=&#34;AWS Certified Solutions Architect - Associate&#34;
  
/&gt;&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" />  
                                <category scheme="https://www.brainware.ro/tags/architecture" term="architecture" label="architecture" /> 
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" />
        </entry>
        <entry>
            <title>A Lesson on Failure: “Going Cloud”</title>
            <link href="https://www.brainware.ro/posts/going_cloud_failure/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/going_cloud_failure/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-05-25T11:20:07+00:00</published>
            <updated>2016-05-25T11:20:07+00:00</updated>
            <content type="html">
                &lt;p&gt;About a year ago, when I knew very little about &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Cloud_computing&#34;
&gt;Cloud Computing&lt;/a&gt; or &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/&#34;
&gt;Amazon Web Services&lt;/a&gt;, I was assigned, along with a few colleagues from the consulting company I worked for, to take an existing codebase from &amp;ldquo;alpha&amp;rdquo; to &amp;ldquo;production&amp;rdquo; and make sure it deployed smoothly to the Amazon cloud.&lt;/p&gt;
&lt;p&gt;The customer wanted to go live in under three months and expected to handle tens of thousands of visitors clicking on banner ads and generating revenue. More likely, they were hoping for a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.bloomberg.com/news/articles/2014-10-28/facebook-s-22-billion-whatsapp-deal-buys-10-million-in-sales&#34;
&gt;good exit&lt;/a&gt;: handing the hot potato to someone else while walking away with a tidy profit. There is a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/images/venture-dunce.webp&#34;
&gt;term for these people&lt;/a&gt;, but this isn&amp;rsquo;t a meme post, so I&amp;rsquo;ll leave it there.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;starting-the-new-project&#34;
    &gt;
        Starting the New Project
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/going_cloud_failure/#starting-the-new-project&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Starting the New Project&#34; aria-label=&#34;Anchor Starting the New Project&#34; href=&#34;#starting-the-new-project&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Things started off reasonably well. We worked through a long list of functional issues and ended up fixing more than 100 bugs and glitches. That was about all we could do, and it took us many long hours to get there.&lt;/p&gt;
&lt;p&gt;We didn&amp;rsquo;t concern ourselves with the cloud configuration. We knew almost nothing about it, and the customer guarded the &amp;ldquo;keys to the kingdom&amp;rdquo; closely, approving instance and resource setups only case by case. They probably felt they were overpaying their Eastern European contractors (us), so I understand why they watched the Amazon bill so carefully. It was their home, their needs and their rules, and that was fine with us.&lt;/p&gt;
&lt;p&gt;Overall, things went well from our side until performance testing began, but after that, everything fell apart. Within about a month, the project was taken away from us and then passed to different contractors, although I don&amp;rsquo;t think the product ever launched. These days the website domain is one of countless spam domains, abandoned and possibly resold a few times already.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;firefighting&#34;
    &gt;
        Firefighting
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/going_cloud_failure/#firefighting&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Firefighting&#34; aria-label=&#34;Anchor Firefighting&#34; href=&#34;#firefighting&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;What did the programmers and QA engineers see when things started going wrong?&lt;/p&gt;
&lt;p&gt;The performance tests were returning poor results. We had a &amp;ldquo;performance environment&amp;rdquo; that closely mirrored production configuration, so we expected test results to reflect real-world behavior.&lt;/p&gt;
&lt;p&gt;The metric falling short was &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Queries_per_second&#34;
&gt;Queries Per Second&lt;/a&gt; (QPS), a target previously agreed with the customer in our contract. Qualitatively, pages loaded slowly and timeouts were frequent. Simply navigating the site was painful because it was so sluggish and unpredictable.&lt;/p&gt;
&lt;p&gt;We were better software engineers than lawyers (oh, the irony), so all we could do was try to improve the software stack:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Backend:&lt;/strong&gt; The framework was &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.tornadoweb.org/en/stable/&#34;
&gt;Python Tornado&lt;/a&gt;, so we converted all &amp;ldquo;sync&amp;rdquo; operations to &amp;ldquo;async&amp;rdquo;. We were hunting for outliers that might be blocking the main server thread, but never properly identified any. The result was inconclusive: some tasks improved, others got worse.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database:&lt;/strong&gt; The database was &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.mongodb.com/&#34;
&gt;MongoDB&lt;/a&gt;, so we spent a lot of time optimizing queries and removing unneeded indexes. Again, there was no meaningful improvement.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the time the customer walked away, all of us were exhausted and frustrated.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;what-went-wrong&#34;
    &gt;
        What Went Wrong?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/going_cloud_failure/#what-went-wrong&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor What Went Wrong?&#34; aria-label=&#34;Anchor What Went Wrong?&#34; href=&#34;#what-went-wrong&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;It took me about a year to understand what actually happened. It wasn&amp;rsquo;t the software stack, but the customer&amp;rsquo;s &amp;ldquo;Cloud&amp;rdquo; (AWS) setup. I only reached this conclusion after working with AWS day to day and while preparing for the AWS certification I&amp;rsquo;m currently pursuing.&lt;/p&gt;
&lt;p&gt;In short, the customer relied heavily on the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/free/&#34;
&gt;AWS free tier&lt;/a&gt;. They used &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ec2/instance-types/&#34;
&gt;t2.micro&lt;/a&gt; instances for development and testing, and most likely &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ec2/instance-types/&#34;
&gt;t2.small&lt;/a&gt; or &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ec2/instance-types/&#34;
&gt;t2.large&lt;/a&gt; for the Mongo database. I don&amp;rsquo;t remember the production web instance setup, but we probably had no proper &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/elasticloadbalancing/&#34;
&gt;load balancer&lt;/a&gt;. Load may have been distributed through DNS round robin: each instance had an elastic IP and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/route53/&#34;
&gt;Route 53&lt;/a&gt; handled the balancing. Either way, all frontend instances used a single database node as their backend.&lt;/p&gt;
&lt;p&gt;Here is the detailed explanation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Burstable &amp;ldquo;T&amp;rdquo; instances:&lt;/strong&gt; These are marketed as general purpose. Their baseline performance is limited, and extra capacity comes from a credit system: credits accrue while the instance is idle and are spent during load spikes. This works well for many non-production scenarios, but not when sustainable performance is required.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EBS storage:&lt;/strong&gt; When creating instances with default storage settings (magnetic or general purpose), the volumes use the same credit model. During normal operation, Amazon throttles baseline IOPS (input/output operations per second) to a value well below what the underlying storage could deliver (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html&#34;
&gt;details&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Credit exhaustion:&lt;/strong&gt; Our performance tests burned through all accumulated EBS credits within the first few minutes, capping storage performance at a low baseline. On the database instance this appeared as high IO wait (the &lt;em&gt;wa&lt;/em&gt; field in &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/top&#34;
&gt;top&lt;/a&gt;). With our limited knowledge, we blamed poor application code rather than something external, i.e. the AWS-imposed limit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MongoDB&amp;rsquo;s access pattern:&lt;/strong&gt; MongoDB has an unpredictable storage access pattern by design, so there was likely never any burst capacity (idle-time credits) available in the first place. We often saw sluggish performance during normal daily work with no obvious cause.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;what-could-have-saved-the-day&#34;
    &gt;
        What Could Have Saved the Day?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/going_cloud_failure/#what-could-have-saved-the-day&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor What Could Have Saved the Day?&#34; aria-label=&#34;Anchor What Could Have Saved the Day?&#34; href=&#34;#what-could-have-saved-the-day&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Two things might have helped:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://docs.mongodb.com/v3.0/core/sharded-cluster-components/&#34;
&gt;MongoDB sharding&lt;/a&gt; on every frontend instance.&lt;/strong&gt; This could have spread I/O across the whole cluster and likely mitigated the single-point-of-failure database design. On the downside, it might have caused memory swapping on &lt;code&gt;t2.micro&lt;/code&gt; instances, cancelling out any benefit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/about-aws/whats-new/2012/07/31/announcing-provisioned-iops-for-amazon-ebs/&#34;
&gt;Provisioned IOPS&lt;/a&gt; for EBS storage.&lt;/strong&gt; A dedicated DevOps engineer, which we didn&amp;rsquo;t have, could have monitored the &amp;ldquo;average queue length&amp;rdquo; metric and recreated the volume with the right provisioning to balance performance and cost.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Neither happened. Sharding was only mentioned when we were already in a downward spiral and it was too late to do anything meaningful.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;conclusion&#34;
    &gt;
        Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/going_cloud_failure/#conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Conclusion&#34; aria-label=&#34;Anchor Conclusion&#34; href=&#34;#conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;When moving to the cloud, put a Cloud Architect on the team. It may be the single biggest difference between success and failure. Also, a cloud provider&amp;rsquo;s free tier is free for a reason, and that reason may be less obvious than what&amp;rsquo;s written in the marketing material.&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Two days after writing this post, I passed the
&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/amazon_certified_architect/&#34;
&gt;AWS Certified Solutions Architect (Associate)&lt;/a&gt; exam. Please always work with an expert when setting up production environments.&lt;/p&gt;
&lt;/blockquote&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/aws" term="aws" label="AWS" /> 
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/python" term="python" label="python" />
        </entry>
        <entry>
            <title>The Second Level LPIC Certification (LPIC-2): How To</title>
            <link href="https://www.brainware.ro/posts/lpic-2-certification/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/lpic-2-certification/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-04-29T10:27:07+00:00</published>
            <updated>2016-04-29T10:27:07+00:00</updated>
            <content type="html">
                &lt;p&gt;As I mentioned in the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/lpic-1-certification/&#34;title=&#34;How to get LPIC-1&#34;
&gt;first post of the certification series&lt;/a&gt;, I took the next step up in LPI&amp;rsquo;s certification ladder and earned &lt;strong&gt;LPIC-2&lt;/strong&gt; (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://cs.lpi.org/caf/Xamman/certification/verify/LPI000352547/dyxgmhunj8&#34;
&gt;verify&lt;/a&gt;). Was it easy? Was it hard? Let&amp;rsquo;s find out.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;introduction&#34;
    &gt;
        Introduction
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/lpic-2-certification/#introduction&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Introduction&#34; aria-label=&#34;Anchor Introduction&#34; href=&#34;#introduction&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;LPIC-2 is awarded after passing two exams, but only if you already hold a &lt;strong&gt;LPIC-1&lt;/strong&gt; certification. In total, that means four exams to go from zero to LPIC-2.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.lpi.org/our-certifications/exam-201-202-objectives/&#34;
&gt;Exam 201&lt;/a&gt;&lt;/strong&gt;: Advanced system administration, including kernel and boot loader configuration, filesystems and troubleshooting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.lpi.org/our-certifications/exam-201-202-objectives/&#34;
&gt;Exam 202&lt;/a&gt;&lt;/strong&gt;: Common services such as e-mail, HTTP, proxies and file sharing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As with LPIC-1, the exams can be taken in any order, and the certification is granted once both are passed.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;logistics&#34;
    &gt;
        Logistics
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/lpic-2-certification/#logistics&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Logistics&#34; aria-label=&#34;Anchor Logistics&#34; href=&#34;#logistics&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I took both exams at a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.pearsonvue.com/lpi/&#34;
&gt;Pearson VUE test center&lt;/a&gt; (two different locations, in fact). Each exam normally costs around EUR 150. The second one was paid for by &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.endava.com/&#34;title=&#34;Endava&#34;
&gt;my current employer&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;preparation&#34;
    &gt;
        Preparation
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/lpic-2-certification/#preparation&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Preparation&#34; aria-label=&#34;Anchor Preparation&#34; href=&#34;#preparation&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Everything I said in the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/lpic-1-certification/&#34;title=&#34;Getting LPIC-1&#34;
&gt;first post&lt;/a&gt; still holds. Books alone won&amp;rsquo;t get you through, and neither will light hands-on experience. The questions aren&amp;rsquo;t tricky: if you have actually used the software or worked through the scenarios, the answer comes quickly. If not, guessing won&amp;rsquo;t save you. I also noticed that some questions appear (seemingly at random) in both the level 1 and level 2 exams, so the boundary between &amp;ldquo;harder&amp;rdquo; level 1 topics and &amp;ldquo;easier&amp;rdquo; level 2 topics is very thin.&lt;/p&gt;
&lt;p&gt;Two books proved useful. Keep in mind I&amp;rsquo;ve been doing hands-on Linux system administration for 13 years, so they served mainly as refreshers and helped me score higher. Without that knowledge base to connect the dots, there&amp;rsquo;s no way to pass, even if you knew every question in advance.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.amazon.co.uk/LPIC-2-Linux-Professional-Institute-Certification-ebook/dp/B0051BKYQI&#34;
&gt;LPIC-2 Linux Professional Institute Certification Study Guide: Exams 201 and 202&lt;/a&gt;&lt;/strong&gt;: I found it lacking in depth on the exam topics, and its practice questions were far easier than the real ones. It was printed before LPI&amp;rsquo;s last update, so it doesn&amp;rsquo;t cover everything needed. It is useful for exam 201, though, and I thought the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Pluggable_authentication_module&#34;title=&#34;Pluggable Authentication Module&#34;
&gt;PAM&lt;/a&gt; chapter was particularly well written.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.amazon.co.uk/Hexa-Marathon-Guide-Professional-Practice-ebook/dp/B01APTI4I0&#34;
&gt;Hexa Marathon Guide: LPIC-2: Linux Network Professional: Practice problems on LPI 201 and 202&lt;/a&gt;&lt;/strong&gt;: It contains real exam questions (though not all of them, and I won&amp;rsquo;t ask how the author got them), but its formatting had serious shortcomings. Alongside the real questions, many others cover topics that no longer apply to current LPIC exams. On its own, it would only help people with a great photographic memory, but I found it excellent for structuring the knowledge I&amp;rsquo;d gained elsewhere and for getting higher scores.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;summary&#34;
    &gt;
        Summary
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/lpic-2-certification/#summary&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Summary&#34; aria-label=&#34;Anchor Summary&#34; href=&#34;#summary&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;How much did it cost to get here?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Preparation books&lt;/strong&gt; (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.amazon.co.uk/LPIC-1-Linux-Professional-Institute-Certification-ebook/dp/B00WWQQ3GA&#34;
&gt;1&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.amazon.co.uk/LPIC-2-Linux-Professional-Institute-Certification-ebook/dp/B0051BKYQI&#34;
&gt;2&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.amazon.co.uk/Hexa-Marathon-Guide-Professional-Practice-ebook/dp/B01APTI4I0&#34;
&gt;3&lt;/a&gt;): approx. EUR 80&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exams&lt;/strong&gt;: four in total, EUR 480 (one was paid directly by my employer)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Other&lt;/strong&gt;: the first two exams were taken in a conference setting, so there were additional transport and hotel costs for the trip to Brussels (excluded from this calculation).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wouldn&amp;rsquo;t call that a lot of money to prove you know Linux. The Red Hat certifications (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.redhat.com/en/services/certification/rhcsa&#34;
&gt;RHCSA&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.redhat.com/en/services/certification/rhce&#34;
&gt;RHCE&lt;/a&gt;) cost at least twice as much, possibly more once you add their (likely mandatory) training. Some will say a certification doesn&amp;rsquo;t help you land a better job, but I&amp;rsquo;d argue it&amp;rsquo;s better to have something that might give you an edge over the competition.&lt;/p&gt;
&lt;p&gt;Is &lt;strong&gt;LPIC-3&lt;/strong&gt; next? Maybe, but LPIC-3 is about specialization, and you must choose between &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.lpi.org/our-certifications/exam-300-objectives/&#34;
&gt;mixed environments&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.lpi.org/our-certifications/exam-300-objectives/&#34;
&gt;security&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.lpi.org/our-certifications/exam-305-objectives/&#34;
&gt;virtualization&lt;/a&gt;. All of these are, more or less, out of my league for now.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/certification" term="certification" label="Certification" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" />
        </entry>
        <entry>
            <title>Variable-Size Directories</title>
            <link href="https://www.brainware.ro/posts/variable_size_directory/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/variable_size_directory/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-04-12T20:02:57+00:00</published>
            <updated>2016-04-12T20:02:57+00:00</updated>
            <content type="html">
                &lt;p&gt;QA teams sometimes send requests like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For testing purposes, I need the &lt;code&gt;/opt/test/xxx&lt;/code&gt; directory limited to 10 Megabytes. This directory is used by the &lt;code&gt;abc123&lt;/code&gt; application, which runs as user &lt;code&gt;tester&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Can a directory&amp;rsquo;s size be limited in Linux? Yes. You need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the directory as a mount point for a size-limited storage device.&lt;/li&gt;
&lt;li&gt;Set mount options so the specified non-root user has full access.&lt;/li&gt;
&lt;li&gt;Disable SELinux (easy) or allow that particular user to access data on mount points (complicated).&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;choosing-the-storage-device&#34;
    &gt;
        Choosing the storage device
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/variable_size_directory/#choosing-the-storage-device&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Choosing the storage device&#34; aria-label=&#34;Anchor Choosing the storage device&#34; href=&#34;#choosing-the-storage-device&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;There are several options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A loop device&lt;/strong&gt;: a regular file used as a file system.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Logical_Volume_Manager_%28Linux%29&#34;
&gt;logical volume (LVM)&lt;/a&gt;&lt;/strong&gt;: assuming your disk setup is already LVM-based and has enough free space for the new volume.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A newly attached storage device&lt;/strong&gt;: for example, in a cloud environment like &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/&#34;
&gt;Amazon Web Services&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each has pros and cons. The loop device is by far the simplest to implement, but its I/O performance is lower than the other options.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;example-loop-device&#34;
    &gt;
        Example: loop device
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/variable_size_directory/#example-loop-device&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Example: loop device&#34; aria-label=&#34;Anchor Example: loop device&#34; href=&#34;#example-loop-device&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# Create a directory to hold the image file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir /var/spool/loop-files
&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:#75715e&#34;&gt;# Create a 10 MB zero-filled image file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dd &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/dev/zero of&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/spool/loop-files/xxx.img bs&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt; count&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10240&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:#75715e&#34;&gt;# Find the first unused loop device&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;losetup -f
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# /dev/loop2&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:#75715e&#34;&gt;# Associate the image file with the loop device&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;losetup /dev/loop2 /var/spool/loop-files/xxx.img
&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:#75715e&#34;&gt;# Create the file system on the device&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkfs.ext4 /dev/loop2
&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:#75715e&#34;&gt;# Update fstab to allow non-privileged user mounting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/dev/loop2  /opt/test/xxx  ext4  defaults,noauto,user  0 0&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; /etc/fstab
&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:#75715e&#34;&gt;# Mount as the non-privileged user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;su - tester -c &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mount /opt/test/xxx&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:#75715e&#34;&gt;# Check the mounted devices&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;df
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The file system size cannot be set to an exact value because of block, superblock, journal, and other metadata overhead. The usable space after creating the file system also varies, so a &amp;ldquo;10 Megabytes&amp;rdquo; request can only be met to a close possible value, through some trial and error with the image size.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;follow-up-more-than-8-loop-devices&#34;
    &gt;
        Follow-up: more than 8 loop devices
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/variable_size_directory/#follow-up-more-than-8-loop-devices&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Follow-up: more than 8 loop devices&#34; aria-label=&#34;Anchor Follow-up: more than 8 loop devices&#34; href=&#34;#follow-up-more-than-8-loop-devices&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;A default installation supports only 8 loop devices. To increase this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# Tell the kernel module to support more devices&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;modprobe loop max_loop&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;64&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:#75715e&#34;&gt;# Create the devices, e.g.:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mknod -m &lt;span style=&#34;color:#ae81ff&#34;&gt;660&lt;/span&gt; /dev/loop36 b &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;36&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should solve the problem. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" /> 
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>On Companies and Career Paths – a Personal Overview</title>
            <link href="https://www.brainware.ro/posts/companies_career_paths/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/companies_career_paths/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-03-26T18:04:40+00:00</published>
            <updated>2016-03-26T18:04:40+00:00</updated>
            <content type="html">
                &lt;p&gt;Starting a career in computer science is hard enough, and landing with a good company is mostly down to luck. I won&amp;rsquo;t argue with that: you do need plenty of luck to get off to a good start. My aim is simply to show where the train you&amp;rsquo;ve just boarded might take you, or might not. Switching trains is always possible, but it gets harder with age.&lt;/p&gt;
&lt;p&gt;At a high level, companies fall into two main categories:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Product Owners&lt;/strong&gt;: Companies that build products for a real market. They either sell software or offer services to individuals or businesses through infrastructure they manage themselves.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Outsourcers&lt;/strong&gt;: Companies that sell &amp;ldquo;work units&amp;rdquo;, directly or indirectly, to product owners or to other businesses.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are nuances here, and &lt;strong&gt;government contractors&lt;/strong&gt; and &lt;strong&gt;start-ups&lt;/strong&gt; arguably deserve categories of their own.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;what-a-fresh-graduate-can-expect&#34;
    &gt;
        What a fresh graduate can expect
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/companies_career_paths/#what-a-fresh-graduate-can-expect&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor What a fresh graduate can expect&#34; aria-label=&#34;Anchor What a fresh graduate can expect&#34; href=&#34;#what-a-fresh-graduate-can-expect&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Product Owner&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can gain deep knowledge, though it&amp;rsquo;s limited to the company&amp;rsquo;s particular product area.&lt;/li&gt;
&lt;li&gt;Few corners get cut, and you may sometimes apply advanced topics in your daily work.&lt;/li&gt;
&lt;li&gt;Pay depends on the company&amp;rsquo;s profitability, and good bonuses are possible.&lt;/li&gt;
&lt;li&gt;The downside: it can be hard to move to another company, because you become &amp;ldquo;entrenched&amp;rdquo; in a narrow set of clever solutions that may not be useful elsewhere.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Outsourcer&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You learn many unrelated or loosely related topics, but none in real depth.&lt;/li&gt;
&lt;li&gt;Projects last from a few months to a year at most, leaving no time to learn to do things well.&lt;/li&gt;
&lt;li&gt;Much of the work is fixing other contractors&amp;rsquo; code while adding technical debt of your own. You won&amp;rsquo;t care, because you&amp;rsquo;ll be gone in 3 to 6 months.&lt;/li&gt;
&lt;li&gt;You&amp;rsquo;re effectively paid by the billable hour (even if the company covers time between projects). Success earns you nothing extra, and failure usually just means another project assignment.&lt;/li&gt;
&lt;li&gt;On the plus side, moving to a similar role is easy: you know a lot of things, albeit shallowly, and you&amp;rsquo;re almost certain to use some of them at your next company.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Government contractor&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Expect a stable environment with few perks and sometimes below-average pay.&lt;/li&gt;
&lt;li&gt;Effectively, these are outsourcers with one large customer who, for all practical purposes, owns the product being developed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start-up&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start-ups own their single product, and your experience depends largely on the initial budget and the market competition.&lt;/li&gt;
&lt;li&gt;They are mostly about losing time and money: time through work/life imbalance, and money through lower pay than comparable skills would earn at a &amp;ldquo;normal&amp;rdquo; company.&lt;/li&gt;
&lt;li&gt;This statistically evens out on the rare occasions when someone strikes a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.merriam-webster.com/dictionary/bonanza&#34;
&gt;bonanza&lt;/a&gt; in the gold mine, meaning the product or business sells for good money.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;what-an-experienced-mid-career-person-can-expect&#34;
    &gt;
        What an experienced, mid-career person can expect
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/companies_career_paths/#what-an-experienced-mid-career-person-can-expect&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor What an experienced, mid-career person can expect&#34; aria-label=&#34;Anchor What an experienced, mid-career person can expect&#34; href=&#34;#what-an-experienced-mid-career-person-can-expect&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Product Owner&lt;/strong&gt;: In some cases, it can fill the knowledge and experience gaps needed to reach a higher position, whether in architecture, management, or sometimes a better-paid role at another company.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Outsourcer&lt;/strong&gt;: It may serve as a stepping stone to independent contracting or full entrepreneurship. Career progression in the style of a product-owner company is sometimes impossible because of how outsourcers are organized.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Government contractor&lt;/strong&gt;: Usually offers little more than an easy path to retirement.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Start-up&lt;/strong&gt;: Outcomes range from a premature end to your career, or being stuck in a dead end or set back for years, to the best case of getting rich and completely redefining your life.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;so-where-to&#34;
    &gt;
        So, where to?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/companies_career_paths/#so-where-to&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor So, where to?&#34; aria-label=&#34;Anchor So, where to?&#34; href=&#34;#so-where-to&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Back to square one: luck. And prepare well, so that you can choose the train you want to ride rather than just taking the first one that passes through your station.&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" />
        </entry>
        <entry>
            <title>The First Linux Certification (LPIC-1): How To</title>
            <link href="https://www.brainware.ro/posts/lpic-1-certification/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/lpic-1-certification/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-02-24T13:34:07+00:00</published>
            <updated>2016-02-24T13:34:07+00:00</updated>
            <content type="html">
                &lt;p&gt;I recently earned my LPIC-1 certification (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://cs.lpi.org/caf/Xamman/certification/verify/LPI000352547/dyxgmhunj8&#34;
&gt;verify here&lt;/a&gt;). Here&amp;rsquo;s what I learned, in case you want to try it and aren&amp;rsquo;t sure where to start.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;introduction&#34;
    &gt;
        Introduction
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/lpic-1-certification/#introduction&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Introduction&#34; aria-label=&#34;Anchor Introduction&#34; href=&#34;#introduction&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;LPIC-1 is granted after passing two exams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.lpi.org/our-certifications/exam-101-102-objectives/&#34;
&gt;Exam 101&lt;/a&gt;&lt;/strong&gt;: more theory-oriented, with many general questions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.lpi.org/our-certifications/exam-101-102-objectives/&#34;
&gt;Exam 102&lt;/a&gt;&lt;/strong&gt;: more practice-oriented, with an emphasis on scripting, networking and security.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can take these exams in any order, and the certification is awarded automatically once you&amp;rsquo;ve passed both. Higher levels require the lower-level certification first. For example, any LPIC-3 certification requires passing a total of 5 exams, again in any order.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;logistics&#34;
    &gt;
        Logistics
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/lpic-1-certification/#logistics&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Logistics&#34; aria-label=&#34;Anchor Logistics&#34; href=&#34;#logistics&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;The official route:&lt;/strong&gt; book through a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.pearsonvue.com/lpi/&#34;
&gt;Pearson VUE test center&lt;/a&gt;. Buy an exam voucher (roughly EUR 150, subject to exchange-rate changes), then sit the exam on a computer in a controlled environment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The alternative route:&lt;/strong&gt; attend a conference that offers pen-and-paper exams. In Europe, you can register your seat on the LPI site and then attend that event. This is cheaper, and a good option if you&amp;rsquo;re going to the conference anyway.&lt;/p&gt;
&lt;p&gt;I took both Exam 101 and Exam 102 at &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://fosdem.org/&#34;
&gt;FOSDEM 2016&lt;/a&gt; in Brussels, Belgium, on January 30 and 31.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;preparation&#34;
    &gt;
        Preparation
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/lpic-1-certification/#preparation&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Preparation&#34; aria-label=&#34;Anchor Preparation&#34; href=&#34;#preparation&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This isn&amp;rsquo;t a school-style exam. To have a real chance of passing, you need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Lots of practical experience.&lt;/strong&gt; Knowing a handful of shell commands won&amp;rsquo;t be enough. Two to three years in a DevOps or sysadmin role is a sensible point to start preparing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Preparation books.&lt;/strong&gt; &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.amazon.co.uk/LPIC-1-Linux-Professional-Institute-Certification-ebook/dp/B00WWQQ3GA/&#34;
&gt;This book&lt;/a&gt; helped me fill some knowledge gaps. Note that there is no official course or exam support for any LPI exam.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Targeted practice.&lt;/strong&gt; Work on your weak areas. Many questions cover everyday topics, but some can only be answered if you&amp;rsquo;re familiar with that specific area.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;about-the-exams&#34;
    &gt;
        About the Exams
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/lpic-1-certification/#about-the-exams&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor About the Exams&#34; aria-label=&#34;Anchor About the Exams&#34; href=&#34;#about-the-exams&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I can&amp;rsquo;t share any exam questions (and I don&amp;rsquo;t remember many anyway), but roughly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;About half the questions&lt;/strong&gt; cover normal day-to-day usage, which you should know if you currently work in a Linux-related role. They&amp;rsquo;re not easy, but they&amp;rsquo;re not impossible either.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The other half&lt;/strong&gt; is split across &amp;ldquo;expertise areas,&amp;rdquo; and you&amp;rsquo;ll probably need to master a few of them to pass. For example, you may need to know which file to edit, and what to put in it, to change how name resolution behaves.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Questions carry different weights&lt;/strong&gt;, so some contribute more to your score than others. I can&amp;rsquo;t tell which are which, and I doubt anyone outside LPI can.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is not a trivia exam. Every question is based on real-world scenarios you may have encountered at work. I suspect that lack of hands-on experience is the leading cause of failure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;conclusion&#34;
    &gt;
        Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/lpic-1-certification/#conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Conclusion&#34; aria-label=&#34;Anchor Conclusion&#34; href=&#34;#conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;ve already started preparing for &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.lpi.org/our-certifications/lpic-2-overview/&#34;
&gt;level 2&lt;/a&gt;, which is certainly tougher. I haven&amp;rsquo;t yet decided on an exam date or how to take the two exams. I&amp;rsquo;ll post an update once I&amp;rsquo;m done. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/certification" term="certification" label="Certification" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" />
        </entry>
        <entry>
            <title>Python: Crazy Interview Questions</title>
            <link href="https://www.brainware.ro/posts/crazy_python_interview/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/crazy_python_interview/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-02-13T16:16:57+00:00</published>
            <updated>2016-02-13T16:16:57+00:00</updated>
            <content type="html">
                &lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-the-mutable-default-argument-trap&#34;
    &gt;
        1. The Mutable Default Argument Trap
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_python_interview/#1-the-mutable-default-argument-trap&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. The Mutable Default Argument Trap&#34; aria-label=&#34;Anchor 1. The Mutable Default Argument Trap&#34; href=&#34;#1-the-mutable-default-argument-trap&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Imagine an interviewer hands you a slip of paper with this on it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(bar&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;[])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No context, just the question: &lt;em&gt;what&amp;rsquo;s wrong with this code?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Strictly speaking, nothing. It&amp;rsquo;s valid Python (aside from the missing colon and function body), and a bug is only a bug when the code behaves differently from what the programmer intended.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s give the function a body:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(bar&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;[]):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bar&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&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:#66d9ef&#34;&gt;return&lt;/span&gt; bar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What would a typical Python programmer expect from calling &lt;code&gt;foo()&lt;/code&gt; three times with no arguments?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;foo()  &lt;span style=&#34;color:#75715e&#34;&gt;# [1]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo()  &lt;span style=&#34;color:#75715e&#34;&gt;# [1]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo()  &lt;span style=&#34;color:#75715e&#34;&gt;# [1]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s not what happens. The actual output is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;foo()  &lt;span style=&#34;color:#75715e&#34;&gt;# [1]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo()  &lt;span style=&#34;color:#75715e&#34;&gt;# [1, 1]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo()  &lt;span style=&#34;color:#75715e&#34;&gt;# [1, 1, 1]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; Python evaluates default argument values once, when the function is defined, not each time it&amp;rsquo;s called. The same list object is reused on every call. This differs from C/C++, and the behaviour resembles &lt;code&gt;static&lt;/code&gt; variables there. That&amp;rsquo;s handy for caching or keeping state, but it&amp;rsquo;s rarely what you intended.&lt;/p&gt;
&lt;p&gt;The usual fix:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(bar&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;None&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:#66d9ef&#34;&gt;if&lt;/span&gt; bar &lt;span style=&#34;color:#f92672&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bar&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&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:#66d9ef&#34;&gt;return&lt;/span&gt; bar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-strings-are-immutable&#34;
    &gt;
        2. Strings Are Immutable
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_python_interview/#2-strings-are-immutable&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Strings Are Immutable&#34; aria-label=&#34;Anchor 2. Strings Are Immutable&#34; href=&#34;#2-strings-are-immutable&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The interviewer says: &lt;em&gt;&amp;ldquo;Given a string &lt;code&gt;S&lt;/code&gt;, replace the 3rd character with &lt;code&gt;&amp;quot;A&amp;quot;&lt;/code&gt;.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You rightly note that the string might be empty or too short. &amp;ldquo;Ignore that,&amp;rdquo; they say. So you write:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;repl&lt;/span&gt;(S):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(S) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        S[&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# index starts at 0&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:#66d9ef&#34;&gt;return&lt;/span&gt; S
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The interviewer glances at it, ends the interview, and tells you HR will be in touch. (If an offer does come, you may want to think twice about working there.)&lt;/p&gt;
&lt;p&gt;The problem: Python strings are &lt;strong&gt;immutable&lt;/strong&gt;, so item assignment isn&amp;rsquo;t allowed. Instead, build a new string:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;repl&lt;/span&gt;(S):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; len(S) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&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:#66d9ef&#34;&gt;return&lt;/span&gt; S[:&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; S[&lt;span style=&#34;color:#ae81ff&#34;&gt;3&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:#66d9ef&#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:#66d9ef&#34;&gt;return&lt;/span&gt; S
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-late-binding-in-closures&#34;
    &gt;
        3. Late Binding in Closures
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_python_interview/#3-late-binding-in-closures&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. Late Binding in Closures&#34; aria-label=&#34;Anchor 3. Late Binding in Closures&#34; href=&#34;#3-late-binding-in-closures&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You&amp;rsquo;re shown this snippet:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;F &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x: i &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; x &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you haven&amp;rsquo;t fled the room yet, you&amp;rsquo;re already ahead of many. Here&amp;rsquo;s what the code is meant to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;F&lt;/code&gt; is a list of functions.&lt;/li&gt;
&lt;li&gt;It holds 5 functions.&lt;/li&gt;
&lt;li&gt;Each takes one argument &lt;code&gt;x&lt;/code&gt; and should return &lt;code&gt;x * i&lt;/code&gt;, where &lt;code&gt;i&lt;/code&gt; is 0 for the first function, 1 for the second, and 4 for the last.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So you&amp;rsquo;d expect:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;F[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;](&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)  &lt;span style=&#34;color:#75715e&#34;&gt;# 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;F[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;](&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)  &lt;span style=&#34;color:#75715e&#34;&gt;# 2&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:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;F[&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;](&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)  &lt;span style=&#34;color:#75715e&#34;&gt;# 8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In reality:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;F[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;](&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)  &lt;span style=&#34;color:#75715e&#34;&gt;# 8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;F[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;](&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)  &lt;span style=&#34;color:#75715e&#34;&gt;# 8&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:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;F[&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;](&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)  &lt;span style=&#34;color:#75715e&#34;&gt;# 8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; The lambdas look up &lt;code&gt;i&lt;/code&gt; when they&amp;rsquo;re &lt;em&gt;called&lt;/em&gt;, not when they&amp;rsquo;re created. By then the loop has finished and &lt;code&gt;i&lt;/code&gt; is &lt;code&gt;4&lt;/code&gt;, so every function uses that value.&lt;/p&gt;
&lt;p&gt;The usual fix is to bind the current value as a default argument:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;F &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x, i&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;i: i &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; x &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Honestly, few experienced Python developers would get this right on the spot, and asking it in an interview will likely leave candidates with a poor impression of your company.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for today. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/interview" term="interview" label="Interview" /> 
                                <category scheme="https://www.brainware.ro/categories/python" term="python" label="Python" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" /> 
                                <category scheme="https://www.brainware.ro/tags/python" term="python" label="python" />
        </entry>
        <entry>
            <title>Linux Performance Monitoring (an Introduction)</title>
            <link href="https://www.brainware.ro/posts/linux_performance_monitoring/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/linux_performance_monitoring/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-02-07T20:31:07+00:00</published>
            <updated>2016-02-07T20:31:07+00:00</updated>
            <content type="html">
                &lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-classification&#34;
    &gt;
        1. Classification
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_performance_monitoring/#1-classification&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Classification&#34; aria-label=&#34;Anchor 1. Classification&#34; href=&#34;#1-classification&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&amp;ldquo;Performance&amp;rdquo; is a broad term, so it helps to split it into categories first. Two questions do most of the work:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;What do we want to monitor?&lt;/strong&gt; The whole system, or one particular application?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What kind of monitoring do we need?&lt;/strong&gt; Basic statistics gathered by the kernel, or in-depth analysis?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Combining the answers gives four categories, each with its own set of tools:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th&gt;&lt;strong&gt;Stats (Counters)&lt;/strong&gt;&lt;/th&gt;
					&lt;th&gt;&lt;strong&gt;Tracing / Profiling / Debugging&lt;/strong&gt;&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;System-wide&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/mpstat&#34;
&gt;mpstat&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/vmstat&#34;
&gt;vmstat&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/iostat&#34;
&gt;iostat&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/netstat&#34;
&gt;netstat&lt;/a&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/tcpdump&#34;
&gt;tcpdump&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/DTrace&#34;
&gt;dtrace&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/SystemTap&#34;
&gt;SystemTap&lt;/a&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Per process&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/ps&#34;
&gt;ps&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/top&#34;
&gt;top&lt;/a&gt;&lt;/td&gt;
					&lt;td&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/strace&#34;
&gt;strace&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.gnu.org/software/gdb/&#34;
&gt;gdb&lt;/a&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Notes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;netstat&lt;/code&gt; does more than report interface and protocol statistics. It can also monitor individual connections.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dtrace&lt;/code&gt; and &lt;code&gt;SystemTap&lt;/code&gt; can also trace individual applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-stats-collection&#34;
    &gt;
        2. Stats Collection
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_performance_monitoring/#2-stats-collection&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Stats Collection&#34; aria-label=&#34;Anchor 2. Stats Collection&#34; href=&#34;#2-stats-collection&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Where do the tools in the first column get their numbers? The short answer is &amp;ldquo;the kernel&amp;rdquo;, but the actual interface is the &lt;code&gt;/proc&lt;/code&gt; file system. For every process, the kernel exposes a &lt;code&gt;stat&lt;/code&gt; file containing all the collected data:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cat /proc/15588/stat&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:#ae81ff&#34;&gt;15588&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;httpd&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; S &lt;span style=&#34;color:#ae81ff&#34;&gt;30837&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;30837&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;30837&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; -1 &lt;span style=&#34;color:#ae81ff&#34;&gt;4202816&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1845&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;381733777&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;671944704&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4446&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;18446744073709551615&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;140071612739584&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;140071613080548&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;140735088901328&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;140735088899312&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;140071585579283&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;16781312&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;201344747&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;18446744071580587657&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;17&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This format suits software far better than people: without the documentation, nobody can tell which number is which. Fortunately, a human-readable version exists:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cat /proc/15588/status&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Name:   httpd
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;State:  S &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;sleeping&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Tgid:   &lt;span style=&#34;color:#ae81ff&#34;&gt;15588&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Pid:    &lt;span style=&#34;color:#ae81ff&#34;&gt;15588&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PPid:   &lt;span style=&#34;color:#ae81ff&#34;&gt;30837&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TracerPid:      &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Uid:    &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Gid:    &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;      &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Utrace: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FDSize: &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Groups: &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmPeak:   &lt;span style=&#34;color:#ae81ff&#34;&gt;656708&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmSize:   &lt;span style=&#34;color:#ae81ff&#34;&gt;655684&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmLck:         &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmHWM:     &lt;span style=&#34;color:#ae81ff&#34;&gt;17920&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmRSS:     &lt;span style=&#34;color:#ae81ff&#34;&gt;17752&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmData:    &lt;span style=&#34;color:#ae81ff&#34;&gt;87788&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmStk:       &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmExe:       &lt;span style=&#34;color:#ae81ff&#34;&gt;336&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmLib:     &lt;span style=&#34;color:#ae81ff&#34;&gt;62692&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmPTE:       &lt;span style=&#34;color:#ae81ff&#34;&gt;872&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VmSwap:        &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; kB
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Threads:        &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SigQ:   0/63581
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SigPnd: &lt;span style=&#34;color:#ae81ff&#34;&gt;0000000000000000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ShdPnd: &lt;span style=&#34;color:#ae81ff&#34;&gt;0000000000000000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SigBlk: &lt;span style=&#34;color:#ae81ff&#34;&gt;0000000000000000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SigIgn: &lt;span style=&#34;color:#ae81ff&#34;&gt;0000000001001000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SigCgt: 000000018c0046eb
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CapInh: &lt;span style=&#34;color:#ae81ff&#34;&gt;0000000000000000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CapPrm: &lt;span style=&#34;color:#ae81ff&#34;&gt;0000000000000000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CapEff: &lt;span style=&#34;color:#ae81ff&#34;&gt;0000000000000000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CapBnd: ffffffffffffffff
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Cpus_allowed:   ff
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Cpus_allowed_list:      0-7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Mems_allowed:   00000000,00000000,...,00000001
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Mems_allowed_list:      &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;voluntary_ctxt_switches:        &lt;span style=&#34;color:#ae81ff&#34;&gt;166&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nonvoluntary_ctxt_switches:     &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The kernel also provides system-wide statistics:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cat /proc/stat&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpu  &lt;span style=&#34;color:#ae81ff&#34;&gt;20887396&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10349385&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3015436747&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;407563&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3166&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1467937&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpu0 &lt;span style=&#34;color:#ae81ff&#34;&gt;10678475&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3883808&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;362454876&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;232413&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3166&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1390223&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpu1 &lt;span style=&#34;color:#ae81ff&#34;&gt;1661441&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1011415&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;378955537&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;31275&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;11441&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpu2 &lt;span style=&#34;color:#ae81ff&#34;&gt;746371&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;330726&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;380344321&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;23829&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;11456&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpu3 &lt;span style=&#34;color:#ae81ff&#34;&gt;519138&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;214791&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;380738302&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;16767&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10813&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpu4 &lt;span style=&#34;color:#ae81ff&#34;&gt;5386158&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3986695&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;371475949&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;54473&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;12596&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpu5 &lt;span style=&#34;color:#ae81ff&#34;&gt;682554&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;324926&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;380359994&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;18308&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;11663&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpu6 &lt;span style=&#34;color:#ae81ff&#34;&gt;705281&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;343150&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;380407382&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;15057&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10218&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpu7 &lt;span style=&#34;color:#ae81ff&#34;&gt;507974&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;253871&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;380700384&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;15438&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;9525&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;intr &lt;span style=&#34;color:#ae81ff&#34;&gt;5529843084&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;126&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; ... &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;long run of mostly zeros omitted&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ctxt &lt;span style=&#34;color:#ae81ff&#34;&gt;5379451608&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;btime &lt;span style=&#34;color:#ae81ff&#34;&gt;1451035714&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;processes &lt;span style=&#34;color:#ae81ff&#34;&gt;6474048&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;procs_running &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;procs_blocked &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;softirq &lt;span style=&#34;color:#ae81ff&#34;&gt;11537062915&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4052674276&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;583728909&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;992215181&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;16867459&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;13667315&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1762309239&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2086018&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4113514518&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is no human-readable version of the system-wide &lt;code&gt;/proc/stat&lt;/code&gt;, which is why you need the tools listed above to interpret it.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-tracing&#34;
    &gt;
        3. Tracing
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_performance_monitoring/#3-tracing&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. Tracing&#34; aria-label=&#34;Anchor 3. Tracing&#34; href=&#34;#3-tracing&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Tracing is where things get more complicated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Userspace tracing.&lt;/strong&gt; You can monitor individual processes with signals such as &lt;code&gt;SIGTRAP&lt;/code&gt;. This makes tracing possible with userspace-only tools, but the overhead is significant, so it is not advisable for performance-sensitive work. Still, &lt;code&gt;strace&lt;/code&gt; and &lt;code&gt;gdb&lt;/code&gt; remain the best tools for debugging and spotting erratic behaviour in individual programs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Kernel-assisted tracing.&lt;/strong&gt; More advanced tools such as &lt;code&gt;dtrace&lt;/code&gt; rely on the kernel to report events for one process or for all of them. This is sometimes called &amp;ldquo;zero-cost&amp;rdquo; tracing, and it can be used in production environments.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dtrace&lt;/code&gt; and &lt;code&gt;SystemTap&lt;/code&gt; both include scripting languages for handling the results when a &amp;ldquo;probe&amp;rdquo; fires, for example when a particular system call runs or execution reaches a certain line in the monitored program. This makes it possible to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Process data in advanced ways (e.g. count specific behaviours)&lt;/li&gt;
&lt;li&gt;Aggregate statistics&lt;/li&gt;
&lt;li&gt;Perform &amp;ldquo;open-heart surgery&amp;rdquo; on programs, intercepting data flows or replacing data that would otherwise trigger undesired behaviour&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Static vs. dynamic tracing.&lt;/strong&gt; Tracing falls into two categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Static tracing&lt;/strong&gt; looks at invariants such as system calls or well-known points within a feature. These are well documented and don&amp;rsquo;t change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic tracing&lt;/strong&gt; is like setting breakpoints on individual lines of code. Such breakpoints work for specific versions and may not apply to later versions of the program.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; a &lt;code&gt;dtrace&lt;/code&gt; one-liner that prints a timestamp for every system call made by a given application:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;$ dtrace -n &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;syscall::: /execname==&amp;#34;myapp&amp;#34;/ { printf(&amp;#34;%d&amp;#34;, timestamp); }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;More one-liners are available here: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.brendangregg.com/DTrace/dtrace_oneliners.txt&#34;
&gt;DTrace One Liners&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That wraps up my introduction to performance monitoring. I hope you enjoyed it!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/monitoring" term="monitoring" label="Monitoring" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/performance" term="performance" label="performance" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Python Cheat Sheet: Lambdas</title>
            <link href="https://www.brainware.ro/posts/python_cheat_sheet_lambdas/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/python_cheat_sheet_lambdas/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-01-15T21:20:57+00:00</published>
            <updated>2016-01-15T21:20:57+00:00</updated>
            <content type="html">
                &lt;p&gt;Do you think list comprehensions are a tricky topic? After reading this post, you may well change your mind about what counts as &amp;ldquo;complicated&amp;rdquo; in Python.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;lambdas&#34;
    &gt;
        Lambdas
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lambdas/#lambdas&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Lambdas&#34; aria-label=&#34;Anchor Lambdas&#34; href=&#34;#lambdas&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;A lambda is a small function defined right where you need it, typically for light data-processing jobs. There are two main reasons to use them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Speed:&lt;/strong&gt; a compiler can optimize them, first by eliminating an actual function call, and then by opening the door to further internal code re-arrangements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brevity:&lt;/strong&gt; you write less code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is a lambda that squares a number:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;g &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x: x &lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# e.g. g(3) yields 9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lambdas are most often paired with the data-processing functions &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;reduce&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;filtering&#34;
    &gt;
        Filtering
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lambdas/#filtering&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Filtering&#34; aria-label=&#34;Anchor Filtering&#34; href=&#34;#filtering&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;To keep only part of an input, &lt;code&gt;filter&lt;/code&gt; combined with a lambda works nicely:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;print filter(&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x: x &lt;span style=&#34;color:#f92672&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, xrange(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;11&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:#75715e&#34;&gt;# [0, 2, 4, 6, 8, 10]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;transformation&#34;
    &gt;
        Transformation
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lambdas/#transformation&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Transformation&#34; aria-label=&#34;Anchor Transformation&#34; href=&#34;#transformation&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;To apply a transformation to every element of the input, use &lt;code&gt;map&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;print map(&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x: x &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, xrange(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;11&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:#75715e&#34;&gt;# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;summarizing&#34;
    &gt;
        Summarizing
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lambdas/#summarizing&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Summarizing&#34; aria-label=&#34;Anchor Summarizing&#34; href=&#34;#summarizing&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;To boil the whole input down to a single result, use &lt;code&gt;reduce&lt;/code&gt;. Note that the lambda must accept two arguments: at first it receives the first two elements, and afterwards it receives the previous result plus the next element, until the input runs out.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;print reduce(&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x, y: x &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; y, xrange(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;11&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:#75715e&#34;&gt;# 55    # 1 + 2 + ... + 10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;p&gt;Now for the more serious material.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;mapreduce-in-python&#34;
    &gt;
        MapReduce in Python
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lambdas/#mapreduce-in-python&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor MapReduce in Python&#34; aria-label=&#34;Anchor MapReduce in Python&#34; href=&#34;#mapreduce-in-python&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;print reduce(&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x, y: x &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; y, map(&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x: x &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, xrange(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;11&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:#75715e&#34;&gt;# 110    # 1*2 + 2*2 + ... + 10*2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;the-intersection-of-two-lists&#34;
    &gt;
        The Intersection of Two Lists
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lambdas/#the-intersection-of-two-lists&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor The Intersection of Two Lists&#34; aria-label=&#34;Anchor The Intersection of Two Lists&#34; href=&#34;#the-intersection-of-two-lists&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;intersection&lt;/span&gt;(A, B):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    S &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; set(A)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; filter(&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x: x &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; S, B)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An answer like this probably isn&amp;rsquo;t what an interviewer expects. If you&amp;rsquo;re in an interview, make sure you can explain what&amp;rsquo;s happening before you write it down (for example, how a &lt;code&gt;set&lt;/code&gt; works and what the complexity is in &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Big_O_notation&#34;
&gt;big O notation&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;removing-duplicates-from-a-list&#34;
    &gt;
        Removing Duplicates from a List
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lambdas/#removing-duplicates-from-a-list&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Removing Duplicates from a List&#34; aria-label=&#34;Anchor Removing Duplicates from a List&#34; href=&#34;#removing-duplicates-from-a-list&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;If the order of the remaining unique items doesn&amp;rsquo;t matter, calling &lt;code&gt;set(A)&lt;/code&gt; is enough. Otherwise, we need to get creative:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;dedup&lt;/span&gt;(A):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    S &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; set()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; filter(&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x: x &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; S &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; S&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;add(x), A)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A set&amp;rsquo;s &lt;code&gt;add&lt;/code&gt; method always returns &lt;code&gt;None&lt;/code&gt;, which evaluates to boolean &lt;code&gt;False&lt;/code&gt;. To make the logic work, a small hack is needed (&lt;code&gt;S.add() == None&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Also note that this solution keeps the first occurrence of each element and rejects the later duplicates. Solutions that keep the last or the n-th occurrence exist, but they&amp;rsquo;re much easier to write when the order of elements in the result doesn&amp;rsquo;t matter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;dedup_last_unordered&lt;/span&gt;(A):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    S &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; set()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    map(&lt;span style=&#34;color:#66d9ef&#34;&gt;lambda&lt;/span&gt; x: ((x &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; S &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; S&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;remove(x)) &lt;span style=&#34;color:#f92672&#34;&gt;or&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; S&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;add(x), A)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; S
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, that version is pushing past what lambdas are meant for. Writing it the &amp;ldquo;normal&amp;rdquo; way is much clearer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;dedup_last_unordered&lt;/span&gt;(A):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    S &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; set()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; A:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; S:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            S&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;remove(i)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        S&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;add(i)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; S
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A solution for the n-th duplicate can&amp;rsquo;t be written purely with lambdas, because it needs a counter that is assigned and incremented, and lambdas don&amp;rsquo;t allow that. A &amp;ldquo;normal&amp;rdquo; approach would use a dictionary that stores the counter as the value, but I think it&amp;rsquo;s best to stop here.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for today. Hope you enjoyed it!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/python" term="python" label="Python" />  
                                <category scheme="https://www.brainware.ro/tags/python" term="python" label="python" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Python Cheat Sheet: Dictionaries</title>
            <link href="https://www.brainware.ro/posts/python_cheat_sheet_dicts/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/python_cheat_sheet_dicts/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2016-01-08T18:23:57+00:00</published>
            <updated>2016-01-08T18:23:57+00:00</updated>
            <content type="html">
                &lt;p&gt;Python dictionaries are built on &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Hash_table&#34;
&gt;hash tables&lt;/a&gt;. They can hold arbitrary key-value pairs, and the keys and values don&amp;rsquo;t have to share a single data type. Dictionaries are unordered, meaning no ordering between elements is defined, so you can&amp;rsquo;t rely on any particular sequence when iterating over them.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Unless stated otherwise, all examples use Python 2 syntax.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;creating-an-empty-dictionary&#34;
    &gt;
        Creating an empty dictionary
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_dicts/#creating-an-empty-dictionary&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Creating an empty dictionary&#34; aria-label=&#34;Anchor Creating an empty dictionary&#34; href=&#34;#creating-an-empty-dictionary&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;D &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;initializing-a-dictionary&#34;
    &gt;
        Initializing a dictionary
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_dicts/#initializing-a-dictionary&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Initializing a dictionary&#34; aria-label=&#34;Anchor Initializing a dictionary&#34; href=&#34;#initializing-a-dictionary&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;D &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; dict((i, &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; xrange(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;11&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)   &lt;span style=&#34;color:#75715e&#34;&gt;# Python 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;D &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {i: &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;11&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;}          &lt;span style=&#34;color:#75715e&#34;&gt;# Python 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: the second form is known as a dictionary comprehension.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;iterating-over-all-items&#34;
    &gt;
        Iterating over all items
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_dicts/#iterating-over-all-items&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Iterating over all items&#34; aria-label=&#34;Anchor Iterating over all items&#34; href=&#34;#iterating-over-all-items&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; D:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print i, D[i]   &lt;span style=&#34;color:#75715e&#34;&gt;# key, value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or alternatively:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; k, v &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; D&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;iteritems():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print k, v      &lt;span style=&#34;color:#75715e&#34;&gt;# key, value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;checking-whether-a-key-exists&#34;
    &gt;
        Checking whether a key exists
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_dicts/#checking-whether-a-key-exists&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Checking whether a key exists&#34; aria-label=&#34;Anchor Checking whether a key exists&#34; href=&#34;#checking-whether-a-key-exists&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; k &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; D:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print k
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;adding-elements&#34;
    &gt;
        Adding elements
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_dicts/#adding-elements&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Adding elements&#34; aria-label=&#34;Anchor Adding elements&#34; href=&#34;#adding-elements&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;D[key] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; value
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: if the key already exists, no error is raised; its value is simply overwritten.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;removing-elements&#34;
    &gt;
        Removing elements
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_dicts/#removing-elements&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Removing elements&#34; aria-label=&#34;Anchor Removing elements&#34; href=&#34;#removing-elements&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;&lt;span style=&#34;color:#66d9ef&#34;&gt;del&lt;/span&gt; D[key]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;removing-duplicates-from-a-list-with-a-dictionary-as-a-lookup-table&#34;
    &gt;
        Removing duplicates from a list with a dictionary as a lookup table
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_dicts/#removing-duplicates-from-a-list-with-a-dictionary-as-a-lookup-table&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Removing duplicates from a list with a dictionary as a lookup table&#34; aria-label=&#34;Anchor Removing duplicates from a list with a dictionary as a lookup table&#34; href=&#34;#removing-duplicates-from-a-list-with-a-dictionary-as-a-lookup-table&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;D &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;unique &lt;span style=&#34;color:#f92672&#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:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; L:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; D:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        D[i] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        unique&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(i)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;L &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; unique
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; this keeps the first occurrence of each element and preserves the original order. To modify the list in place instead of rebinding the name, use &lt;code&gt;L[:] = unique&lt;/code&gt; as the last line.&lt;/p&gt;
&lt;p&gt;A &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://docs.python.org/2/library/stdtypes.html#set&#34;
&gt;set&lt;/a&gt; is a better fit for this job. If the original order of the list doesn&amp;rsquo;t matter, you can use the shorter form &lt;code&gt;list(set(L))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for today. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/python" term="python" label="Python" />  
                                <category scheme="https://www.brainware.ro/tags/python" term="python" label="python" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Note to Self: HTTP Server KeepAlive Timeout</title>
            <link href="https://www.brainware.ro/posts/http_keepalive_timeout/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/http_keepalive_timeout/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-12-28T11:41:07+00:00</published>
            <updated>2015-12-28T11:41:07+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I have ran into this problem on &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://httpd.apache.org/&#34;
&gt;Apache httpd&lt;/a&gt;, but it could just as easily affect any other HTTP server.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;http-keepalive&#34;
    &gt;
        HTTP KeepAlive
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/http_keepalive_timeout/#http-keepalive&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor HTTP KeepAlive&#34; aria-label=&#34;Anchor HTTP KeepAlive&#34; href=&#34;#http-keepalive&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The idea behind &amp;ldquo;KeepAlive&amp;rdquo; is straightforward: instead of opening a new connection for every request, the browser opens one connection to the server and reuses it to fetch many resources, such as the main page, stylesheets, JavaScript files, and images. In theory, this cuts page load times and gives visitors a better experience. So far, so good.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;server-configuration&#34;
    &gt;
        Server Configuration
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/http_keepalive_timeout/#server-configuration&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Server Configuration&#34; aria-label=&#34;Anchor Server Configuration&#34; href=&#34;#server-configuration&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Apache httpd manages this feature with three directives, all part of the &lt;code&gt;core&lt;/code&gt; module:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;KeepAlive&lt;/strong&gt;: on or off (default: &lt;code&gt;on&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;KeepAliveTimeout&lt;/strong&gt;: a number of seconds (default: &lt;code&gt;5&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MaxKeepAliveRequests&lt;/strong&gt;: a positive integer (default: &lt;code&gt;100&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Apache httpd has no way to serve KeepAlive and non-KeepAlive requests side by side (for instance, allowing up to 100 KeepAlive requests per connection and handling anything beyond that differently). You have to decide on the behavior up front.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;the-traffic&#34;
    &gt;
        The Traffic
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/http_keepalive_timeout/#the-traffic&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor The Traffic&#34; aria-label=&#34;Anchor The Traffic&#34; href=&#34;#the-traffic&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Time for some math. Starting from the &lt;strong&gt;MaxClients&lt;/strong&gt; value (default: 256), how many new clients per second can the server handle without hurting the user experience? You might answer &amp;ldquo;MaxClients,&amp;rdquo; but let&amp;rsquo;s not jump to conclusions. A few factors come into play:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The time between opening a connection and the &lt;strong&gt;KeepAliveTimeout&lt;/strong&gt; expiring. With default settings that&amp;rsquo;s at least 5 seconds, and in typical real-world conditions probably 7 to 10 seconds.&lt;/li&gt;
&lt;li&gt;Fluctuations in traffic (spikes).&lt;/li&gt;
&lt;li&gt;Apache httpd&amp;rsquo;s own overhead, such as spawning new processes to handle incoming connections.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Things get complicated quickly. But if we assume a typical 7 seconds per client, during which a server process is either busy or waiting for data, and that all clients behave roughly the same way, then the default &lt;strong&gt;MaxClients&lt;/strong&gt; of 256 supports a steady rate of 256 / 7 ≈ 36 new requests per second. Any spike above that will cause slow page loads and a poor user experience.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;better-planning&#34;
    &gt;
        Better Planning
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/http_keepalive_timeout/#better-planning&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Better Planning&#34; aria-label=&#34;Anchor Better Planning&#34; href=&#34;#better-planning&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;If turning &lt;strong&gt;KeepAlive&lt;/strong&gt; off isn&amp;rsquo;t an option, plan around the worst spike you expect to handle (for example, 2x or 3x the average during your busiest period). If your busy-period average is 50 requests/second, the server should be able to cope with 100 or even 150 requests/second without degrading the user experience. If the hardware is already pushed to its limit, you&amp;rsquo;ll need other approaches, such as multiple servers or load balancers (which I won&amp;rsquo;t go into here).&lt;/p&gt;
&lt;p&gt;For a peak of 150 requests/second with the default 5-second &lt;strong&gt;KeepAliveTimeout&lt;/strong&gt;, you&amp;rsquo;d likely need to raise &lt;strong&gt;MaxClients&lt;/strong&gt; to around 1,000. If you&amp;rsquo;re using the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://httpd.apache.org/docs/2.0/mod/prefork.html&#34;
&gt;prefork MPM&lt;/a&gt;, &lt;strong&gt;ServerLimit&lt;/strong&gt; needs to be raised as well.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;conclusion&#34;
    &gt;
        Conclusion
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/http_keepalive_timeout/#conclusion&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Conclusion&#34; aria-label=&#34;Anchor Conclusion&#34; href=&#34;#conclusion&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Don&amp;rsquo;t rely on the defaults. Begin your parameter calculations with the outcome you want to achieve. On hardware that is short on memory, disabling &lt;strong&gt;KeepAlive&lt;/strong&gt; is the best way to squeeze out extra performance. And don&amp;rsquo;t assume your hardware can deliver what your calculations demand; when something fails or was planned badly, treat it as a chance to learn.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for today. Have fun!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/configuration" term="configuration" label="Configuration" />  
                                <category scheme="https://www.brainware.ro/tags/architecture" term="architecture" label="architecture" /> 
                                <category scheme="https://www.brainware.ro/tags/performance" term="performance" label="performance" />
        </entry>
        <entry>
            <title>Python Cheat Sheet: Lists</title>
            <link href="https://www.brainware.ro/posts/python_cheat_sheet_lists/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/python_cheat_sheet_lists/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-12-26T13:55:57+00:00</published>
            <updated>2015-12-26T13:55:57+00:00</updated>
            <content type="html">
                &lt;p&gt;Lists are ordered, linear collections that offer constant-time element lookup by index. They can grow or shrink, be searched, and be sorted (including with a custom comparison function). They also aren&amp;rsquo;t limited to one data type, so a single list can hold a mix of values. Python lists are zero-indexed.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Unless stated otherwise, all examples use Python 2 syntax.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;creating-a-pre-filled-list-of-10-numbers-all-zeros&#34;
    &gt;
        Creating a pre-filled list of 10 numbers (all zeros):
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#creating-a-pre-filled-list-of-10-numbers-all-zeros&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Creating a pre-filled list of 10 numbers (all zeros):&#34; aria-label=&#34;Anchor Creating a pre-filled list of 10 numbers (all zeros):&#34; href=&#34;#creating-a-pre-filled-list-of-10-numbers-all-zeros&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;creating-a-pre-filled-list-of-10-numbers-powers-of-2&#34;
    &gt;
        Creating a pre-filled list of 10 numbers (powers of 2):
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#creating-a-pre-filled-list-of-10-numbers-powers-of-2&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Creating a pre-filled list of 10 numbers (powers of 2):&#34; aria-label=&#34;Anchor Creating a pre-filled list of 10 numbers (powers of 2):&#34; href=&#34;#creating-a-pre-filled-list-of-10-numbers-powers-of-2&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;i &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; xrange(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note 1:&lt;/strong&gt; &lt;code&gt;xrange&lt;/code&gt; in the example above produces the values 0 through 9, inclusive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note 2:&lt;/strong&gt; This syntax is called a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.pythonforbeginners.com/basics/list-comprehensions-in-python&#34;
&gt;list comprehension&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;looping-over-every-element-read-only&#34;
    &gt;
        Looping over every element (read-only):
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#looping-over-every-element-read-only&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Looping over every element (read-only):&#34; aria-label=&#34;Anchor Looping over every element (read-only):&#34; href=&#34;#looping-over-every-element-read-only&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;, {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;c&amp;#39;&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:#66d9ef&#34;&gt;for&lt;/span&gt; e &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; A:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print e
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;looping-over-every-element-readwrite&#34;
    &gt;
        Looping over every element (read/write):
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#looping-over-every-element-readwrite&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Looping over every element (read/write):&#34; aria-label=&#34;Anchor Looping over every element (read/write):&#34; href=&#34;#looping-over-every-element-readwrite&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;, {&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;c&amp;#39;&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:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; xrange(len(A)):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print i, A[i]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;appending-elements-to-the-end-of-a-list&#34;
    &gt;
        Appending elements to the end of a list:
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#appending-elements-to-the-end-of-a-list&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Appending elements to the end of a list:&#34; aria-label=&#34;Anchor Appending elements to the end of a list:&#34; href=&#34;#appending-elements-to-the-end-of-a-list&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;append&lt;/code&gt; method can be used for the same purpose.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;inserting-elements&#34;
    &gt;
        Inserting elements:
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#inserting-elements&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Inserting elements:&#34; aria-label=&#34;Anchor Inserting elements:&#34; href=&#34;#inserting-elements&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;insert(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)  &lt;span style=&#34;color:#75715e&#34;&gt;# position, value&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;insert&lt;/code&gt; call above places the new element at the front of the list.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;finding-elements-in-a-list&#34;
    &gt;
        Finding elements in a list:
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#finding-elements-in-a-list&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Finding elements in a list:&#34; aria-label=&#34;Anchor Finding elements in a list:&#34; href=&#34;#finding-elements-in-a-list&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;index(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;index&lt;/code&gt; performs a linear search for the given value. If the value isn&amp;rsquo;t in the list, a &lt;code&gt;ValueError&lt;/code&gt; is raised.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;removing-elements-from-a-list&#34;
    &gt;
        Removing elements from a list:
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#removing-elements-from-a-list&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Removing elements from a list:&#34; aria-label=&#34;Anchor Removing elements from a list:&#34; href=&#34;#removing-elements-from-a-list&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;remove(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)  &lt;span style=&#34;color:#75715e&#34;&gt;# by value&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:#66d9ef&#34;&gt;del&lt;/span&gt; A[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;]     &lt;span style=&#34;color:#75715e&#34;&gt;# by index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;using-a-python-list-as-a-stack&#34;
    &gt;
        Using a Python list as a stack:
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#using-a-python-list-as-a-stack&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Using a Python list as a stack:&#34; aria-label=&#34;Anchor Using a Python list as a stack:&#34; href=&#34;#using-a-python-list-as-a-stack&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;append(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)          &lt;span style=&#34;color:#75715e&#34;&gt;# always add to the end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;stacktop &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; A&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;pop()   &lt;span style=&#34;color:#75715e&#34;&gt;# returns 2, the most recently added element&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;pop&lt;/code&gt; raises an &lt;code&gt;IndexError&lt;/code&gt; if the list is empty.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;using-a-python-list-as-a-queue&#34;
    &gt;
        Using a Python list as a queue:
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/python_cheat_sheet_lists/#using-a-python-list-as-a-queue&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Using a Python list as a queue:&#34; aria-label=&#34;Anchor Using a Python list as a queue:&#34; href=&#34;#using-a-python-list-as-a-queue&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;A &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;insert(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;A&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;insert(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)    &lt;span style=&#34;color:#75715e&#34;&gt;# always insert at the front of the list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;elem &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; A&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;pop()    &lt;span style=&#34;color:#75715e&#34;&gt;# returns 1, the earliest element added&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For an optimized implementation of both stacks and queues, take a look at &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://docs.python.org/2/library/collections.html#collections.deque&#34;
&gt;collections.deque&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for today. Have fun!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/python" term="python" label="Python" />  
                                <category scheme="https://www.brainware.ro/tags/python" term="python" label="python" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Setting up a Secure Linux Server</title>
            <link href="https://www.brainware.ro/posts/linux_server_secure/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/linux_server_secure/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-12-10T10:18:07+00:00</published>
            <updated>2015-12-10T10:18:07+00:00</updated>
            <content type="html">
                &lt;p&gt;No server is ever completely secure. Whenever you expose services to the public, someone will eventually try to attack them, whether through privilege escalation or denial of service. What you can do is reduce the odds that an attack succeeds, or at least limit the damage it causes.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/securing-server.webp&#34;
  alt=&#34;Servers in Data Center&#34;
  
/&gt;&lt;/p&gt;
&lt;p&gt;This article doesn&amp;rsquo;t cover advanced security techniques. It covers practical, common-sense measures that will stop most opportunistic attackers and automated bots. Let&amp;rsquo;s begin.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-set-up-iptables&#34;
    &gt;
        1. Set Up iptables
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_server_secure/#1-set-up-iptables&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Set Up iptables&#34; aria-label=&#34;Anchor 1. Set Up iptables&#34; href=&#34;#1-set-up-iptables&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You might wonder why you need a configured firewall if your server runs only three services and those are the only ones listening on sockets.&lt;/p&gt;
&lt;p&gt;The answer: a firewall is &lt;strong&gt;always&lt;/strong&gt; necessary. A &amp;ldquo;deny everything, allow exceptions&amp;rdquo; policy makes any rogue service an attacker manages to plant through privilege escalation useless, since it can&amp;rsquo;t be reached from outside.&lt;/p&gt;
&lt;p&gt;On RedHat/CentOS 6 systems, the firewall rules live in &lt;strong&gt;/etc/sysconfig/iptables&lt;/strong&gt;. A typical restrictive configuration looks like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m multiport --dports 22,80,443 -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This configuration accepts new TCP connections to ports 22 (SSH), 80 (HTTP) and 443 (HTTPS). It permits all outgoing traffic along with the replies to it, and allows ICMP (ping). Everything else is blocked.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-secure-tmp&#34;
    &gt;
        2. Secure /tmp
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_server_secure/#2-secure-tmp&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Secure /tmp&#34; aria-label=&#34;Anchor 2. Secure /tmp&#34; href=&#34;#2-secure-tmp&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;/tmp&lt;/strong&gt; is the best-known place on a Linux server where anyone can create files. In a default installation it&amp;rsquo;s just another directory on the root partition, which leads to problems such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An attacker can create huge numbers of files in &lt;strong&gt;/tmp&lt;/strong&gt;, filling the disk or, worse, exhausting the file system&amp;rsquo;s inodes.&lt;/li&gt;
&lt;li&gt;Attack scripts can be dropped into &lt;strong&gt;/tmp&lt;/strong&gt; and executed, hoping to exploit a kernel bug or a flaw in a daemon running as root.&lt;/li&gt;
&lt;li&gt;If a scripting language isn&amp;rsquo;t powerful enough for the attack, the attacker may even bring a compiler and build a binary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The fix is to give &lt;strong&gt;/tmp&lt;/strong&gt; its own mount point and apply special &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/mount&#34;
&gt;mount options&lt;/a&gt;: &lt;strong&gt;noexec&lt;/strong&gt; or, if that isn&amp;rsquo;t possible, &lt;strong&gt;nosuid&lt;/strong&gt;. The first prevents anything from being executed in &lt;strong&gt;/tmp&lt;/strong&gt;, even by the superuser. The second disables the &amp;ldquo;suid&amp;rdquo; bit on executables, blocking a class of privilege escalation techniques that rely on such scripts or binaries.&lt;/p&gt;
&lt;p&gt;An example &lt;strong&gt;/etc/fstab&lt;/strong&gt; entry:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/dev/xvdf2	/tmp	xfs		defaults,nosuid,noexec	1 2
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-isolate-user-files&#34;
    &gt;
        3. Isolate User Files
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_server_secure/#3-isolate-user-files&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. Isolate User Files&#34; aria-label=&#34;Anchor 3. Isolate User Files&#34; href=&#34;#3-isolate-user-files&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;User files may live in &lt;strong&gt;/home&lt;/strong&gt; (a classic Linux setup) or somewhere under &lt;strong&gt;/var&lt;/strong&gt; (typical for a web server). Either way, they should sit on a dedicated mount point, for several important reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Storage_Administration_Guide/ch-disk-quotas.html&#34;
&gt;Disk quotas&lt;/a&gt; can only be enforced per mount point, so a dedicated one makes setup simpler.&lt;/li&gt;
&lt;li&gt;Even without quotas, no user can cripple the server by filling the disk or using up all the inodes.&lt;/li&gt;
&lt;li&gt;Hard links to system files become impossible. Otherwise, a rogue user could keep a copy of a vulnerable &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.redhat.com/en/blog/suid-sgid-sticky-bit&#34;
&gt;suid binary&lt;/a&gt; for their own use, and the sysadmin would never know.&lt;/li&gt;
&lt;li&gt;Mount options such as &lt;strong&gt;noexec&lt;/strong&gt; or &lt;strong&gt;nosuid&lt;/strong&gt; can be applied to user files alone without affecting the rest of the system.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;4-allow-ssh-key-login-only&#34;
    &gt;
        4. Allow SSH Key Login Only
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_server_secure/#4-allow-ssh-key-login-only&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 4. Allow SSH Key Login Only&#34; aria-label=&#34;Anchor 4. Allow SSH Key Login Only&#34; href=&#34;#4-allow-ssh-key-login-only&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Password login is insecure: passwords are easier to steal and guess than private keys. On large installations with many nodes, remembering and typing passwords for every login is also impractical and tedious.&lt;/p&gt;
&lt;p&gt;Disabling password authentication completely shuts out brute-force bots, which then have no theoretical chance of getting in.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;5-disable-root-login-in-production&#34;
    &gt;
        5. Disable Root Login in Production
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_server_secure/#5-disable-root-login-in-production&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 5. Disable Root Login in Production&#34; aria-label=&#34;Anchor 5. Disable Root Login in Production&#34; href=&#34;#5-disable-root-login-in-production&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This one arguably belongs at the top of the list. In production, there should be no direct root access, by password or by SSH key, without exception. All administrative work should be done through &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/sudo&#34;
&gt;sudo&lt;/a&gt; from a dedicated, ordinary user account that is reachable only by SSH key.&lt;/p&gt;
&lt;p&gt;In lower-level environments or fully private servers, this rule can safely be relaxed.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;6-other-measures&#34;
    &gt;
        6. Other Measures
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_server_secure/#6-other-measures&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 6. Other Measures&#34; aria-label=&#34;Anchor 6. Other Measures&#34; href=&#34;#6-other-measures&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Enable &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/SYN_cookies&#34;
&gt;SYN cookies&lt;/a&gt; if they aren&amp;rsquo;t already on by default.&lt;/li&gt;
&lt;li&gt;Use a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.fail2ban.org/wiki/index.php/Main_Page&#34;
&gt;fail2ban&lt;/a&gt;-style tool.&lt;/li&gt;
&lt;li&gt;Consider using &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Security-Enhanced_Linux&#34;
&gt;SELinux&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s all. I hope you found it useful!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/security" term="security" label="Security" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Crazy DevOps Interview Questions (2)</title>
            <link href="https://www.brainware.ro/posts/crazy_devops_interview_2/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/crazy_devops_interview_2/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-11-24T17:41:57+00:00</published>
            <updated>2015-11-24T17:41:57+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is the second article of the series. The others are: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_1/&#34;
&gt;part 1&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/&#34;
&gt;part 3&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_4/&#34;
&gt;part 4&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-1&#34;
    &gt;
        Question 1
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_2/#question-1&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 1&#34; aria-label=&#34;Anchor Question 1&#34; href=&#34;#question-1&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Imagine you run these commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cd /tmp&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:#75715e&#34;&gt;# mkdir a&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:#75715e&#34;&gt;# cd a&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:#75715e&#34;&gt;# mkdir b&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:#75715e&#34;&gt;# cd b&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:#75715e&#34;&gt;# ln /tmp/a a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What happens?&lt;/p&gt;
&lt;p&gt;A candidate might note that this hardlink would create a circular reference. That&amp;rsquo;s right, but it&amp;rsquo;s only part of the story. How would the operating system or file system actually deal with the command?&lt;/p&gt;
&lt;p&gt;A command-line expert might brush the question off by saying hardlinks to directories aren&amp;rsquo;t allowed. Another might notice that &lt;code&gt;ln&lt;/code&gt; is missing the &lt;code&gt;-d&lt;/code&gt; option, so the command fails before anything else. Both are correct, but neither is the full answer an interviewer is looking for.&lt;/p&gt;
&lt;p&gt;A complete answer should cover the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most file systems forbid directory hardlinks, but not all. The best-known exception is &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/HFS_Plus&#34;
&gt;HFS+ (Apple OS X)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;By definition, hard links are directory entries that point to the same inode. The inode holds a link counter, and deleting a hard link only removes the file itself once that counter reaches 1.&lt;/li&gt;
&lt;li&gt;Directory hard links aren&amp;rsquo;t inherently dangerous, so that&amp;rsquo;s not why they&amp;rsquo;re disallowed. The real problem is the circular reference described above. &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Graph_theory&#34;
&gt;Graph theory&lt;/a&gt; can solve it, but doing so takes a lot of CPU and memory.&lt;/li&gt;
&lt;li&gt;The decision to forbid directory hard links was made because of that cost, which grows as the file system gets larger.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A thorough answer like this is what you&amp;rsquo;d typically expect in an interview at one of the &amp;ldquo;Big Four&amp;rdquo; technology companies.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-2&#34;
    &gt;
        Question 2
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_2/#question-2&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 2&#34; aria-label=&#34;Anchor Question 2&#34; href=&#34;#question-2&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Suppose you run this command on Linux:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# mv /home/testuser/magicalapp /usr/local/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What does it do, and how does it work? If it doesn&amp;rsquo;t work, why not?&lt;/p&gt;
&lt;p&gt;The answer comes down to how &lt;code&gt;mv&lt;/code&gt; basically works. It doesn&amp;rsquo;t necessarily move any data. Most of the time it just creates a new directory entry at the destination that points to the same inode as the source, and the source entry is removed in the process.&lt;/p&gt;
&lt;p&gt;When the source and destination are on different file systems, &lt;code&gt;mv&lt;/code&gt; generally behaves like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cp -r /home/testuser/magicalapp /usr/local/&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:#75715e&#34;&gt;# rm -rf /home/testuser/magicalapp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note 1:&lt;/strong&gt; Very old versions of &lt;code&gt;mv&lt;/code&gt; couldn&amp;rsquo;t move directories between file systems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note 2:&lt;/strong&gt; The PowerShell equivalent (move item) works differently. It can move files across file systems but has no recursion option.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a good interview question, don&amp;rsquo;t you think? I&amp;rsquo;m not sure how many candidates would get it right.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-3&#34;
    &gt;
        Question 3
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_2/#question-3&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 3&#34; aria-label=&#34;Anchor Question 3&#34; href=&#34;#question-3&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;What does each field in the CPU usage line of &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/top&#34;
&gt;top&lt;/a&gt; mean (for example &lt;code&gt;us&lt;/code&gt;, &lt;code&gt;sy&lt;/code&gt;, &lt;code&gt;wa&lt;/code&gt;)?&lt;/p&gt;
&lt;p&gt;The general answer is that these fields are percentages that add up to 100. Each one shows the share of CPU time spent on a particular kind of work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;us&lt;/strong&gt;: user-space programs, meaning ordinary processing that isn&amp;rsquo;t otherwise categorized.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sy&lt;/strong&gt;: kernel-mode processing, i.e. everything the kernel does.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ni&lt;/strong&gt;: user-space programs running with a modified priority via &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Nice_%28Unix%29&#34;
&gt;nice&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;id&lt;/strong&gt;: idle time, when the CPU effectively runs &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/NOP&#34;
&gt;NOP instructions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;wa&lt;/strong&gt;: time spent waiting on a resource such as a disk or the network. It doesn&amp;rsquo;t mean busy-waiting. It&amp;rsquo;s CPU time spent sending or receiving raw data to or from external devices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;hi&lt;/strong&gt;: time spent servicing hardware interrupts raised by external devices, such as a physical network card. A high value here can point to a DDoS against the network interface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;si&lt;/strong&gt;: time spent servicing software interrupts. User programs ask the kernel for services through software interrupts, though there can be other uses as well.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;st&lt;/strong&gt;: stolen time (not applicable on physical machines). This is CPU time taken by the hypervisor in a virtualized environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That wraps up the second installment of the interview questions. I hope you enjoyed it!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/interview" term="interview" label="Interview" /> 
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>A Bit of PowerShell Scripting</title>
            <link href="https://www.brainware.ro/posts/powershell_scripting/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/powershell_scripting/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-11-15T22:10:24+00:00</published>
            <updated>2015-11-15T22:10:24+00:00</updated>
            <content type="html">
                &lt;p&gt;Almost every large deployment ends up with a stray &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Windows_Server&#34;
&gt;Windows&lt;/a&gt; machine somewhere. Actually, that&amp;rsquo;s not quite right: plenty of organizations run on Windows exclusively. The reason is simple: most closed-source SDKs only work on Windows, so to use their features you have to build a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Windows_service&#34;
&gt;Windows service&lt;/a&gt;. Luckily for anyone who loves the command line, Microsoft provides an outstanding toolset in &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Windows_PowerShell&#34;
&gt;PowerShell&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When writing PowerShell code, keep two things in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Script files should use the &lt;strong&gt;.ps1&lt;/strong&gt; extension instead of &lt;strong&gt;.bat&lt;/strong&gt;. You will usually also need to &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://technet.microsoft.com/en-us/library/ee176961.aspx&#34;
&gt;change a security setting&lt;/a&gt; (the execution policy) before the system lets you run them.&lt;/li&gt;
&lt;li&gt;Most tasks can be done in a single line.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you come from Linux scripting, some behavior may seem strange. For example, you can&amp;rsquo;t directly move a directory; you have to copy it recursively and then delete the original. Still, the work gets done. Below are a few basic tasks you may need at some point.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;1-download-a-zip-file-from-an-http-server-and-extract-it&#34;
    &gt;
        1. Download a zip file from an HTTP server and extract it
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/powershell_scripting/#1-download-a-zip-file-from-an-http-server-and-extract-it&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 1. Download a zip file from an HTTP server and extract it&#34; aria-label=&#34;Anchor 1. Download a zip file from an HTTP server and extract it&#34; href=&#34;#1-download-a-zip-file-from-an-http-server-and-extract-it&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$source_file = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://internal.repo/package/module.zip&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$tmp_folder = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;C:\Temp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$dest_folder = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;C:\Program Files\Internal\Application&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;$source_file_name = [&lt;span style=&#34;color:#66d9ef&#34;&gt;io.path&lt;/span&gt;]::GetFileNameWithoutExtension($source_file)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$dest_zip = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$tmp_folder&lt;span style=&#34;color:#e6db74&#34;&gt;\&lt;/span&gt;$source_file_name&lt;span style=&#34;color:#e6db74&#34;&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;New-Item -ItemType Directory -Force -Path $tmp_folder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Invoke-WebRequest $source_file -OutFile $dest_zip
&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;New-Item -ItemType Directory -Force -Path $dest_folder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Add-Type -AssemblyName System.IO.Compression.FileSystem
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#66d9ef&#34;&gt;System.IO.Compression.ZipFile&lt;/span&gt;]::ExtractToDirectory($dest_zip, $dest_folder)
&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;Remove-Item -Path &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$dest_zip&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; -Force
&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:#75715e&#34;&gt;### No -Force for the temp folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Remove-Item -Path &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$tmp_folder&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;2-register-and-start-a-new-service&#34;
    &gt;
        2. Register and start a new service
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/powershell_scripting/#2-register-and-start-a-new-service&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 2. Register and start a new service&#34; aria-label=&#34;Anchor 2. Register and start a new service&#34; href=&#34;#2-register-and-start-a-new-service&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;New-Service -BinaryPathName $exePath -Name $serviceName -DisplayName $serviceName -description $serviceDescription -StartupType Automatic
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Start-Service $serviceName
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;3-stop-and-delete-a-service&#34;
    &gt;
        3. Stop and delete a service
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/powershell_scripting/#3-stop-and-delete-a-service&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 3. Stop and delete a service&#34; aria-label=&#34;Anchor 3. Stop and delete a service&#34; href=&#34;#3-stop-and-delete-a-service&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$existingService = Get-WmiObject -Class Win32_Service -Filter &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Name=&amp;#39;&lt;/span&gt;$serviceName&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&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:#66d9ef&#34;&gt;if&lt;/span&gt; ($existingService)
&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;	Stop-Service $serviceName
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;### We should sleep for a few seconds to give time for the service to stop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	Start-Sleep -s &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	$existingService.Delete()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;### When upgrading an existing service, if we are to put a new binary for the same name, we should also sleep a few seconds here&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;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;4-open-a-firewall-port-tcp&#34;
    &gt;
        4. Open a firewall port (TCP)
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/powershell_scripting/#4-open-a-firewall-port-tcp&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor 4. Open a firewall port (TCP)&#34; aria-label=&#34;Anchor 4. Open a firewall port (TCP)&#34; href=&#34;#4-open-a-firewall-port-tcp&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$port = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;30000&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$existing_fw_rule = netsh advfirewall firewall show rule name=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;access to port &lt;/span&gt;$port&lt;span style=&#34;color:#e6db74&#34;&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:#66d9ef&#34;&gt;if&lt;/span&gt; ($existing_fw_rule &lt;span style=&#34;color:#f92672&#34;&gt;-match&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;No rules match&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;	netsh advfirewall firewall add rule name=&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;access to port &lt;/span&gt;$port&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt; dir=&lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; action=allow protocol=TCP localport=$port
&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;That wraps up today&amp;rsquo;s PowerShell tips. Enjoy!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>AWSome Day Bucharest 2015</title>
            <link href="https://www.brainware.ro/posts/awsome_day_2015/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/awsome_day_2015/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-11-02T23:12:57+00:00</published>
            <updated>2015-11-02T23:12:57+00:00</updated>
            <content type="html">
                &lt;p&gt;Less than a month ago, I attended an &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/&#34;title=&#34;Amazon Web Services&#34;
&gt;Amazon&lt;/a&gt; event called &amp;ldquo;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/events/awsome-day/roadshow-romania/&#34;title=&#34;AWSome Day&#34;
&gt;&lt;strong&gt;AWSome Day&lt;/strong&gt;&lt;/a&gt;&amp;rdquo;. It was far from boring, and it clearly reflected the company&amp;rsquo;s image: polished, sophisticated and focused on the customer.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/awsome-day.webp&#34;
  alt=&#34;AWSome Day 2015&#34;
  
/&gt;&lt;/p&gt;
&lt;p&gt;The day had two parts. The first was lighter and business-oriented, while the second, after lunch, went deeper into the technical side. Still, it&amp;rsquo;s worth remembering one thing: when a product costs you nothing (or appears to), you are the product.&lt;/p&gt;
&lt;p&gt;Amazon covered the venue, the talks, lunch and refreshments, and in return delivered what amounted to a very classy sales pitch.&lt;/p&gt;
&lt;p&gt;The services covered in depth, or shown in the hands-on demo, were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Elastic Compute Cloud (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ec2/&#34;title=&#34;Amazon EC2&#34;
&gt;EC2&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Simple Storage Service (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/s3/&#34;title=&#34;Amazon S3&#34;
&gt;S3&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Content Delivery Web Service (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudfront/&#34;title=&#34;Amazon CloudFront&#34;
&gt;CloudFront&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/elasticloadbalancing/&#34;title=&#34;Elastic Load Balancing&#34;
&gt;Elastic Load Balancer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Relational Database Service (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/rds/&#34;title=&#34;Amazon RDS&#34;
&gt;Amazon RDS&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other services were mentioned only briefly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/elasticbeanstalk/&#34;title=&#34;Elastic Beanstalk&#34;
&gt;Elastic Beanstalk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/glacier/&#34;title=&#34;Amazon Glacier&#34;
&gt;Glacier Backup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/importexport/&#34;title=&#34;AWS Import/Export Snowball&#34;
&gt;AWS Import/Export Snowball&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudwatch/&#34;title=&#34;Amazon CloudWatch&#34;
&gt;CloudWatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/cloudformation/&#34;title=&#34;Amazon CloudFormation&#34;
&gt;CloudFormation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All in all, it was a packed day. The complete presentation is on SlideShare (&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://sebs.to/awsomedays&#34;title=&#34;AWSome Day Course Material - 2015&#34;
&gt;link&lt;/a&gt;) if you&amp;rsquo;d like to go through it again. Many slides were skipped because of time constraints, and the deck seems to describe even more AWS products.&lt;/p&gt;
&lt;p&gt;When thinking about &lt;strong&gt;the Cloud&lt;/strong&gt;, and &lt;strong&gt;Amazon Web Services&lt;/strong&gt; in particular, there are a few important points to keep in mind. As a product suite, AWS is a couple of years ahead of its competitors in terms of features and interface. Note, however, that there is competition: several companies offer similar services, sometimes at a lower price or with better cost efficiency than Amazon.&lt;/p&gt;
&lt;p&gt;In my opinion, AWS is the right choice for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Experiments, test deployments and temporary solutions;&lt;/li&gt;
&lt;li&gt;Non-production environments whose lifespan and makeup keep changing (e.g. development and/or QA);&lt;/li&gt;
&lt;li&gt;Unusually heavy loads lasting only a few days a year (e.g. traffic peaks on Black Friday or during Christmas sales);&lt;/li&gt;
&lt;li&gt;Medium- and long-term data storage (backups).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your environment is fixed and won&amp;rsquo;t change or scale significantly for a year or more (e.g. a production website and/or a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Software_as_a_service&#34;title=&#34;Software as a Service&#34;
&gt;SaaS&lt;/a&gt; product), AWS may not be the only cost-effective option to consider.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: if a similar event is held near you, go and reserve your seat! Just remember that you are attending a sales pitch.&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/architecture" term="architecture" label="architecture" /> 
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" />
        </entry>
        <entry>
            <title>Crazy DevOps Interview Questions (1)</title>
            <link href="https://www.brainware.ro/posts/crazy_devops_interview_1/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/crazy_devops_interview_1/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-10-28T22:09:57+00:00</published>
            <updated>2015-10-28T22:09:57+00:00</updated>
            <content type="html">
                &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There are three more episodes in this interview series: &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_2/&#34;
&gt;part 2&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_3/&#34;
&gt;part 3&lt;/a&gt; and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/crazy_devops_interview_4/&#34;
&gt;part 4&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nobody enjoys interviews. Well, maybe it depends on the day or on what side of the table you happen to be in.&lt;/p&gt;
&lt;p&gt;If an interviewer asks you any of the questions below, then they either have read this post or had drawn on the same sources I did. Either way, you&amp;rsquo;re now a step ahead.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-1&#34;
    &gt;
        Question 1
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_1/#question-1&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 1&#34; aria-label=&#34;Anchor Question 1&#34; href=&#34;#question-1&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;You log into a node and find this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# ls -la /bin/chmod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rw-r--r-- &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;56032&lt;/span&gt; ian &lt;span style=&#34;color:#ae81ff&#34;&gt;14&lt;/span&gt;  &lt;span style=&#34;color:#ae81ff&#34;&gt;2015&lt;/span&gt; /bin/chmod
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;chmod&lt;/code&gt; binary has lost its execute bit. Can this be fixed?&lt;/p&gt;
&lt;p&gt;Yes, most of the time. Remember how Linux starts executables: through a system loader, something like &lt;code&gt;ld-linux&lt;/code&gt;. Let&amp;rsquo;s find out which one &lt;code&gt;chmod&lt;/code&gt; uses:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# ldd /bin/chmod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	linux-vdso.so.1 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt;  &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0x00007ffdf27fc000&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	libc.so.6 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0x00007fb11a650000&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	/lib64/ld-linux-x86-64.so.2 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0x00007fb11aa15000&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now call the loader directly and let it run &lt;code&gt;chmod&lt;/code&gt; for you:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# /lib64/ld-linux-x86-64.so.2 /bin/chmod +x /bin/chmod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Neat, right? The obvious follow-up is: &amp;ldquo;What if the loader&amp;rsquo;s own permissions are wrong?&amp;rdquo; Not every filesystem problem has a simple command-line fix. You may have to mount the filesystem from a different installation (for example from a Live CD, or by attaching the virtual disk to another healthy node) and repair it from there.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-2&#34;
    &gt;
        Question 2
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_1/#question-2&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 2&#34; aria-label=&#34;Anchor Question 2&#34; href=&#34;#question-2&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;A running process hangs while reading from a socket. Variations: it may be &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Deadlock&#34;
&gt;deadlocked&lt;/a&gt; on a read or on a write, or it may keep receiving &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.gnu.org/software/libc/manual/html_node/Error-Codes.html&#34;
&gt;EAGAIN&lt;/a&gt; and sit in a &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Deadlock#Livelock&#34;
&gt;livelock&lt;/a&gt;. How do you close the bad socket / file descriptor without killing the process?&lt;/p&gt;
&lt;p&gt;First, where can we see the files and sockets a process has open, from the outside? In &lt;code&gt;/proc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# ps -e | grep myprocess&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:#ae81ff&#34;&gt;979&lt;/span&gt; pts/0    00:00:00 /usr/bin/myprocess
&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:#75715e&#34;&gt;# ls -la /proc/979/fd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;total &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dr-x------ &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; root   root  &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dr-xr-xr-x &lt;span style=&#34;color:#ae81ff&#34;&gt;9&lt;/span&gt; nobody dip   &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 ..
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lrwx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; -&amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lrwx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; -&amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lrwx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; -&amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lrwx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; -&amp;gt; socket:&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;9814&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lrwx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt; -&amp;gt; socket:&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;9816&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lrwx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; -&amp;gt; socket:&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;9817&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lrwx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt; -&amp;gt; socket:&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;9818&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lr-x------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; -&amp;gt; pipe:&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;9825&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;l-wx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; -&amp;gt; pipe:&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;9825&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lrwx------ &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root   root &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; oct &lt;span style=&#34;color:#ae81ff&#34;&gt;22&lt;/span&gt; 21:37 &lt;span style=&#34;color:#ae81ff&#34;&gt;9&lt;/span&gt; -&amp;gt; socket:&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;9827&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We now have the &lt;strong&gt;pid&lt;/strong&gt; and the &lt;strong&gt;fd&lt;/strong&gt; (file descriptor). You can&amp;rsquo;t remove or manipulate an open socket from outside the process, so we have to get inside, by using &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/gdb&#34;
&gt;gdb&lt;/a&gt;. Assuming &lt;code&gt;pid == 979&lt;/code&gt; and &lt;code&gt;fd == 9&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# gdb&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:#f92672&#34;&gt;(&lt;/span&gt;lots of output&lt;span style=&#34;color:#f92672&#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:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; attach &lt;span style=&#34;color:#ae81ff&#34;&gt;979&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Attaching to process &lt;span style=&#34;color:#ae81ff&#34;&gt;979&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:#f92672&#34;&gt;(&lt;/span&gt;lots of output&lt;span style=&#34;color:#f92672&#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:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; p close&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;9&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$1 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&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:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; detach
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Detaching from program: /usr/bin/myprocess, process &lt;span style=&#34;color:#ae81ff&#34;&gt;979&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:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; quit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tricky, wasn&amp;rsquo;t it? An interviewer who asks this is probably looking for a real expert.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;question-3&#34;
    &gt;
        Question 3
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/crazy_devops_interview_1/#question-3&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Question 3&#34; aria-label=&#34;Anchor Question 3&#34; href=&#34;#question-3&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;How would you deal with this situation?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# ls&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bash: fork: retry: Resource temporarily unavailable
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In short, the system has run out of pids, and this shell is the only access you have left.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Fork_bomb&#34;
&gt;classic fork bomb question&lt;/a&gt; that companies such as &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.google.com&#34;
&gt;Google&lt;/a&gt; sometimes ask. They aren&amp;rsquo;t after one definitive answer (none exists); they want to see how you approach the problem.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Realistically, the system may be so overloaded (many processes &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.cyberciti.biz/tips/howto-linux-increase-pid-limits.html&#34;
&gt;compete for CPU time&lt;/a&gt;) that a hard reboot is the only real fix. In an interview, though, you&amp;rsquo;re usually expected to give a &amp;ldquo;clever&amp;rdquo; answer with shell scripting tricks.&lt;/p&gt;
&lt;p&gt;Before writing that answer, three sub-problems need solving beforehand:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How do you find the process name? In a fork bomb, the same name often occupies all the available pids.&lt;/li&gt;
&lt;li&gt;Once you have the name, how do you identify every matching pid?&lt;/li&gt;
&lt;li&gt;Once you have a (very long) pid list, how do you run the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/kill&#34;
&gt;kill command&lt;/a&gt;?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Interviewers rarely ask about the first; the name is usually &amp;ldquo;known,&amp;rdquo; or can be found by trial and error in &lt;code&gt;/proc/&lt;/code&gt;. Even that isn&amp;rsquo;t trivial, since &lt;code&gt;ls&lt;/code&gt; and &lt;code&gt;cat&lt;/code&gt; are external commands and can&amp;rsquo;t be launched. Shell builtins could do it, though:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# read t &amp;lt; /proc/1091/cmdline ; echo $t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/usr/sbin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can also iterate over the pids with builtins only. (Note: &lt;code&gt;while&lt;/code&gt; spawns a process, so it can&amp;rsquo;t be used here.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# for p in /proc/[0-9]* ; do echo ${p#/proc/} ; done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... long pid list, one per line ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now to the process killing part. A plain &lt;code&gt;kill -9&lt;/code&gt; is easy but doesn&amp;rsquo;t solve anything: each freed pid just lets another process spawn. So you need two passes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Freeze all the offending processes (&lt;code&gt;kill -SIGSTOP&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Then remove them (&lt;code&gt;kill -SIGKILL&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The code looks like this. (Note: the double-bracket &lt;code&gt;[[ ... ]]&lt;/code&gt; form is a builtin, while the single-bracket &lt;code&gt;[&lt;/code&gt; starts a new process.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# for p in /proc/[0-9]*/cmdline ; do read cmd &amp;lt; $p ; if [[ $cmd = &amp;#39;bomb_process_name&amp;#39; ]]; then t=${p%/cmdline} ; kill -SIGSTOP ${t#/proc/} ; fi ; done&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:#75715e&#34;&gt;# for p in /proc/[0-9]*/cmdline ; do read cmd &amp;lt; $p ; if [[ $cmd = &amp;#39;bomb_process_name&amp;#39; ]]; then t=${p%/cmdline} ; kill -SIGKILL ${t#/proc/} ; fi ; done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The string comparison relies on whitespace around the variable, the equals sign and the string. &lt;code&gt;a = &amp;quot;xxx&amp;quot;&lt;/code&gt; is a comparison, while &lt;code&gt;a=&amp;quot;xxx&amp;quot;&lt;/code&gt; is an assignment in Bash.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;=&lt;/code&gt; and &lt;code&gt;==&lt;/code&gt; behave identically in this comparison.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;#&lt;/code&gt; and &lt;code&gt;%&lt;/code&gt; operators remove the shortest match. Since we match a fixed string rather than a pattern, &lt;code&gt;##&lt;/code&gt; and &lt;code&gt;%%&lt;/code&gt; (longest match) would give the same result.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cmdline&lt;/code&gt; in &lt;code&gt;/proc/&amp;lt;pid&amp;gt;&lt;/code&gt; is not a reliable source for the process name. It works against simple bash fork bombs or sloppy code, but a determined attacker can randomize it, for example with &lt;code&gt;snprintf(argv[0], size, &amp;quot;randomstuff&amp;quot;)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Other sources (&lt;code&gt;/proc/&amp;lt;pid&amp;gt;/comm&lt;/code&gt;, &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/status&lt;/code&gt;) can also be overridden, for example with &lt;code&gt;prctl(PR_SET_NAME, (char*) &amp;quot;randomstuff&amp;quot;)&lt;/code&gt;. Yes, yes, I know about &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://en.cppreference.com/w/cpp/language/const_cast&#34;
&gt;const_cast&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Follow-up questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What if the bomb is a bash fork bomb and you&amp;rsquo;re in a bash shell? Wouldn&amp;rsquo;t the first loop kill your own shell too?&lt;/li&gt;
&lt;li&gt;What if &lt;code&gt;kill&lt;/code&gt; isn&amp;rsquo;t a builtin and only the external version exists?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not everything can be solved cleanly. &lt;code&gt;/proc/self&lt;/code&gt; is a symlink to your own pid, and &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/1/readlink&#34;
&gt;readlink&lt;/a&gt; can read it, but that&amp;rsquo;s an external command. Luckily, the builtin &lt;code&gt;echo $$&lt;/code&gt; gives you your own pid, which you can exclude in the &lt;code&gt;if&lt;/code&gt; condition above.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;kill&lt;/code&gt; only available as an external command, I&amp;rsquo;m not sure the problem can always be solved.&lt;/p&gt;
&lt;p&gt;If a normal user triggered the bomb, you can immediately append a limit to &lt;code&gt;/etc/security/limits.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;forkuser hard nproc 20&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; /etc/security/limits.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This stops the active part of the bomb: even if you run &lt;code&gt;exec ...&lt;/code&gt; in the terminal, the fork bomb can&amp;rsquo;t claim the pid. Running the second kill command will then probably free enough pids for normal operation to resume.&lt;/p&gt;
&lt;p&gt;If the user is root, or has certain capabilities such as &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://man7.org/linux/man-pages/man7/capabilities.7.html&#34;
&gt;CAP_SYS_ADMIN&lt;/a&gt;, this option doesn&amp;rsquo;t work. Collecting all the pids in a shell variable and running &lt;code&gt;exec /usr/bin/kill&lt;/code&gt; then locks you out when it&amp;rsquo;s time for the second command of the pair. Cleaning up the now stale pids becomes the hard part.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There&amp;rsquo;s no guarantee that the pid released by the vanished shell stays free for another process under your control. Other daemons on the machine may compete for the same resource.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Still, you can try:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Cron&#34;
&gt;cron&lt;/a&gt;&lt;/strong&gt;: a best-effort approach, since there&amp;rsquo;s no guarantee cron can run.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.tldp.org/LDP/sag/html/config-init.html&#34;
&gt;inittab&lt;/a&gt;&lt;/strong&gt;, if the system has one (newer distributions don&amp;rsquo;t). Put the kill commands into a file executed on switching to a runlevel (e.g. 4), then force the change with &lt;code&gt;telinit&lt;/code&gt;. Again, no guarantees.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On machines you can physically access, you usually have several login screens available via key combinations like &lt;strong&gt;ALT + digit&lt;/strong&gt;, which lets you get back in. On machines reached through virtual terminals (ssh, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/Xterm&#34;
&gt;xterm&lt;/a&gt;, &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://en.wikipedia.org/wiki/GNOME_Terminal&#34;
&gt;GNOME Terminal&lt;/a&gt;), that isn&amp;rsquo;t possible, so the question has no real answer there.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it for today&amp;rsquo;s &amp;ldquo;crazy&amp;rdquo; interview questions. Hope you enjoyed them!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/interview" term="interview" label="Interview" /> 
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" /> 
                                <category scheme="https://www.brainware.ro/tags/companies" term="companies" label="companies" /> 
                                <category scheme="https://www.brainware.ro/tags/interview" term="interview" label="interview" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>What is DevOps?</title>
            <link href="https://www.brainware.ro/posts/what_is_devops/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/what_is_devops/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-10-25T21:37:57+00:00</published>
            <updated>2015-10-25T21:37:57+00:00</updated>
            <content type="html">
                &lt;p&gt;&lt;strong&gt;DevOps&lt;/strong&gt;: Some people dismiss it as hype or as the sysadmin role under a new name, while others see it as just another skill you pick up from a course or a degree. It is none of these. In my view, it is a blend of skills: some come from school, some from formal training, and the rest from hands-on work day to day.&lt;/p&gt;
&lt;p&gt;&lt;img
  src=&#34;https://www.brainware.ro/images/devops-template.webp&#34;
  alt=&#34;DevOps&#34;
  title=&#34;DevOps&#34;
/&gt;&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;why-isnt-it-simply-a-renamed-sysadmin-role&#34;
    &gt;
        Why isn&amp;rsquo;t it simply a renamed SysAdmin role?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/what_is_devops/#why-isnt-it-simply-a-renamed-sysadmin-role&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Why isn&amp;rsquo;t it simply a renamed SysAdmin role?&#34; aria-label=&#34;Anchor Why isn&amp;rsquo;t it simply a renamed SysAdmin role?&#34; href=&#34;#why-isnt-it-simply-a-renamed-sysadmin-role&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;A &amp;ldquo;classical&amp;rdquo; SysAdmin generally doesn&amp;rsquo;t rely on sophisticated automation tools. The typical routine means moving from one node to the next, applying configurations, installing software, and repairing whatever is broken.&lt;/li&gt;
&lt;li&gt;A standard SysAdmin role usually involves no real programming beyond small scripts that run on individual nodes.&lt;/li&gt;
&lt;li&gt;A &amp;ldquo;classical&amp;rdquo; SysAdmin typically works with physical machines, and much of the day goes to storage problems (rebuilding file systems, restoring from backups), tracking down hardware incompatibilities, and applying patches.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;why-do-serious-formal-coding-skills-matter-for-a-devops-engineer&#34;
    &gt;
        Why do serious, formal coding skills matter for a DevOps engineer?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/what_is_devops/#why-do-serious-formal-coding-skills-matter-for-a-devops-engineer&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Why do serious, formal coding skills matter for a DevOps engineer?&#34; aria-label=&#34;Anchor Why do serious, formal coding skills matter for a DevOps engineer?&#34; href=&#34;#why-do-serious-formal-coding-skills-matter-for-a-devops-engineer&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;The current industry trend is to describe infrastructure as &lt;strong&gt;Code&lt;/strong&gt;. Today you can create whole environments (for example on &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com&#34;title=&#34;Amazon Web Services&#34;
&gt;AWS&lt;/a&gt;), complete with correctly sized hardware and pre-installed services, using nothing but &lt;strong&gt;Code&lt;/strong&gt;. Automation tools like Ansible or Chef make all this possible. It takes more than basic scripting, though it doesn&amp;rsquo;t call for complex algorithms either.&lt;/p&gt;
&lt;p&gt;As noted above, &lt;strong&gt;DevOps&lt;/strong&gt; is defined by &lt;strong&gt;Automation&lt;/strong&gt;, since working with nodes is no longer almost entirely manual. Commands now run against many nodes simultaneously, and automated monitoring tools raise alerts and sometimes trigger corrective actions, such as scaling resources or adding new nodes to a cluster.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;who-needs-devops-skills&#34;
    &gt;
        Who needs DevOps skills?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/what_is_devops/#who-needs-devops-skills&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Who needs DevOps skills?&#34; aria-label=&#34;Anchor Who needs DevOps skills?&#34; href=&#34;#who-needs-devops-skills&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;In my opinion, any organization running a computing environment so large that scaling it through classical &lt;strong&gt;SysAdmin&lt;/strong&gt; work is no longer practical or cost-effective. The same goes for any organization planning to move its infrastructure to the &lt;strong&gt;Cloud&lt;/strong&gt;. Because this is a relatively new position that doesn&amp;rsquo;t fit neatly alongside &lt;strong&gt;Devs&lt;/strong&gt;, &lt;strong&gt;SysAdmins&lt;/strong&gt; or &lt;strong&gt;QAs&lt;/strong&gt;, it can be hard to define job requirements, map out a career path, or even settle on compensation, but that is beginning to change.&lt;/p&gt;
&lt;p&gt;That was my introduction to the &lt;strong&gt;DevOps&lt;/strong&gt; concept. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/nontechnical" term="nontechnical" label="Nontechnical" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/career" term="career" label="career" />
        </entry>
        <entry>
            <title>Simple E-Mail Config with Postfix and Cyrus IMAP</title>
            <link href="https://www.brainware.ro/posts/email_config_postfix_cyrus/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/email_config_postfix_cyrus/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-10-23T08:42:57+00:00</published>
            <updated>2015-10-23T08:42:57+00:00</updated>
            <content type="html">
                &lt;p&gt;This is a quick, no-frills guide to getting email running on a minimal Linux installation (Red Hat, Fedora or CentOS), such as the one you get when you launch a node in AWS from a predefined AMI (Amazon Machine Image).&lt;/p&gt;
&lt;p&gt;Red Hat-family distributions ship with &lt;strong&gt;Postfix&lt;/strong&gt; as the MTA (Mail Transport Agent) and &lt;strong&gt;Cyrus IMAP&lt;/strong&gt; as the MDA (Mail Delivery Agent), so this guide focuses on those two. Once both packages are installed, the work is mostly in the configuration files.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;key-configuration-files&#34;
    &gt;
        Key Configuration Files
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/email_config_postfix_cyrus/#key-configuration-files&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Key Configuration Files&#34; aria-label=&#34;Anchor Key Configuration Files&#34; href=&#34;#key-configuration-files&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;/etc/postfix/main.cf&lt;/code&gt;&lt;/strong&gt;: the Postfix configuration. It controls which emails are accepted and how they are handled.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;/etc/imapd.conf&lt;/code&gt;&lt;/strong&gt;: Cyrus IMAP settings, such as where mailbox passwords are stored and which authentication mechanisms POP/IMAP support.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;/etc/sasl2/smtpd.conf&lt;/code&gt;&lt;/strong&gt;: SMTP authentication settings, needed if you want to run a mail relay. (This file may instead be at &lt;code&gt;/usr/lib/sasl2/smtpd.conf&lt;/code&gt;.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is also &lt;strong&gt;&lt;code&gt;/etc/cyrus.conf&lt;/code&gt;&lt;/strong&gt;, which normally has sensible defaults after installation, so you probably won&amp;rsquo;t need to touch it. It defines the supported protocols (POP3, POP3S, IMAP, IMAPS) and the location of the LMTP socket, the interface between Postfix and Cyrus IMAP.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;step-1-configure-postfix&#34;
    &gt;
        Step 1: Configure Postfix
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/email_config_postfix_cyrus/#step-1-configure-postfix&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Step 1: Configure Postfix&#34; aria-label=&#34;Anchor Step 1: Configure Postfix&#34; href=&#34;#step-1-configure-postfix&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Add these essential settings to &lt;code&gt;/etc/postfix/main.cf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;mailbox_transport = lmtp:unix:/var/lib/imap/socket/lmtp
virtual_transport = $mailbox_transport
virtual_mailbox_domains = /etc/postfix/virtual_domains
virtual_mailbox_maps = hash:/etc/postfix/virtual_maps
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;What this does:&lt;/strong&gt; Mail addressed to the domains listed in &lt;code&gt;virtual_domains&lt;/code&gt; is accepted for further processing. Postfix then looks up the destination mailbox in &lt;code&gt;virtual_mailbox_maps&lt;/code&gt;; if no mailbox is found, an error goes back to the sender. Actual delivery happens through the socket defined in &lt;code&gt;mailbox_transport&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Example file contents:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cat /etc/postfix/virtual_domains&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brainware.ro
&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:#75715e&#34;&gt;# cat /etc/postfix/virtual_maps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;john.doe@brainware.ro	brainware.ro/john.doe
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;virtual_maps&lt;/code&gt; file must be converted into a hash database with &lt;code&gt;postmap&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# postmap hash:/etc/postfix/virtual_maps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;step-2-check-the-cyrus-imap-lmtp-socket&#34;
    &gt;
        Step 2: Check the Cyrus IMAP LMTP Socket
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/email_config_postfix_cyrus/#step-2-check-the-cyrus-imap-lmtp-socket&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Step 2: Check the Cyrus IMAP LMTP Socket&#34; aria-label=&#34;Anchor Step 2: Check the Cyrus IMAP LMTP Socket&#34; href=&#34;#step-2-check-the-cyrus-imap-lmtp-socket&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Confirm the Cyrus daemon is listening on the right LMTP socket (it should be by default):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cat /etc/cyrus.conf | grep lmtp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lmtpunix	cmd&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;lmtpd&amp;#34;&lt;/span&gt; listen&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/var/lib/imap/socket/lmtp&amp;#34;&lt;/span&gt; prefork&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; At this point you may want to either disable SELinux (easy), or add the required SELinux rules (harder) so that Postfix and Cyrus IMAP can communicate over the socket.&lt;/p&gt;
&lt;hr&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;step-3-configure-cyrus-imap&#34;
    &gt;
        Step 3: Configure Cyrus IMAP
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/email_config_postfix_cyrus/#step-3-configure-cyrus-imap&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Step 3: Configure Cyrus IMAP&#34; aria-label=&#34;Anchor Step 3: Configure Cyrus IMAP&#34; href=&#34;#step-3-configure-cyrus-imap&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;For corporate-style addresses (&lt;code&gt;name.surname@domain&lt;/code&gt;), the mailbox namespace separator has to be something other than the dot. Change it in &lt;code&gt;/etc/imapd.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;unixhierarchysep: 1		# changes the separator to &amp;#34;/&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Other settings to review in &lt;code&gt;imapd.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;admins: cyrus					# user allowed to run Cyrus admin commands
sasl_mech_list: plain login cram-md5 digest-md5 ntlm gssapi		# enable all mechanisms
sasl_pwcheck_method: auxprop	# look up passwords in /etc/sasldb2
virtdomains: userid				# derive the domain from the mailbox name (user@domain)
allowanonymouslogin: no			# security
allowplaintext: yes				# allow older login methods (e.g. testing with telnet)
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;step-4-restart-the-services&#34;
    &gt;
        Step 4: Restart the Services
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/email_config_postfix_cyrus/#step-4-restart-the-services&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Step 4: Restart the Services&#34; aria-label=&#34;Anchor Step 4: Restart the Services&#34; href=&#34;#step-4-restart-the-services&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Restart both services to apply the new configuration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# service postfix restart&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Shutting down postfix:				&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;  OK  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Starting postfix:					&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;  OK  &lt;span style=&#34;color:#f92672&#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:#75715e&#34;&gt;# service cyrus-imapd restart&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Shutting down cyrus-imapd:			&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;  OK  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Exporting cyrus-imapd databases:	&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;  OK  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Importing cyrus-imapd databases:	&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;  OK  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Starting cyrus-imapd:				&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;  OK  &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;step-5-create-the-admin-user-and-a-first-mailbox&#34;
    &gt;
        Step 5: Create the Admin User and a First Mailbox
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/email_config_postfix_cyrus/#step-5-create-the-admin-user-and-a-first-mailbox&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Step 5: Create the Admin User and a First Mailbox&#34; aria-label=&#34;Anchor Step 5: Create the Admin User and a First Mailbox&#34; href=&#34;#step-5-create-the-admin-user-and-a-first-mailbox&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;We&amp;rsquo;re close to done. First, check the permissions on &lt;code&gt;/etc/sasldb2&lt;/code&gt;. (Be aware that passwords are stored there without any encryption.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# ls -la /etc/sasldb2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-rw-r----- &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; cyrus mail &lt;span style=&#34;color:#ae81ff&#34;&gt;12288&lt;/span&gt; Oct &lt;span style=&#34;color:#ae81ff&#34;&gt;15&lt;/span&gt; 12:34 sasldb2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Before running &lt;code&gt;cyradm&lt;/code&gt; (the Cyrus IMAP admin tool) for the first time, set a password for the &lt;code&gt;cyrus&lt;/code&gt; admin user defined in &lt;code&gt;/etc/imapd.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# saslpasswd2 -c &amp;#34;cyrus&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Password:
&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;Now run &lt;code&gt;cyradm&lt;/code&gt;, create your first mailbox, then set its password:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cyradm -u cyrus localhost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;IMAP Password:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;localhost&amp;gt; cm user/john.doe@brainware.ro
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;localhost&amp;gt; quit
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# saslpasswd2 -c &amp;#34;john.doe@brainware.ro&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Password:
&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;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;step-6-test-pop3-login&#34;
    &gt;
        Step 6: Test POP3 Login
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/email_config_postfix_cyrus/#step-6-test-pop3-login&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Step 6: Test POP3 Login&#34; aria-label=&#34;Anchor Step 6: Test POP3 Login&#34; href=&#34;#step-6-test-pop3-login&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Test a plaintext POP3 login using telnet:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# telnet localhost 110&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Trying ::1...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Connected to localhost.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Escape character is &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;^]&amp;#39;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+OK ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;user john.doe@brainware.ro
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+OK Name is a valid mailbox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pass ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+OK Mailbox locked and ready
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;list
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+OK scan listing follows
&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;quit
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+OK
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Connection closed by foreign host.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;step-7-optional-relaying-with-smtp-authentication&#34;
    &gt;
        Step 7 (Optional): Relaying with SMTP Authentication
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/email_config_postfix_cyrus/#step-7-optional-relaying-with-smtp-authentication&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Step 7 (Optional): Relaying with SMTP Authentication&#34; aria-label=&#34;Anchor Step 7 (Optional): Relaying with SMTP Authentication&#34; href=&#34;#step-7-optional-relaying-with-smtp-authentication&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;If you also want to relay email using SMTP authentication, first enable it in Postfix by adding to &lt;code&gt;/etc/postfix/main.cf&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, permit
smtpd_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then set up the authentication mechanism in &lt;code&gt;/etc/sasl2/smtpd.conf&lt;/code&gt; (remember the alternate location, &lt;code&gt;/usr/lib/sasl2/smtpd.conf&lt;/code&gt;, mentioned above):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pwcheck_method: auxprop 		# use /etc/sasldb2
auxprop_plugin: sasldb
mech_list: plain login cram-md5 digest-md5 ntlm gssapi		# enable all mechanisms
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;wrapping-up&#34;
    &gt;
        Wrapping Up
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/email_config_postfix_cyrus/#wrapping-up&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Wrapping Up&#34; aria-label=&#34;Anchor Wrapping Up&#34; href=&#34;#wrapping-up&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;After one more Postfix restart, you should have a simple, working email service built on Postfix and Cyrus IMAP. Thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/tutorial" term="tutorial" label="Tutorial" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/tutorial" term="tutorial" label="tutorial" />
        </entry>
        <entry>
            <title>Gmail-style Aliasing with Postfix</title>
            <link href="https://www.brainware.ro/posts/gmail_style_alias_postfix/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/gmail_style_alias_postfix/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-10-20T10:43:57+00:00</published>
            <updated>2015-10-20T10:43:57+00:00</updated>
            <content type="html">
                &lt;p&gt;One of Gmail&amp;rsquo;s lesser-known features is plus addressing: e-mail sent to an alias of your main address, such as &lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;mailto:john.doe&amp;#43;22@gmail.com&#34;
&gt;john.doe+22@gmail.com&lt;/a&gt;&lt;/strong&gt;, is delivered to the main mailbox, &lt;strong&gt;&lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;mailto:john.doe@gmail.com&#34;
&gt;john.doe@gmail.com&lt;/a&gt;&lt;/strong&gt;, where it can be labeled and placed in different folders. (Note: this address is made up, and hopefully it doesn&amp;rsquo;t belong to a real person.)&lt;/p&gt;
&lt;p&gt;How could you reproduce this on a mail server you run yourself? I won&amp;rsquo;t go into every detail, just scratch the surface. With &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.postfix.org/&#34;
&gt;Postfix&lt;/a&gt; (the default MTA on Red Hat, Fedora and CentOS), the place to start is the &lt;a
  class=&#34;gblog-markdown__link--code&#34;
  href=&#34;http://www.postfix.org/postconf.5.html#virtual_alias_maps&#34;
&gt;&lt;code&gt;virtual_alias_maps&lt;/code&gt;&lt;/a&gt; option in the configuration file, &lt;code&gt;main.cf&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Maps are a core concept throughout Postfix&amp;rsquo;s configuration. A map translates an input (for example, an e-mail address) into a desired output (for example, a mailbox location on disk or the real destination address). Postfix treats &amp;ldquo;virtual&amp;rdquo; as anything not tied to a real Unix account. To get Gmail-style aliasing, you therefore need a virtual map that converts addresses containing a &lt;code&gt;+&lt;/code&gt; into the main mailbox address.&lt;/p&gt;
&lt;p&gt;Since the aliased addresses can&amp;rsquo;t be predicted in advance, the only way to match them to the real destination is with some kind of regular expression matching. Simple Postfix map types, such as hash tables, only do exact matching, so you could alias &lt;code&gt;john.doe+1&lt;/code&gt; to &lt;code&gt;john.doe&lt;/code&gt;, but that wouldn&amp;rsquo;t cover &lt;code&gt;john.doe+2&lt;/code&gt; or &lt;code&gt;john.doe+99&lt;/code&gt;, unless you added a separate line for each possible alias.&lt;/p&gt;
&lt;p&gt;The better news is that Postfix can match regular expressions through the corresponding built-in module, so the configuration could look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cat /etc/postfix/main.cf | grep virtual_alias_maps&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;virtual_alias_maps &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; regexp:/etc/postfix/virtual_alias
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;virtual_alias&lt;/code&gt; file could then contain:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# cat /etc/postfix/virtual_alias&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;/^sample.name+&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;.*&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;@brainware.ro$/	sample.name@brainware.ro
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works, but it has some drawbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Manual maintenance.&lt;/strong&gt; You have to edit the &lt;code&gt;virtual_alias&lt;/code&gt; file by hand to add new aliases. That isn&amp;rsquo;t practical for large installations where accounts are created and removed through web interfaces.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance.&lt;/strong&gt; Postfix itself performs the regex matching, which can in theory reduce mail throughput. On a busy server with thousands of such aliases this might become noticeable, though it&amp;rsquo;s probably not a serious problem on modern hardware.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The fix for both issues is to hand the address matching over to a database such as &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.mysql.com/&#34;
&gt;MySQL&lt;/a&gt; or &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.postgresql.org/&#34;
&gt;PostgreSQL&lt;/a&gt; and do the regex matching in a stored procedure. I may return to this in a later post, but for now, thanks for reading!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/tutorial" term="tutorial" label="Tutorial" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/tutorial" term="tutorial" label="tutorial" />
        </entry>
        <entry>
            <title>Adding Swap Space to a Node</title>
            <link href="https://www.brainware.ro/posts/linux_adding_swap/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/linux_adding_swap/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-10-16T09:24:57+00:00</published>
            <updated>2015-10-16T09:24:57+00:00</updated>
            <content type="html">
                &lt;p&gt;You might wonder why swap is even needed, because this isn&amp;rsquo;t enabled by default on any node in &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com&#34;
&gt;AWS&lt;/a&gt; or on any other cloud provider. The most likely reasons are the added complexity and the risk of wasting storage. And with instances now available with 200+ GB of RAM, why would anyone still need swap?&lt;/p&gt;
&lt;p&gt;Swap space can be a sensible option for small nodes with 1-2 GB of memory, such as &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://aws.amazon.com/ec2/instance-types/&#34;
&gt;t2.micro&lt;/a&gt;, but because of the performance penalty, this is not suitable for production workloads. For experiments, dev testing, or QA, though, small instances are a cost-effective choice for most use cases (&lt;code&gt;t2.micro&lt;/code&gt; is even free within certain limits during the first year).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you add swap to an EBS-backed node in AWS, keep the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://www.brainware.ro/posts/amazon_ebs_limitation/&#34;
&gt;EBS storage limitations&lt;/a&gt; in mind.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;creating-the-swap-file&#34;
    &gt;
        Creating the swap file
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_adding_swap/#creating-the-swap-file&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Creating the swap file&#34; aria-label=&#34;Anchor Creating the swap file&#34; href=&#34;#creating-the-swap-file&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;A few commands are enough to add swap (1 GB in this example):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# dd if=/dev/zero of=/swapfile bs=1024 count=1048576&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:#75715e&#34;&gt;# mkswap /swapfile&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:#75715e&#34;&gt;# swapon /swapfile&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:#75715e&#34;&gt;# echo -e &amp;#34;/swapfile\t\tswap\t\t\tswap\tdefaults\t0 0&amp;#34; &amp;gt;&amp;gt; /etc/fstab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These commands create a 1 GB file in the root directory, format it as swap, tell the kernel to use it, and register it in &lt;code&gt;/etc/fstab&lt;/code&gt; so it is enabled on every boot.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;tuning-swappiness&#34;
    &gt;
        Tuning swappiness
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/linux_adding_swap/#tuning-swappiness&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Tuning swappiness&#34; aria-label=&#34;Anchor Tuning swappiness&#34; href=&#34;#tuning-swappiness&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Creating the swap space may not be the whole job. You may also want to adjust the &amp;ldquo;swappiness&amp;rdquo; behavior, which controls when memory pages get moved to swap to free up RAM for running applications. This is governed by the kernel parameter &lt;code&gt;/proc/sys/vm/swappiness&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This parameter holds a number that represents the minimum amount of free memory the kernel tries to preserve before it starts swapping out pages. For example, a value of &lt;code&gt;10&lt;/code&gt; means no pages are swapped until free memory falls below 10%. From the console you can set it with &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/sysctl&#34;
&gt;sysctl&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# sysctl vm.swappiness=10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To make this setting survive reboots, add it to the system configuration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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:#75715e&#34;&gt;# echo &amp;#34;vm.swappiness=10&amp;#34; &amp;gt;&amp;gt; /etc/sysctl.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hope you found this useful. Have a nice day!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/tutorial" term="tutorial" label="Tutorial" />  
                                <category scheme="https://www.brainware.ro/tags/aws" term="aws" label="aws" /> 
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/tutorial" term="tutorial" label="tutorial" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" />
        </entry>
        <entry>
            <title>Worst Mistake when Creating a RPM...</title>
            <link href="https://www.brainware.ro/posts/rpm_scriptlets/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/rpm_scriptlets/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-10-16T09:24:57+00:00</published>
            <updated>2015-10-16T09:24:57+00:00</updated>
            <content type="html">
                &lt;p&gt;&amp;hellip;is overlooking the order in which RPM scriptlets are executed. Ideally, you want the package to behave like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;First install:&lt;/strong&gt; register the service with &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/chkconfig&#34;
&gt;chkconfig&lt;/a&gt; and start it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complete removal:&lt;/strong&gt; stop the service and unregister it from &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/chkconfig&#34;
&gt;chkconfig&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Upgrade:&lt;/strong&gt; stop the running service, replace the binary, and start the new version, leaving the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/chkconfig&#34;
&gt;chkconfig&lt;/a&gt; registration untouched.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The tempting shortcut is to skip the upgrade case entirely and assume that combining the removal and installation steps will cover it. In the &lt;strong&gt;.spec&lt;/strong&gt; file, that might look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;%post
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chkconfig --add my_wow_service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;service my_wow_service start
&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;%preun
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;service my_wow_service stop
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chkconfig --del my_wow_service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works fine as long as the package is only ever installed or removed. During an upgrade, however, this fails badly, because the scriptlets run in a different order than this example assumes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;%pre&lt;/strong&gt; of the new package&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;%post&lt;/strong&gt; of the new package&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;%preun&lt;/strong&gt; of the old package&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;%postun&lt;/strong&gt; of the old package&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As a result, an upgrade with these scriptlets leaves the service stopped and removed from &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://linux.die.net/man/8/chkconfig&#34;
&gt;chkconfig&lt;/a&gt;, which is a real problem.&lt;/p&gt;
&lt;p&gt;The fix is to check the first argument (&lt;code&gt;$1&lt;/code&gt;) that RPM passes to each scriptlet. RPM &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;https://fedoraproject.org/wiki/Packaging:ScriptletSnippets?rd=Packaging/ScriptletSnippets#Syntax&#34;
&gt;supplies a value&lt;/a&gt; that tells the script whether it is running during an install, a removal, or an upgrade. Using that value, we can write better scriptlets:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;%post
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; $1 -gt &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; ; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  service my_wow_service restart
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  chkconfig --add my_wow_service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  service my_wow_service start
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&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;%preun
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; $1 -eq &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; ; &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  service my_wow_service stop
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  chkconfig --del my_wow_service
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That solves the problem above.&lt;/p&gt;
&lt;p&gt;Hope you found this useful!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" /> 
                                <category scheme="https://www.brainware.ro/tags/tutorial" term="tutorial" label="tutorial" />
        </entry>
        <entry>
            <title>mail() Function in PHP and Bounced E-Mails</title>
            <link href="https://www.brainware.ro/posts/mail_php_bounces/" rel="alternate" type="text/html"  hreflang="en" />
            <id>https://www.brainware.ro/posts/mail_php_bounces/</id>
                    <author>
                        <name>Dan</name>
                    </author>
            <published>2015-10-08T19:15:57+00:00</published>
            <updated>2015-10-08T19:15:57+00:00</updated>
            <content type="html">
                &lt;p&gt;Everyone&amp;rsquo;s favorite way of sending spam is the &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://php.net/manual/en/function.mail.php&#34;
&gt;mail()&lt;/a&gt;  function in PHP. The question of the day is what happens to the bounced e-mails that may result from this operation.&lt;/p&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;where-do-bounced-e-mails-go&#34;
    &gt;
        Where do bounced e-mails go?
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/mail_php_bounces/#where-do-bounced-e-mails-go&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Where do bounced e-mails go?&#34; aria-label=&#34;Anchor Where do bounced e-mails go?&#34; href=&#34;#where-do-bounced-e-mails-go&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;No, they&amp;rsquo;re not necessarily sent back to the &amp;ldquo;From&amp;rdquo; address of the original message. Mail servers return undeliverable messages to the &lt;strong&gt;envelope sender&lt;/strong&gt;, which may or may not match the &amp;ldquo;From&amp;rdquo; field. There used to be a special header, &lt;code&gt;Errors-To&lt;/code&gt;, but it was deprecated and as of today that is often ignored.&lt;/p&gt;
&lt;p&gt;The envelope sender is set by the SMTP client when it connects to the server, so you might expect PHP&amp;rsquo;s &lt;code&gt;mail()&lt;/code&gt; to handle it intelligently. First, let&amp;rsquo;s see how the function really works, starting with &lt;code&gt;php.ini&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;[mail function]&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:#75715e&#34;&gt;; For Win32 only.&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:#a6e22e&#34;&gt;SMTP&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;localhost&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:#a6e22e&#34;&gt;smtp_port&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;25&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:#75715e&#34;&gt;; For Win32 only.&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:#a6e22e&#34;&gt;sendmail_from&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;me@example.com&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:#75715e&#34;&gt;; For Unix only. You may supply arguments as well (default: &amp;#34;sendmail -t -i&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:#a6e22e&#34;&gt;sendmail_path&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;/usr/sbin/sendmail -t -i&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On Windows, &lt;code&gt;mail()&lt;/code&gt; appears to handle everything by itself. On Linux, the work is delegated to an external program: &lt;code&gt;sendmail&lt;/code&gt;. The &lt;a
  class=&#34;gblog-markdown__link&#34;
  href=&#34;http://www.postfix.org/sendmail.1.html&#34;
&gt;sendmail man page&lt;/a&gt; (the Postfix version) explains the two flags that are used here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-i&lt;/strong&gt; When reading a message from standard input, don&amp;rsquo;t treat a line containing only a &lt;code&gt;.&lt;/code&gt; character as the end of input.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;-t&lt;/strong&gt; Extract recipients from the message headers. These are added to any recipients given on the command line.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So the &lt;code&gt;mail()&lt;/code&gt; function actually prepares the message and pipes it to &lt;code&gt;sendmail&lt;/code&gt;. How about the &lt;strong&gt;envelope sender&lt;/strong&gt;, this elusive piece of data we were actually looking for? The man page above has the answer as well:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-f sender&lt;/strong&gt; Set the envelope sender address. This is the address where delivery problems are sent. With Postfix versions before 2.1, the &lt;code&gt;Errors-To:&lt;/code&gt; message header overrides the error return address.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since no &lt;code&gt;-f&lt;/code&gt; parameter is being passed here, bounced e-mails end up being sent to one of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For older mail systems, the address in the &lt;code&gt;Errors-To:&lt;/code&gt; header (if you supplied one in the 4th parameter of &lt;code&gt;mail()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The address in the &lt;code&gt;Return-Path:&lt;/code&gt; header (if you supplied one in the 4th parameter of &lt;code&gt;mail()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The address automatically derived from the local user who ran the sendmail command (e.g. &lt;code&gt;apache&lt;/code&gt;, &lt;code&gt;nobody&lt;/code&gt; or a local user name). Postfix records all this in the automatically added &lt;code&gt;X-Postfix-Sender:&lt;/code&gt; header.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;flex align-center gblog-post__anchorwrap&#34;&gt;
    &lt;h3 id=&#34;avoiding-the-third-scenario&#34;
    &gt;
        Avoiding the third scenario
    &lt;/h3&gt;
    &lt;a data-clipboard-text=&#34;https://www.brainware.ro/posts/mail_php_bounces/#avoiding-the-third-scenario&#34; class=&#34;gblog-post__anchor clip flex align-center&#34; title=&#34;Anchor Avoiding the third scenario&#34; aria-label=&#34;Anchor Avoiding the third scenario&#34; href=&#34;#avoiding-the-third-scenario&#34;&gt;
        &lt;svg class=&#34;gblog-icon gblog_link&#34;&gt;&lt;use xlink:href=&#34;#gblog_link&#34;&gt;&lt;/use&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;To avoid the third case, we need to to work our way around this. First, note that &lt;code&gt;php.ini&lt;/code&gt; lets you replace the mail-sending program with your own script, which can do some additional processing before calling into &lt;code&gt;sendmail&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sendmail_path&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;/usr/local/sbin/sendmail_wrapper&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script needs the right permissions to run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#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;rwxr-xr-x &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; root root &lt;span style=&#34;color:#ae81ff&#34;&gt;814&lt;/span&gt; Oct &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt; 15:45 sendmail_wrapper
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You could write the wrapper in Python or Ruby, but PHP works nicely too, as long as the script itself doesn&amp;rsquo;t call &lt;code&gt;mail()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#!/usr/bin/php -q
&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:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;php&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:#a6e22e&#34;&gt;set_time_limit&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&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;$mtext &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$from &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$has_return_path &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&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:#75715e&#34;&gt;// Feel free to replace the regex with a better e-mail match
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$regex &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/[a-z0-9]+([_&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.-][a-z0-9]+)*@([a-z0-9]+([\.-][a-z0-9]+)*)+&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.[a-z]{2,}/i&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$stdin &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fopen&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;php://stdin&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;r&amp;#39;&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:#66d9ef&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;feof&lt;/span&gt;($stdin))
&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;  $cline &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fgets&lt;/span&gt;($stdin);
&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:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;((&lt;span style=&#34;color:#a6e22e&#34;&gt;strpos&lt;/span&gt;($cline, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Return-Path:&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;===&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&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:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;preg_match_all&lt;/span&gt;($regex, $cline, $matches, &lt;span style=&#34;color:#a6e22e&#34;&gt;PREG_PATTERN_ORDER&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      $has_return_path &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&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 style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;((&lt;span style=&#34;color:#a6e22e&#34;&gt;strpos&lt;/span&gt;($cline, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;From:&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;===&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&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:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;preg_match_all&lt;/span&gt;($regex, $cline, $matches, &lt;span style=&#34;color:#a6e22e&#34;&gt;PREG_PATTERN_ORDER&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      $from &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; $matches[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;][&lt;span style=&#34;color:#ae81ff&#34;&gt;0&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;  $mtext &lt;span style=&#34;color:#f92672&#34;&gt;.=&lt;/span&gt; $cline;
&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:#a6e22e&#34;&gt;fclose&lt;/span&gt;($stdin);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;empty&lt;/span&gt;($from) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;$has_return_path) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    $from_opt &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; -f&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt; $from;
&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;$fd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;popen&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/usr/sbin/sendmail -t -i&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt; $from_opt, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;w&amp;#39;&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:#a6e22e&#34;&gt;fwrite&lt;/span&gt;($fd, $mtext);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;pclose&lt;/span&gt;($fd);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is all that it is. Hope you found it useful!&lt;/p&gt;

            </content>  
                                <category scheme="https://www.brainware.ro/authors/dan" term="dan" label="dan" />  
                                <category scheme="https://www.brainware.ro/categories/scripts" term="scripts" label="Scripts" />  
                                <category scheme="https://www.brainware.ro/tags/linux" term="linux" label="linux" /> 
                                <category scheme="https://www.brainware.ro/tags/scripting" term="scripting" label="scripting" /> 
                                <category scheme="https://www.brainware.ro/tags/tutorial" term="tutorial" label="tutorial" />
        </entry>
</feed>
