<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Pete Freitag</title>
    <description>The latest articles on Forem by Pete Freitag (@pfreitag).</description>
    <link>https://forem.com/pfreitag</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F171021%2Fcc53bc5e-026a-4cfb-a267-acc927397457.jpg</url>
      <title>Forem: Pete Freitag</title>
      <link>https://forem.com/pfreitag</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pfreitag"/>
    <language>en</language>
    <item>
      <title>How I cut AWS Lambda Java Cold Start Times in Half</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Tue, 12 Apr 2022 19:56:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/how-i-cut-aws-lambda-java-cold-start-times-in-half-1ne4</link>
      <guid>https://forem.com/pfreitag/how-i-cut-aws-lambda-java-cold-start-times-in-half-1ne4</guid>
      <description>&lt;p&gt;It is rare that a simple JVM argument change can have a dramatic impact on execution times, but in the case of AWS Lambda adjusting the &lt;em&gt;Tiered Complication&lt;/em&gt; settings can have a really big impact on performance in many (but not all) cases.&lt;/p&gt;

&lt;p&gt;The change I made was to add the JVM arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-XX:+TieredCompilation -XX:TieredStopAtLevel=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On AWS Lambda you can do this by simply adding the environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JAVA_TOOL_OPTIONS = -XX:+TieredCompilation -XX:TieredStopAtLevel=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This chart below shows the average execution time of a Java (more specifically written in CFML and using &lt;a href="https://fuseless.org/"&gt;FuseLess&lt;/a&gt;) Lambda Function over the course of two days. I've annotated where I made the change and you can see average execution times cut in half, cold start times also cut in half (though the chart doesn't show that).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--anSc1Mjz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.petefreitag.com/images/blog/tieredcompilation-tieredstopatlevel-lambda.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--anSc1Mjz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.petefreitag.com/images/blog/tieredcompilation-tieredstopatlevel-lambda.jpg" alt="Chart of average lambda execution time before and after jvm change" width="880" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that this particular java lambda function that I used for testing does have some highly intensive invocations that might take up to 30 seconds to execute, after the change I didn't see any executions going above 15 seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is &lt;code&gt;TieredCompilation&lt;/code&gt; and what is &lt;code&gt;TieredStopAtLevel&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;That graph is probably leading you to wonder what is &lt;code&gt;TieredCompilation&lt;/code&gt; in java. As you may know the JVM translates your bytecode (class files) into machine code at runtime. This step can take a lot of resources if the compiler wants to make it optimal, it might add counters so it can figure out where the &lt;em&gt;hot spots&lt;/em&gt; are and then do further optimizations. This works great and leads to awesome performance on the JVM when your server is running for a long time. In a way the JVM self tunes itself over time, at runtime.&lt;/p&gt;

&lt;p&gt;When you are running on a &lt;em&gt;serverless&lt;/em&gt; environment like AWS Lambda your runtime will only survive for a short period of time (as little as a few minutes, but no more than a few hours) before being destroyed. The assumption that the JVM default configuration makes is servers will run for a long time, and it should optimize the parts of the code that run the most over time. By setting the &lt;code&gt;TieredStopAtLevel&lt;/code&gt; flag to 1 we are telling the JVM not to insert profiling code that is used for runtime measurements and optimizations. In essence we are telling the JVM, don't get try to be too smart, just execute the code, and in the process we are saving CPU cycles and yielding faster execution.&lt;/p&gt;

&lt;p&gt;I learned about this technique &lt;a href="https://aws.amazon.com/blogs/compute/optimizing-aws-lambda-function-performance-for-java/"&gt;from AWS&lt;/a&gt;, so it makes me wonder why don't they just enable it by default on all Java Lambda Functions? I think all Java Lambda functions could see a lower cold start time with these flags set, but possibly not a lower overall average execution time like I saw. It really depends on if the code can be optimized by the jvm, and how many executions run before the lambda container is recycled. It is certainly worth your time to experiment and see if this flag will improve your Java Lambda Cold Start and Average Duration execution times. Such large performance gains are often not so easily found.&lt;/p&gt;

&lt;p&gt;While my experience was specific to AWS Lambda running Java, I'm sure if you are running Azure Cloud Functions on Java, or Google Cloud Functions on Java you could use the same tip to cut your cold start times and hopefully your average duration as well.&lt;/p&gt;

