<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Perl on Evan Hoffman</title><link>https://evan.wtf/tags/perl/</link><description>Recent content in Perl on Evan Hoffman</description><generator>Hugo</generator><language>en-US</language><copyright>Evan Hoffman</copyright><lastBuildDate>Fri, 02 Mar 2012 10:01:11 +0000</lastBuildDate><atom:link href="https://evan.wtf/tags/perl/index.xml" rel="self" type="application/rss+xml"/><item><title>Reorganizing photos in 1 line with exiftool</title><link>https://evan.wtf/2012/03/02/reorganizing-photos-in-1-line-with-exiftool/</link><pubDate>Fri, 02 Mar 2012 10:01:11 +0000</pubDate><guid>https://evan.wtf/2012/03/02/reorganizing-photos-in-1-line-with-exiftool/</guid><description>&lt;p&gt;A few years ago I wrote &lt;a href="https://evan.wtf/2007/03/28/java-utility-to-reorganize-photos-by-date-taken-via-exif-metadata/"&gt;a utility&lt;/a&gt; in Java to find all JPG files in a directory and move them into a date-based directory structure like /YYYY/MM/DD/ based on the date the photo was taken, extracted from the exif metadata in the file. Well, apparently that was a huge waste of time, as I just discovered that &lt;code&gt;exiftool&lt;/code&gt;, an awesome perl utility I&amp;rsquo;ve used for years to edit/extract the metadata on the command line, can also do this natively. So my entire program can be replaced with this simple command:&lt;/p&gt;</description></item><item><title>Graphing SSH dictionary attacks with HighCharts</title><link>https://evan.wtf/2011/11/18/graphing-ssh-dictionary-attacks-with-highcharts/</link><pubDate>Fri, 18 Nov 2011 14:06:03 +0000</pubDate><guid>https://evan.wtf/2011/11/18/graphing-ssh-dictionary-attacks-with-highcharts/</guid><description>&lt;p&gt;After my 10-year-old basement Linux server died this week from a power outage, I took the sad step of giving up on it. It&amp;rsquo;s died before and I&amp;rsquo;ve patched it back together with a new power supply here or an addon PCI SATA card there, but I finally decided to throw in the towel since I had a newer old computer that had been idle for several years. The one that died was an Athlon K7 750 MHz with 512 MB ram. The new one is an Athlon 2 GHz (3200+) with 1 gig. For my uses, specs don&amp;rsquo;t really matter that much, but it&amp;rsquo;s nice to have more power for free.&lt;/p&gt;</description></item><item><title>Logging RT username in Apache access_log</title><link>https://evan.wtf/2011/08/08/logging-rt-username-in-apache-access_log/</link><pubDate>Mon, 08 Aug 2011 17:34:18 +0000</pubDate><guid>https://evan.wtf/2011/08/08/logging-rt-username-in-apache-access_log/</guid><description>&lt;p&gt;&lt;a href="http://bestpractical.com/rt/"&gt;RT&lt;/a&gt; has its own internal accounting &amp;amp; tracking system for logging activity, but I was interested in even more granular stuff, like seeing who looked at which tickets. I figured it wouldn&amp;rsquo;t be that hard to log this in Apache. Well, I was kind of right, in that it wasn&amp;rsquo;t &amp;ldquo;hard,&amp;rdquo; but it took me a long time to find the right place to do it. I did finally get it though.&lt;/p&gt;</description></item><item><title>Amazon SES: "illegal headers" with ses-send-email.pl (followup)</title><link>https://evan.wtf/2011/08/02/amazon-ses-illegal-headers-with-ses-send-email-pl-followup/</link><pubDate>Tue, 02 Aug 2011 14:39:45 +0000</pubDate><guid>https://evan.wtf/2011/08/02/amazon-ses-illegal-headers-with-ses-send-email-pl-followup/</guid><description>&lt;p&gt;A few people have emailed me asking me to integrate &lt;a href="https://evan.wtf/2011/05/16/amazon-ses-illegal-header-errors/"&gt;the perl code snippet into I wrote to strip illegal headers&lt;/a&gt; when sending email via Amazon SES into something actually usable. I&amp;rsquo;ve done so! I haven&amp;rsquo;t really tested this beyond sending some test emails, but here it is. Use this at your own risk, I make no warranty, blah blah blah.&#10;This fix requires editing &lt;code&gt;ses-send-email.pl&lt;/code&gt;, so I&amp;rsquo;d advise making a backup copy, though I imagine you can always get a fresh version from Amazon if necessary.&lt;/p&gt;</description></item><item><title>Amazon SES - "Illegal Header" errors</title><link>https://evan.wtf/2011/05/16/amazon-ses-illegal-header-errors-2/</link><pubDate>Mon, 16 May 2011 12:37:49 +0000</pubDate><guid>https://evan.wtf/2011/05/16/amazon-ses-illegal-header-errors-2/</guid><description>My thoughts on the &amp;ldquo;illegal header&amp;rdquo; error some people are encountering when relaying mail through postfix/SES. Plus some perl code that should help fix it.</description></item><item><title>Integrating Amazon Simple Email Service with postfix for SMTP smarthost relaying.</title><link>https://evan.wtf/2011/04/28/integrating-amazon-simple-email-service-with-postfix-for-smarthost-relaying/</link><pubDate>Thu, 28 Apr 2011 12:23:47 +0000</pubDate><guid>https://evan.wtf/2011/04/28/integrating-amazon-simple-email-service-with-postfix-for-smarthost-relaying/</guid><description>How I configured an EC2 instance to relay mail through Amazon&amp;rsquo;s SES, and some of the bumps I encountered along the way.</description></item><item><title>More fun parsing BIND query logs</title><link>https://evan.wtf/2010/12/13/more-fun-parsing-bind-query-logs/</link><pubDate>Mon, 13 Dec 2010 18:21:59 +0000</pubDate><guid>https://evan.wtf/2010/12/13/more-fun-parsing-bind-query-logs/</guid><description>&lt;p&gt;&amp;ldquo;But wouldn&amp;rsquo;t it be cool if it also&amp;hellip;&amp;rdquo; That phrase usually triggers a lot of wasted cycles in my brain, though it sometimes comes up with something neat. I added a super lame graph to the DNS QPS parser. Makes it really easy to see peaks &amp;amp; troughs in usage:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;2010-12-12 00:00 to 00:59 =&amp;gt; 3237, rate 0.899 queries/sec&#9;***********&#10;2010-12-12 01:00 to 01:59 =&amp;gt; 2709, rate 0.752 queries/sec&#9;**********&#10;2010-12-12 02:00 to 02:59 =&amp;gt; 2473, rate 0.687 queries/sec&#9;*********&#10;2010-12-12 03:00 to 03:59 =&amp;gt; 2171, rate 0.603 queries/sec&#9;********&#10;2010-12-12 04:00 to 04:59 =&amp;gt; 2048, rate 0.569 queries/sec&#9;*******&#10;2010-12-12 05:00 to 05:59 =&amp;gt; 1918, rate 0.533 queries/sec&#9;*******&#10;2010-12-12 06:00 to 06:59 =&amp;gt; 2120, rate 0.589 queries/sec&#9;********&#10;2010-12-12 07:00 to 07:59 =&amp;gt; 2477, rate 0.688 queries/sec&#9;*********&#10;2010-12-12 08:00 to 08:59 =&amp;gt; 2994, rate 0.832 queries/sec&#9;**********&#10;2010-12-12 09:00 to 09:59 =&amp;gt; 3704, rate 1.029 queries/sec&#9;*************&#10;2010-12-12 10:00 to 10:59 =&amp;gt; 4297, rate 1.194 queries/sec&#9;***************&#10;2010-12-12 11:00 to 11:59 =&amp;gt; 4744, rate 1.318 queries/sec&#9;****************&#10;2010-12-12 12:00 to 12:59 =&amp;gt; 5106, rate 1.418 queries/sec&#9;******************&#10;2010-12-12 13:00 to 13:59 =&amp;gt; 5311, rate 1.475 queries/sec&#9;******************&#10;2010-12-12 14:00 to 14:59 =&amp;gt; 5083, rate 1.412 queries/sec&#9;*****************&#10;2010-12-12 15:00 to 15:59 =&amp;gt; 4855, rate 1.349 queries/sec&#9;*****************&#10;2010-12-12 16:00 to 16:59 =&amp;gt; 5179, rate 1.439 queries/sec&#9;******************&#10;2010-12-12 17:00 to 17:59 =&amp;gt; 4959, rate 1.377 queries/sec&#9;*****************&#10;2010-12-12 18:00 to 18:59 =&amp;gt; 4693, rate 1.304 queries/sec&#9;****************&#10;2010-12-12 19:00 to 19:59 =&amp;gt; 4792, rate 1.331 queries/sec&#9;****************&#10;2010-12-12 20:00 to 20:59 =&amp;gt; 4799, rate 1.333 queries/sec&#9;****************&#10;2010-12-12 21:00 to 21:59 =&amp;gt; 5068, rate 1.408 queries/sec&#9;*****************&#10;2010-12-12 22:00 to 22:59 =&amp;gt; 4672, rate 1.298 queries/sec&#9;****************&#10;2010-12-12 23:00 to 23:59 =&amp;gt; 4514, rate 1.254 queries/sec&#9;****************&#10;2010-12-13 00:00 to 00:59 =&amp;gt; 3917, rate 1.088 queries/sec&#9;**************&#10;2010-12-13 01:00 to 01:59 =&amp;gt; 3458, rate 0.961 queries/sec&#9;************&#10;2010-12-13 02:00 to 02:59 =&amp;gt; 2874, rate 0.798 queries/sec&#9;**********&#10;2010-12-13 03:00 to 03:59 =&amp;gt; 2715, rate 0.754 queries/sec&#9;**********&#10;2010-12-13 04:00 to 04:59 =&amp;gt; 2690, rate 0.747 queries/sec&#9;*********&#10;2010-12-13 05:00 to 05:59 =&amp;gt; 2719, rate 0.755 queries/sec&#9;**********&#10;2010-12-13 06:00 to 06:59 =&amp;gt; 2831, rate 0.786 queries/sec&#9;**********&#10;2010-12-13 07:00 to 07:59 =&amp;gt; 3416, rate 0.949 queries/sec&#9;************&#10;2010-12-13 08:00 to 08:59 =&amp;gt; 4962, rate 1.378 queries/sec&#9;*****************&#10;2010-12-13 09:00 to 09:59 =&amp;gt; 6943, rate 1.929 queries/sec&#9;************************&#10;2010-12-13 10:00 to 10:59 =&amp;gt; 8296, rate 2.304 queries/sec&#9;****************************&#10;2010-12-13 11:00 to 11:59 =&amp;gt; 8938, rate 2.483 queries/sec&#9;******************************&#10;2010-12-13 12:00 to 12:59 =&amp;gt; 8926, rate 2.479 queries/sec&#9;******************************&#10;2010-12-13 13:00 to 13:59 =&amp;gt; 8950, rate 2.486 queries/sec&#9;******************************&#10;2010-12-13 14:00 to 14:59 =&amp;gt; 2173, rate 0.604 queries/sec&#9;********&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can see pretty quickly that 4-5 AM (Eastern) is the period of lowest activity, as you&amp;rsquo;d probably expect for a US-based US-centric site. Modified perl script below.&lt;/p&gt;</description></item><item><title>Perl script to calculate DNS queries per second in BIND (named)</title><link>https://evan.wtf/2010/12/07/perl-script-to-calculate-dns-queries-per-second-in-bind-named/</link><pubDate>Tue, 07 Dec 2010 18:53:43 +0000</pubDate><guid>https://evan.wtf/2010/12/07/perl-script-to-calculate-dns-queries-per-second-in-bind-named/</guid><description>&lt;p&gt;I&amp;rsquo;m pricing out DNS providers and was asked what our current queries-per-second currently are. Sadly I had no idea. After lots of Googling I decided there was really no good way to get this information so I decided to parse the logfile myself.&#10;First, I turned on logging with timestamp in named.conf:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;logging&#10;{&#10;...&#10; # Query logging 2010-12-07&#10; channel query-log {&#10; file &amp;#34;data/queries.log&amp;#34; versions 3 size 10m;&#10; print-time yes;&#10; };&#10; category queries { query-log; };&#10;};&#10;options&#10;{&#10;...&#10; # Query logging 2010-12-07&#10; querylog yes;&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;};&lt;/p&gt;</description></item><item><title>Blocking comment spammers by IP</title><link>https://evan.wtf/2010/08/13/blocking-comment-spammers-by-ip/</link><pubDate>Fri, 13 Aug 2010 11:59:27 +0000</pubDate><guid>https://evan.wtf/2010/08/13/blocking-comment-spammers-by-ip/</guid><description>&lt;p&gt;I use &lt;a href="http://akismet.com/"&gt;Akismet&lt;/a&gt; to block comment spam, but it still annoys me that it even exists. Last night I put a simple IP ban into my httpd config. But who to block?&lt;/p&gt;&#10;&lt;p&gt;I used a grep &amp;amp; Perl to get a rough guess of which IPs were submitting the most comments (working on the assumption that one IP address submits many spam comments) It took me about 20 minutes to write this mess but it does what I wanted to do:&#10;&lt;code&gt;[root@lunix ~]# zgrep POST /var/log/httpd/evanhoffman-access_log-201008??.gz | grep comment | perl -ne 'chomp; $_ =~ m/(?:\d{1,3}\.){3}\d{1,3}/; print &amp;quot;$&amp;amp;\n&amp;quot;;' | perl -e '%a = (); while (&amp;lt;&amp;gt;) { chomp; $a{$_} += 1; } while (my ($key, $value) = each (%a)) { if ($value &amp;gt; 1) { print &amp;quot;$value\t=&amp;gt;\t$key\n&amp;quot;;}}' 2 =&amp;gt; 218.6.9.140 180 =&amp;gt; 91.201.66.34 2 =&amp;gt; 213.5.67.41 2 =&amp;gt; 188.187.102.74 [root@lunix ~]#&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Running MRTG cfgmaker across your entire subnet?</title><link>https://evan.wtf/2010/01/27/running-mrtg-cfgmaker-across-your-entire-subnet/</link><pubDate>Wed, 27 Jan 2010 13:00:30 +0000</pubDate><guid>https://evan.wtf/2010/01/27/running-mrtg-cfgmaker-across-your-entire-subnet/</guid><description>&lt;p&gt;I realized recently that I had a bunch of newly-provisioned VMs that weren&amp;rsquo;t being monitored by MRTG (one of the tools we use to monitor network usage and other fun stats). Rather than manually run cfgmaker against all the new machines, I decided to script my way out of this.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Step 1: Build a list of hosts to monitor&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;For this I used an nmap ping test to generate a list of &amp;ldquo;up&amp;rdquo; hosts:&lt;/p&gt;</description></item><item><title>Victory! Change Active Directory Password via LDAP through browser</title><link>https://evan.wtf/2010/01/13/victory-change-active-directory-password-via-ldap-through-browser/</link><pubDate>Wed, 13 Jan 2010 13:51:43 +0000</pubDate><guid>https://evan.wtf/2010/01/13/victory-change-active-directory-password-via-ldap-through-browser/</guid><description>&lt;p&gt;I had to give up on PHP and go to Perl, but it turned out not to be so bad. Users can now change their Active Directory passwords via a self-service web page that doesn&amp;rsquo;t require admin credentials. The Perl code is below. Authentication to the script is done via .htaccess LDAP authentication, so the REMOTE_USER env variable is assumed to contain the user&amp;rsquo;s username (sAMAccountName) by the time this script is called. There is a simple check for $ENV{HTTPS} to ensure the script is called via SSL, and AD requires password changes to be done via ldaps, so the whole thing &lt;em&gt;should&lt;/em&gt; be encrypted end to end.&lt;/p&gt;</description></item><item><title>Flac to MP3 (flac2mp3.pl)</title><link>https://evan.wtf/2005/11/07/flac-to-mp3-flac2mp3-pl/</link><pubDate>Mon, 07 Nov 2005 00:00:44 +0000</pubDate><guid>https://evan.wtf/2005/11/07/flac-to-mp3-flac2mp3-pl/</guid><description>&lt;p&gt;I wrote a crappy perl script to read all the .flac files in a directory and convert them to MP3 using LAME, extracting the meta-data and inserting it as ID3v2 tags. I figured this might be somewhat useful to others, so here you go: &amp;lt;flac2mp3.pl&amp;gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://gist.github.com/1642637.js?file=flac2mp3.pl"&gt;https://gist.github.com/1642637.js?file=flac2mp3.pl&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>