1/40

Perl for Sysadmin

Jack Brooks, Monster Slayer
pipes, daemons, just another typical sysadmin day, really

Who am I?

What am I going to do to you today?

Quick show-and-tell of how Perl can make your day-to-day life easier.

Who is the Audience?

How to run a Perl script?

Way #1: as a program

#!/usr/bin/env perl

use strict;
use warnings;

print "Hello world\n";

and then

$ chmod +X my_script.pl
$ ./my_script.pl
Hello world

How to run a Perl script? (cont)

Way #2: feed code via STDIN

$ perl
print "Hello world\n";
^D

How to run a Perl script? (cont)

Way #3: command-line

Welcome to the wonderful, terrible world of one-liners.

$ perl -e'print "Hello world!\n"'

Perl command line options

Let the fun begin...

-h -- haaaa-elp!

For when memory fails us

$ perl -h
Usage: perl [switches] [--] [programfile] [arguments]
-0[octal]         specify record separator (\0, if no argument)
-a                autosplit mode with -n or -p (splits $_ into @F)
-C[number/list]   enables the listed Unicode features
-c                check syntax only (runs BEGIN and CHECK blocks)
[ ... ]

To get the full manpage:

$ perldoc perlrun

-v -- version

$ perl -v

This is perl 5, version 12, subversion 0 (v5.12.0) built for i686-linux

Copyright 1987-2010, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

-V -- configuration values

$ perl -V
Summary of my perl5 (revision 5 version 12 subversion 0) configuration:

Platform:
    osname=linux, osvers=2.6.31-20-generic, archname=i686-linux
    uname='linux enkidu 2.6.31-20-generic #58-ubuntu smp fri mar 12 05:23:09 utc 2010 i686 gnulinux '
[ ... ] 

More targeted:

$ perl -V:osname  
osname='linux';

-e, -E -- execute line of code

$ perl -e'print "Hello world!\n"'

Or, for perl >= 5.10

$ perl -E'say "Hello world!"'

Can have more than one:

$ perl -e '$x = "foo";' \
       -e '$x++;'       \
       -e 'print $x;'

-n -- iterate through stdin lines

Print subject lines in a mbox

$ perl -nE'print if s/^Subject:\s+//;' mbox

Poor man's web analyzer:

$ perl -nE '$a{$1}++ if /(?:GET|POST) (\S+)/;' \
       -E  'END { say "$_ $a{$_}" for sort keys %a}' \
       access_log

/email_backlog/ 13
/email_backlog/backlog.csv 13
/email_backlog/dygraph-combined.js 12
/favicon.ico 2

-p -- iterate, and print

Rot-13 for the masses!

$ echo "shazam" | perl -pE'y/a-z/n-za-m/'

funmnz

$ echo "funmnz" | perl -pE'y/a-z/n-za-m/'

shazam

-l -- auto-CR end of lines (mostly)

$ echo "one two three" | perl -lne'print for split'

one
two
three

-0 -- record separator

Specify character by octal value

$ echo "1,2,3,4,5" | perl -054 -nE'$x+=$_; END { say $x; }'

No argument? Slurp everything in one go

$ curl http://babyl.ca/techblog | \
    perl -0 -pe'($_)=m#<title>(.*?)</title>#is'

-a -- split records

$ df | perl -a -nE'say "$F[0] is $F[4] full"'

/dev/sda1 is 37% full
/dev/sdb9 is 96% full

-F -- specify on what to split

$ cat foo
1,2,3
4,5,6

$ perl -0 -aF/,\|\\n/ -pE'$_=join"!",@F' foo

1!2!3!4!5!6

-M -- load module

$ echo "1,2,3,4,5" | \
    perl -MList::Util=sum  -nE'say sum split ","'

Tricks

Quickly find the installed version of a module:

$ perl -MList::Util\ 999 -e1

List::Util version 999 required--this is only version 1.22.
BEGIN failed--compilation aborted.

Explain to me, please

NoCOUG SQL Challenge – thinking outside the padded box