</description>
      <category>java</category>
      <category>lambda</category>
      <category>aws</category>
    </item>
    <item>
      <title>Replacing Twitter Share / Follow Widget Buttons with CSS</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Fri, 03 Sep 2021 15:22:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/replacing-twitter-share-follow-widget-buttons-with-css-5n0</link>
      <guid>https://forem.com/pfreitag/replacing-twitter-share-follow-widget-buttons-with-css-5n0</guid>
      <description>&lt;p&gt;While looking at the &lt;em&gt;PageSpeed Insights&lt;/em&gt; for &lt;a href="https://www.petefreitag.com/"&gt;my blog&lt;/a&gt; I noticed that the Twitter widgets I was using to display a twitter follow button and a tweet / share button were causing some page speed issues. Specifically the TBT (Total Blocking Time), LCB (Largest Contentful Paint) saw an impact. Overall it was taking about 151 KiB and blocking the main thread for 56ms.&lt;/p&gt;

&lt;p&gt;Here's an example of what I was using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;a href="https://twitter.com/pfreitag" class="twitter-follow-button" data-show-count="true" data-size="large"&amp;gt;Follow @pfreitag&amp;lt;/a&amp;gt;
&amp;lt;script async src="https://platform.twitter.com/widgets.js"&amp;gt;&amp;lt;/script&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That loads the following button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/pfreitag"&gt;Follow @pfreitag&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note this doesn't show up on dev.to, but you can see it if you &lt;a href="https://www.petefreitag.com/item/921.cfm"&gt;go to my blog directly&lt;/a&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Taking a look at this script, it replaces the button with an iframe, it's just quite simply overkill for what it does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Replacing the Twitter button with pure CSS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It should be easy enough to replace this button with a pure css implementation. First, we should replace &lt;a href="https://twitter.com/pfreitag"&gt;https://twitter.com/pfreitag&lt;/a&gt; with a twitter intent to follow url, for example: &lt;a href="https://twitter.com/intent/follow?screen_name=pfreitag"&gt;https://twitter.com/intent/follow?screen_name=pfreitag&lt;/a&gt;. We can also get rid of &lt;code&gt;data-show-count="true" data-size="large"&lt;/code&gt; in the link. One thing our new solution won't have is that nice follower count, but I can live without it. It would be possible to add that back in again, perhaps using a hard coded count to keep it efficient.&lt;/p&gt;

