Perl one-liner to see who is hogging all the open filehandles

Posted by Chris on March 22nd, 2011 filed in programming, sysadmin

Helpful one-liner to help fix a problem we ran into the other day.

perl -e 'map{$c{(split(/\s+/))[2]}++} `lsof`;print "$_ $c{$_}\n" for (keys %c);'

The thinking is:

Use lsof to get all the open filehandles which conveniently also shows who has it open.


Loop through them, using the ` as a cheat that it inputs an array

map {   } `lsof`;

Splitting on whitespace.  The input to each iteration of the map{ } defaults to $_, and if you don't put anything to split in a perl split, it uses $_.  Neat.


Since we just care about the count, only use the 3rd column by forcing the output of the split into an array and using a slice.


Now, we just want the count for those users so we increment a hash with the user name as they key.

$c{ }++

Of course, the split is returning the name so that gives us the user name and hash key.


And increment that.  Unlike python, for example, you can just increment it.


It will do that for every iteration of the map{ }.  i.e. every line in the output of the `lsof`.

After that, it's just a matter of printing out the key/value pairs using a easy hash printing line blatently stolen from an answer on Stack Overflow.

3 Responses to “Perl one-liner to see who is hogging all the open filehandles”

  1. oylenshpeegul Says:

    Ooh, I love one-liners! I’m not really much of a golfer, but here’s a few things you might do with flags:

    You can use -l to get Perl to put that newline on for you.

    perl -le ‘map{$c{(split(/\s+/))[2]}++} `lsof`;print “$_ $c{$_}” for keys %c;’

    If we move the lsof call outside, then we can use -n to do the map

    lsof | perl -nle ‘$c{(split(/\s+/))[2]}++; END{print “$_ $c{$_}” for keys %c}’

    Then we can use -a to do the split

    lsof | perl -anle ‘$c{$F[2]}++; END{print “$_ $c{$_}” for keys %c}’

    With a recent perl, we can use say instead of print with -l

    lsof | perl -anE ‘$c{$F[2]}++; END{say “$_ $c{$_}” for keys %c}’

    The -l does a chomp on the way in too, but we didn’t really make use of that here, so say is all we need.

  2. Simon Flack Says:

    perl has some nice switches to simplify this a bit:

    lsof | perl -anE '$c{$F[2]}++ }END{say "$_ $c{$_}" for (keys %c);'

    =) Which is essentially piping lsof into:

    use feature 'say';
    while (defined($_ = )) {
    our(@F) = split(' ', $_, 0);
    sub END {
    say "$_ $c{$_}" foreach (keys %c);

    see `perldoc perlrun` for more info

  3. Chris Says:

    I’m so stealing both of those in the future – thanks both of you.

Leave a Comment