#!/usr/bin/perl -p
s/ (\w+)/lc$&/e;$k{$1}=$_}{/ /&&s/[A-Z]+/$k{$&}/,$x[y---c]=$_
for(%k)x%k;$_=pop@x;

$ perl -MO=Deparse horror.pl

Documentation and help

$ perldoc perl

$ perldoc Any::Perl::Module::Installed
$ man Any::Perl::Module::Installed

or online at [[http://perldoc.perl.org]]

RTFM in style

perldoc-complete

[[https://github.com/ap/perldoc-complete]]

xpod

#!/bin/bash
POD_PORT=8787
perl -MPod::POM::Web -e"Pod::POM::Web->server($POD_PORT)" \
    2> /dev/null &
PAGE=`perl -e's#::#/#g for @ARGV; print @ARGV' $1`
HOSTNAME=`hostname`
kfmclient openURL "http://${HOSTNAME}:$POD_PORT/$PAGE";

corelist -- Which modules are core?

$ corelist Module::CoreList

Module::CoreList was first released with perl 5.008009

Documentation Tricks

Search the FAQ

$ perldoc -q strip

Locate a module

$ perldoc -l List::Util

/home/yanick/[...]/i686-linux/List/Util.pm

module_info, brought to you by Module::Info

$ module_info List::Util

Name:        List::Util
Version:     1.22
Directory:   /home/yanick/[...]/i686-linux
File:        /home/yanick/[...]/i686-linux/List/Util.pm
Core module: yes

Tools

ack -- grep, only better

App::ack

$ ack --thpppt
_   /|
\'o.O'
=(___)=
   U    ack --thpppt!


$ ack --vim  -i Perl ~/.vim

Skip the usual crud:

autom4te.cache, blib, _build, .bzr, .cdv, cover_db, CVS, 
_darcs, ~.dep, ~.dot, .git, .hg, ~.nib, .pc, ~.plst, RCS, 
SCCS, _sgbak and .svn

http sharing

http_this

$ cd /path/to/what/you/want/to/share
$ http_this

cpanminus

$ curl -L http://cpanmin.us | perl - --sudo App::cpanminus

perlbrew

$ curl -L http://xrl.us/perlbrewinstall | bash
$ perlbrew init
$ perlbrew install perl-5.12.2

Useful modules

File::Find

a classic...

use 5.12.0;
use File::Find;
find(\&wanted, '.' );

sub wanted {
    # $_, $File::Find::dir, $File::Find::name
    $File::Find::prune = 1 if -d $_ and $_ eq '.git';
    my $size = -s $_;
    say "$_ - $size" if $size > 100;
}

Net::CIDR

#!/usr/bin/env perl 
use 5.12.0;
use Net::CIDR qw/ :all /;

my @cidr; 
@cidr = cidradd( range2cidr( $_ ), @cidr ) while <DATA>;
print join " : ", @cidr;

__DATA__
192.68.0.0-192.68.0.255
192.68.1.0-192.68.1.32

App::FatPacker

$ fatpack trace myscript.pl
$ fatpack packlists-for `cat fatpacker.trace` >packlists
$ fatpack tree `cat packlists`
$ (fatpack file; cat myscript.pl) >myscript.packed.pl

Perl 5.10

Summoned by

use 5.10.0;  # or 5.12.0

or

$ perl -E 'say "Hi!"'

Perl >5.10 goodies

say

say "Hi there!";

equivalent to

print "Hi there!\n";

Perl >5.10 goodies (cont)

yadah operator

if ( $weird_stuf ) {
    # can't be bothered, right now
    ...
}

Perl >5.10 goodies (cont)

given

given ( $alarm_level ) {
    when ( 'yellow' ) {
        say "I'm on it";
    }
    when ( 'red' ) {
        say vacation_message();
    }
    default {
        sleep 60;
    }
}

Perl >5.10 goodies (cont)

smart-match operator

'foo' ~~ @bag;

$x ~~ $y;

Perl >5.10 goodies (cont)

regular expression named parameters

/(?<stuff>al.*?\b)/;
print $+{stuff};