&lt;p&gt;Finally here's the css we are using to make the button look similar to the twitter follow button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
.twitter-follow-button, .twitter-follow-button:visited {
    background-color: #1b95e0;
    color: #fff;
    border-radius: 4px;
    height: 28px;
    font-weight: 500;
    font-size: 13px;
    line-height: 26px;
    padding: 8px 8px 8px 30px;
    text-decoration: none;
    background-image: url('/images/twitter.png');
    background-repeat: no-repeat;
    background-size: 16px 13px;
    background-position: 8px 10px;
}
.twitter-follow-button:hover {
    background-color: #0c7abf;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing you'll note is that we are using an image for the twitter logo, but you don't have to do that. If you have an icon pack like font-awesome you may have a twitter logo you can use, or you can even create the twitter logo in pure css. &lt;/p&gt;

&lt;p&gt;If you want to make the button even more efficient to load just omit the button and use something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
.twitter-follow-button, .twitter-follow-button:visited {
    background-color: #1b95e0;
    color: #fff;
    border-radius: 4px;
    height: 28px;
    font-weight: 500;
    font-size: 13px;
    line-height: 26px;
    padding: 8px;
    text-decoration: none;
}
.twitter-follow-button:hover {
    background-color: #0c7abf;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another good reason to remove the twitter JavaScript is that it also makes the &lt;a href="https://content-security-policy.com/examples/twitter/"&gt;Content-Security-Policy for twitter buttons&lt;/a&gt; much easier to implement.&lt;/p&gt;

&lt;p&gt;To see an example of the pure CSS button take a look below the end of this entry (&lt;a href="https://www.petefreitag.com/item/921.cfm"&gt;go to my blog directly&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>web</category>
      <category>css</category>
    </item>
    <item>
      <title>Bash Script to log file modifications with osquery</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Sat, 10 Apr 2021 00:58:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/bash-script-to-log-file-modifications-with-osquery-4i0b</link>
      <guid>https://forem.com/pfreitag/bash-script-to-log-file-modifications-with-osquery-4i0b</guid>
      <description>&lt;p&gt;Here's a bash script that uses &lt;code&gt;osquery&lt;/code&gt; to log which files in a specific folder have been modified over a 15 minute period. My use case here wasn't file integrity monitoring, for that you would want to use file events.&lt;/p&gt;

&lt;p&gt;Here's the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#!/bin/bash

WORKSPACE_DIR=`echo ~/workspace`
LOG_DIR=`echo ~/Documents/Logs/osquery_file_logs/`
AGO_TIMESTAMP=`date -v-15M "+%s"`
LOG_FOLDER_NAME=`date "+%Y-%m"`
LOG_FILE_NAME=`date "+%Y-%m-%d"`
LOG_FILE="$LOG_DIR/$LOG_FOLDER_NAME/$LOG_FILE_NAME.txt"

mkdir -p "$LOG_DIR/$LOG_FOLDER_NAME"

touch $LOG_FILE

/usr/local/bin/osqueryi --csv --header=false "SELECT datetime(mtime,'unixepoch') AS file_last_modified_time, path FROM file WHERE path LIKE '$WORKSPACE_DIR/%%' AND type != 'directory' AND mtime &amp;gt; $AGO_TIMESTAMP ORDER BY mtime ASC;" &amp;gt;&amp;gt; $LOG_FILE

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I tested this bash script on a Mac, but I think it would work just the same on linux. You'll need to install osquery first. If you set this up in a cron job running every 15 minutes, you'll have a nice log of what files where changed when.&lt;/p&gt;

&lt;h3&gt;
  
  
  A better way?
&lt;/h3&gt;

&lt;p&gt;It has occurred to me that using osquery here is probably a bit overkill for this task, I think you could create a more rudimentary version of this script like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
find $WORKSPACE_DIR -type f -newer $LOG_DIR/timestamp &amp;gt;&amp;gt; $LOG_FILE
touch $LOG_DIR/timestamp 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;-newer&lt;/code&gt; flag of the &lt;code&gt;find&lt;/code&gt; command it will return all files newer than our &lt;code&gt;$LOG_DIR/timestamp&lt;/code&gt;, and because we &lt;code&gt;touch&lt;/code&gt; that file after the script runs, the next time it runs it will show all files changed since it was last run.&lt;/p&gt;

&lt;p&gt;That doesn't include the last modified dates in the log file, but it is possible to do with a little more work.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>osquery</category>
      <category>linux</category>
      <category>mac</category>
    </item>
    <item>
      <title>One liner to download a Browser with PowerShell on Windows Server</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Tue, 20 Oct 2020 23:28:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/one-liner-to-download-a-browser-with-powershell-on-windows-server-g93</link>
      <guid>https://forem.com/pfreitag/one-liner-to-download-a-browser-with-powershell-on-windows-server-g93</guid>
      <description>&lt;p&gt;It would be nice if Windows Server 2019 came with Microsoft Edge Browser, but it still comes with &lt;del&gt;good&lt;/del&gt; old IE 11, and on a Windows Server, you have to jump through hoops to let IE download anything due to its default security settings.&lt;/p&gt;

&lt;p&gt;First I tried downloading Microsoft Edge Browser with IE on Windows Server 2019. I got the following prompt: &lt;em&gt;Do you want to allow this website to open an app on your computer?&lt;/em&gt;, then when I click &lt;em&gt;Allow&lt;/em&gt; it says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You'll need a new app to open this &lt;strong&gt;microsoft-edge&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes IE, I know!&lt;/p&gt;

&lt;p&gt;My next attempt was to download Chrome on Windows Server 2019 using IE, it tells me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your current security settings do not allow this file to be downloaded.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now I realize I could just make IE's security settings more lax, but I'd rather not do that on a server.&lt;/p&gt;

&lt;p&gt;Finally before event attempting to download Firefox on Windows Server using IE, I though maybe I can just write a powershell script to download it, and bypass IE all together. It turns out this was quite a simple and successful endeavor. Just open up a new PowerShell session and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Invoke-WebRequest -Uri "https://download.mozilla.org/?product=firefox-msi-latest-ssl&amp;amp;os=win64&amp;amp;lang=en-US" -OutFile firefox.msi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This powershell command will download the latest Firefox web browser and save it as firefox.msi in the current directory. You can then just run firefox.msi and you'll be on your way with a legit browser.&lt;/p&gt;

&lt;p&gt;You could use the same technique to download Chrome or Edge on Windows Server 2019, you would just need a URL to download it first. Then swap the URL in the powershell script to point to the browser you want to use. No need to even open Internet Explorer on Windows Server.&lt;/p&gt;

</description>
      <category>powershell</category>
      <category>windows</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>SameSite cookies with Apache</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Wed, 01 Apr 2020 11:47:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/samesite-cookies-with-apache-6bd</link>
      <guid>https://forem.com/pfreitag/samesite-cookies-with-apache-6bd</guid>
      <description>&lt;p&gt;Almost two years ago I wrote about how you can enable &lt;a href="https://www.petefreitag.com/item/850.cfm"&gt;SameSite cookies with IIS&lt;/a&gt; on cookies that do not have the ability to be written as SameSite. Today I was helping a client on Apache do the same thing, here's how we can add &lt;code&gt;SameSite=lax&lt;/code&gt; to a &lt;code&gt;JSESSIONID&lt;/code&gt; cookie for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Header edit Set-Cookie ^(JSESSIONID.\*)$ $1;SameSite=lax
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But suppose you just wanted to make all cookies set by your web app SameSite, you can just do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Header edit Set-Cookie ^(.\*)$ $1;SameSite=lax
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This works by appending &lt;code&gt;;SameSite=lax&lt;/code&gt; to the end of all &lt;code&gt;Set-Cookie&lt;/code&gt; http response headers.&lt;/p&gt;

</description>
      <category>web</category>
    </item>
    <item>
      <title>Do you ¿ UTF-8? It's easier than you think</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Wed, 04 Mar 2020 21:19:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/do-you-utf-8-it-s-easier-than-you-think-h13</link>
      <guid>https://forem.com/pfreitag/do-you-utf-8-it-s-easier-than-you-think-h13</guid>
      <description>&lt;p&gt;Understanding how UTF-8 works is one of those things that most programmers are a little fuzzy on. I know I often have to look up specific on it when dealing with a problem. One of the most common UTF-8 related issues that I see has to do with MySQL's support for UTF-8. Also known as &lt;em&gt;how do I insert emoji into mysql?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The TLDR answer to that question is that you have to use the &lt;code&gt;utf8mb4&lt;/code&gt; encoding, because MySQL's &lt;code&gt;utf8&lt;/code&gt; encoding won't hold an emoji. But the longer answer is sort of of interesting and not as hard as you might think to understand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So UTF-8 can take 3 or 4 bytes to store?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Encoding a character with UTF-8 may take, 1, 2, 3, or 4 bytes (early versions of the spec went up to 6 bytes, but was later changed to 4).&lt;/p&gt;

&lt;p&gt;What’s cool about UTF8 is that if you are only using basic ASCII characters (eg, character codes 0-127) then it only uses 1 byte. Here’s a handy table that shows how many bytes it takes to encode a given character code in UTF8:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Character Code (decimal)&lt;/th&gt;
&lt;th&gt;Bytes Used&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0-127&lt;/td&gt;
&lt;td&gt;1 byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;128-2047&lt;/td&gt;
&lt;td&gt;2 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2048-65535&lt;/td&gt;
&lt;td&gt;3 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;65536-1114111&lt;/td&gt;
&lt;td&gt;4 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So hopefully that helps you 😍 UFT8. BTW that emoji is &lt;code&gt;1F60D&lt;/code&gt; in hex, or &lt;code&gt;128525&lt;/code&gt; in decimal, which means it takes 4 bytes to store in unicode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So why can't MySQL uft8 store an emoji?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;utf8&lt;/code&gt; encoding in MySQL can only hold up to 3 bytes UTF-8 characters, and UTF-8 actually supports up to 4 bytes. I don’t know why they choose to limit &lt;code&gt;utf-8&lt;/code&gt; to 3 bytes, but I will speculate that they probably added support while uft8 was still not officially standardized, and assumed that 3 bytes will be plenty big enough.&lt;/p&gt;

&lt;p&gt;So to get the real UTF-8 in MySQL you need to use &lt;code&gt;utf8mb4&lt;/code&gt; encoding. Which can store all 4 bytes of a Unicode character, including emoji.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UTF-8 != Unicode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've probably mistakenly used the terms &lt;code&gt;UTF-8&lt;/code&gt; and &lt;code&gt;Unicode&lt;/code&gt; interchangeably in the past, it's a common mistake, so let's clarify the difference.&lt;/p&gt;

&lt;p&gt;Unicode is a character set standard, it specifies what character a given character code maps to. In Unicode parlance they call the character codes &lt;em&gt;code points&lt;/em&gt;. This is probably just to confuse you. There are many ways to encode a unicode string into binary, and this is where the different encodings come in to play: UTF-8, UTF-16, etc.&lt;/p&gt;

&lt;p&gt;UTF-8 is a way of encoding the characters into bytes. Now if they decided to use 4 bytes for every character, it would have wasted a lot of space (since the most commonly used characters (at least in the english) can be represented using only 1 byte. Although UTF-8 is defined by Unicode and was designed for Unicode, you could invent another character mapping standard and use UTF-8 to store it.&lt;/p&gt;

</description>
      <category>misc</category>
    </item>
    <item>
      <title>Searching for files by file name on Mac or Linux</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Tue, 07 Jan 2020 22:42:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/searching-for-files-by-file-name-on-mac-or-linux-1n4c</link>
      <guid>https://forem.com/pfreitag/searching-for-files-by-file-name-on-mac-or-linux-1n4c</guid>
      <description>&lt;p&gt;Have you ever had to find a file by a file name or file extension? Sure you have! Here's how I locate a file when I'm using a Mac or Linux shell.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;find&lt;/code&gt; command&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;find&lt;/code&gt; command is really handy because it will list every file in the current directory and all sub directories. You can also give it a path, so if you want to search just your home directory (and it is not your current working directory) you can just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;find ~
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And that will list every single file in your home directory (The &lt;code&gt;~&lt;/code&gt; is a shortcut for home directory).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;find&lt;/code&gt; command will be installed by default on your Mac, and just about every linux distribution.&lt;/p&gt;

&lt;p&gt;While that is handy, it might list out thousands of files, so our next step is to search the results for the file name we are looking for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;grep&lt;/code&gt; command&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;grep&lt;/code&gt; command can be used to search the output of another command by using the &lt;code&gt;|&lt;/code&gt; pipe operator. For example if I run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;find ~ | grep log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I can search my home directory for any file with &lt;code&gt;log&lt;/code&gt; in the file name (or directory name).&lt;/p&gt;

&lt;p&gt;Since grep supports regular expressions, if I just want to search file files ending in &lt;code&gt;.log&lt;/code&gt; I can do that like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;find | grep '\.log$'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Searching by file name using &lt;code&gt;find&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After my initial thought to use &lt;code&gt;grep&lt;/code&gt;, I realized that the &lt;code&gt;find&lt;/code&gt; command also has a lot of builtin options you can leverage, so we can simplify this by using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;find -name '\*.log'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are a bunch of options you might find handy, run &lt;code&gt;man find&lt;/code&gt; to see them all.&lt;/p&gt;

&lt;p&gt;Some of you might say that you can just use Finder on a Mac to search for files by name, and you'd be correct, that also works, but this is much faster and more flexible.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Running PostgreSQL in Docker for local dev</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Wed, 18 Dec 2019 01:50:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/running-postgresql-in-docker-for-local-dev-2ojk</link>
      <guid>https://forem.com/pfreitag/running-postgresql-in-docker-for-local-dev-2ojk</guid>
      <description>&lt;p&gt;Recently I blogged about how I'm running &lt;a href="https://www.petefreitag.com/item/880.cfm"&gt;SQL Server on Mac with Docker&lt;/a&gt; and &lt;a href="https://www.petefreitag.com/item/886.cfm"&gt;Oracle on a Mac with Docker&lt;/a&gt;, so here's how you can run PostgreSQL locally using Docker... more specifically docker-compose.&lt;/p&gt;

&lt;p&gt;To start, you'll need to download and install docker, you can check that you have it installed by running &lt;code&gt;docker-compose -v&lt;/code&gt; on the command line and it should output a version number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An example docker-compose.yml for postgres&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a file &lt;code&gt;docker-compose.yml&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.7'
services: 
  pg: 
    image: postgres:9.5.20 
    ports: 
      - "5432:5432" 
    volumes: 
      - ./pg:/docker-entrypoint-initdb.d/ 
    environment: 
      - "POSTGRES\_PASSWORD=${DB\_PASS}"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this case I am exposing port 5432 (the default postgres port) locally, so I'll be able to connect to it via localhost on port 5432.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Running an initialization SQL or sh script&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can initialize this database by creating some files in a folder under your &lt;code&gt;docker-compose.yml&lt;/code&gt; file called &lt;code&gt;pg&lt;/code&gt;. The docker initialization scripts will run any &lt;code&gt;.sql&lt;/code&gt; file or any &lt;code&gt;.sh&lt;/code&gt; file it finds in there during startup. So you can create database users or create table schema by placing files in those directories.&lt;/p&gt;

&lt;p&gt;The default username will be &lt;code&gt;postgres&lt;/code&gt; and the password for that user is defined in the &lt;code&gt;environment&lt;/code&gt; variable &lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt; which I am defining to be the value of my computers environment variable named &lt;code&gt;DB_PASS&lt;/code&gt;. You could hard code it instead if you really wanted to.&lt;/p&gt;

&lt;p&gt;Finally the version of PostgreSQL that is used can be tweaked by changing the line &lt;code&gt;image: postgres:9.5.20&lt;/code&gt; to use a different version number.&lt;/p&gt;

&lt;p&gt;Once you have customized it as necessary, then you can run the following command to bring up the database server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;During initialization it will run your scripts in your &lt;code&gt;pg&lt;/code&gt; folder to create the database. If you need to re-run the initialization scripts you'll need to remove the docker container (hint: use &lt;code&gt;docker container ls&lt;/code&gt; and &lt;code&gt;docker container rm&lt;/code&gt; commands)&lt;/p&gt;

</description>
      <category>database</category>
      <category>postgres</category>
      <category>docker</category>
    </item>
    <item>
      <title>Everything I know about Markdown Bullet Lists</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Fri, 22 Nov 2019 13:47:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/everything-i-know-about-markdown-bullet-lists-5442</link>
      <guid>https://forem.com/pfreitag/everything-i-know-about-markdown-bullet-lists-5442</guid>
      <description>&lt;p&gt;My goal here is to create a quick guide to creating &lt;em&gt;bullet lists&lt;/em&gt;, also known as &lt;em&gt;ul lists&lt;/em&gt; or &lt;em&gt;unordered lists&lt;/em&gt; with Markdown.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLDR use &lt;code&gt;*&lt;/code&gt; or &lt;code&gt;-&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As long as you start the line with a &lt;code&gt;*&lt;/code&gt; or a &lt;code&gt;-&lt;/code&gt; markdown will interpret that as a list item. So the following markdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* One 
* Two
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Will produce a bullet list like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One&lt;/li&gt;
&lt;li&gt;Two&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As already mentioned we can use a &lt;code&gt;-&lt;/code&gt; to start an unordered list in Markdown as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- One
- Two
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Will produce the same list as above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about nested bullet lists?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To create a nested UL list just indent the line with a tab or 3-4 spaces. For example the following markdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* One 
* Two 
    * Three 
        * Four
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Will render as the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One&lt;/li&gt;
&lt;li&gt;Two 

&lt;ul&gt;
&lt;li&gt;Three 

&lt;ul&gt;
&lt;li&gt;Four&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Can you Mix &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;-&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You certainly can, the following will render the same list nested bullet list as above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- One 
- Two 
    * Three 
        * Four
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What about Numbered Lists?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can do numbered lists by prefixing each line with incrementing numbers followed by a period. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. One 
2. Two
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Results in an ordered list (OL):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One&lt;/li&gt;
&lt;li&gt;Two&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's pretty much all I know about markdown lists, did I miss anything?&lt;/p&gt;

</description>
      <category>web</category>
      <category>markdown</category>
      <category>tips</category>
    </item>
    <item>
      <title>How to run Oracle DB on a Mac with Docker</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Tue, 05 Nov 2019 02:08:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/how-to-run-oracle-db-on-a-mac-with-docker-3846</link>
      <guid>https://forem.com/pfreitag/how-to-run-oracle-db-on-a-mac-with-docker-3846</guid>
      <description>&lt;p&gt;Oracle puts out a Windows and Linux binary for their Oracle Database servers, but what if you want to run it on a Mac? The solution for a while was to use a VM and boot up the linux version. Nowadays using Docker is a little bit easier.&lt;/p&gt;

&lt;p&gt;I will say that running Oracle DB on docker is not quite as &lt;a href="https://www.petefreitag.com/item/880.cfm"&gt;easy as running SQL Server on Docker&lt;/a&gt;, but it is also not too difficult.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Download the Oracle Database Linux Binary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your first step is to download the &lt;em&gt;Download the Oracle Express Edition version 18c (xe) Linux rpm&lt;/em&gt; from &lt;a href="https://www.oracle.com/database/technologies/xe-downloads.html"&gt;oracle.com&lt;/a&gt;. Oracle's docker files do support other editions, but the Express Edition is sufficient for getting started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clone the Oracle Dockerfile Repo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oracle has a GitHub repo with all its Dockerfiles, you can clone it (download it) by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/oracle/docker-images.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Copy Binary to Dockerfiles dir&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Within the git repository you just cloned, go to the OracleDatabase dockerfiles folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ./OracleDatabase/SingleInstance/dockerfiles
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Copy the binary you downloaded in step 1 to the 18.4.0 folder within the dockerfiles folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp ~/Downloads/oracle-database-xe-18c-1.0-1.x86\_64.rpm ./18.4.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Build a Docker Image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./buildDockerImage.sh -x -v 18.4.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-x&lt;/code&gt; tells the script that you are installing the express edition, and the &lt;code&gt;-v 18.4.0&lt;/code&gt; tells it which version you are installing.&lt;/p&gt;

&lt;p&gt;This step will take a few minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Look for local docker image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should now have a docker image named &lt;code&gt;oracle/database:18.4.0-xe&lt;/code&gt; which you can start using docker. Run &lt;code&gt;docker images&lt;/code&gt; from Terminal to look for it and make sure it is there. The total size of the image will be around 8-9GB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start an Oracle Database Using docker-compose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally we'll create a docker-compose.yml file so we can easily startup the db whenever we need it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3" 
services: 
  oracle: 
    image: oracle/database:18.4.0-xe 
    ports: 
      - "11521:1521" 
    environment: 
      - ORACLE\_PWD=testing12345
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now we can start up our container by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you omit the &lt;code&gt;ORACLE_PWD&lt;/code&gt; environment variable it will just generate a presumably random password and output it during startup. The startup takes a few minutes to initialize.&lt;/p&gt;

&lt;p&gt;After it starts up you will have an oracle database that is accessible on your local machine on port &lt;code&gt;11521&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>database</category>
      <category>oracle</category>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Timing Attacks and the Timing-Allow-Origin Header</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Thu, 24 Oct 2019 01:57:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/timing-attacks-and-the-timing-allow-origin-header-1b13</link>
      <guid>https://forem.com/pfreitag/timing-attacks-and-the-timing-allow-origin-header-1b13</guid>
      <description>&lt;p&gt;I've always found &lt;em&gt;Timing Attacks&lt;/em&gt; to be an interesting type of web application vulnerability. You need to understand timing attacks before you can understand how to use the &lt;code&gt;Timing-Allow-Origin&lt;/code&gt; http response header.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a Timing Attack?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Timing attacks can happen when attackers use timing to ascertain information, or perhaps better put, when performance is a bug!&lt;/p&gt;

&lt;p&gt;Here is a common timing attack I see often in real code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if ( isValidUser(username) ) { 
  if ( isValidPassword( username, password ) ) { 
    return { authenticated: true };
  }
} 
return { authenticated: false };
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the above case an attacker use the response time to determine what usernames are valid. If an invalid username is passed it fails fast. This works well because &lt;code&gt;isValidPassword&lt;/code&gt; is probably doing an expensive operation to compute the entered password's hash, and it will take notable amount of time. By comparing the response time of a valid username and an invalid username the attacker can form a list of valid user names.&lt;/p&gt;

&lt;p&gt;Other real world timing attacks have taken place that have allowed attackers to figure out the identity (see &lt;a href="https://blog.twitter.com/engineering/en_us/topics/insights/2018/twitter_silhouette.html"&gt;Twitter Silhouette Attack&lt;/a&gt;). On Facebook, it was possible to create a page that had age restrictions setup such that only a 32 year old could view it, by creating a page for each age, and then requesting each one it was possible for another site to tell how old you are.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.opera.com/blog/timing-attacks/"&gt;Mathias Bynens&lt;/a&gt; has a great talk on this subject that will help you further understand this topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Timing-Allow-Origin Header&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a new header, that according to &lt;a href="https://caniuse.com/#feat=mdn-http_headers_timing-allow-origin"&gt;Can I Use&lt;/a&gt; has only been around for about a month (September 2019).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Timing-Allow-Origin&lt;/code&gt; header allows you to specify what origins can view the timing data, it needs to be an exact match, so if you want to share the timing data with &lt;code&gt;https://example.com&lt;/code&gt; you can specify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Timing-Allow-Origin: https://example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The spec also allows you to specify a wildcard here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Timing-Allow-Origin: \*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Hopefully you can understand that specifying the &lt;code&gt;*&lt;/code&gt; wildcard for the &lt;code&gt;Timing-Allow-Origin&lt;/code&gt; is not a good idea, and can open yourself up to cross site timing attacks via the Web &lt;a href="https://w3c.github.io/resource-timing/"&gt;Resource Timing API&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
    </item>
    <item>
      <title>Counting IP Addresses in a Log File</title>
      <dc:creator>Pete Freitag</dc:creator>
      <pubDate>Fri, 11 Oct 2019 23:00:00 +0000</pubDate>
      <link>https://forem.com/pfreitag/counting-ip-addresses-in-a-log-file-38pn</link>
      <guid>https://forem.com/pfreitag/counting-ip-addresses-in-a-log-file-38pn</guid>
      <description>&lt;p&gt;I've been using &lt;code&gt;grep&lt;/code&gt; to search through files on linux / mac for years, but one flag I didn't use much until recently is the &lt;code&gt;-o&lt;/code&gt; flag. This tells grep to only output the matched pattern (instead of lines that mach the pattern).&lt;/p&gt;

&lt;p&gt;This feature turns out to be pretty handy, lets say you want to find all the IP addresses in a file. You just need to come up with a &lt;a href="https://www.petefreitag.com/cheatsheets/regex/"&gt;regular expression&lt;/a&gt; to match an IP, I'll use this: &lt;code&gt;"[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+"&lt;/code&gt; it's not perfect, but it will work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" httpd.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What if I want to see just unique IPs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can use the &lt;code&gt;uniq&lt;/code&gt; command to remove duplicate ip addresses, but &lt;code&gt;uniq&lt;/code&gt; needs a sorted input. We can do that with the &lt;code&gt;sort&lt;/code&gt; command, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" httpd.log | sort | uniq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Show me the number of times each IP shows up in the log&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we can use the &lt;code&gt;-c&lt;/code&gt; flag for &lt;code&gt;uniq&lt;/code&gt; to display counts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" httpd.log | sort | uniq -c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will output something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    7 10.0.0.30 
    1 10.0.0.80 
    3 10.0.0.70
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The counts are not in order, so we can pass our results through sort again, this time with the &lt;code&gt;-n&lt;/code&gt; flag to use a numeric sort.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" httpd.log | sort | uniq -c | sort -n
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above will put them in order from least to greatest, you can pipe the result to &lt;code&gt;tail&lt;/code&gt; if you only want to see the top N IP addresses!&lt;/p&gt;

&lt;p&gt;Pretty handy right?&lt;/p&gt;

</description>
      <category>linux</category>
    </item>
  </channel>
</rss>
