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.
`lsof`
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.
split(/\s+/)
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.
(split(/\s+/))[2]
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.
$c{(split(/\s+/))[2]}
And increment that. Â Unlike python, for example, you can just increment it.
$c{(split(/\s+/))[2]}++
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.
]]>
http://www.imaginarybillboards.com/?feed=rss2&p=194
3
-
New network – How I find out what’s there
http://www.imaginarybillboards.com/?p=96
http://www.imaginarybillboards.com/?p=96#respond
Fri, 29 Jan 2010 16:48:21 +0000
http://www.imaginarybillboards.com/?p=96
I switched jobs recently to become sysadmin of a fairly small company. Â I think job #1 is to figure out just what is on your new network. Â It’s kind of important. Â This is the dumb little perl script I re-write every time I go someplace new because frankly – it’s fun!
#!/usr/bin/perl
use warnings;
use strict;
#this should be run as root, otherwise nmap will probably yell at you
my $net=shift || usage();
#the lazy, lazy regex to get the subnet you're working on...
$net=~s/(\d{1,3}\.\d{1,3}\.\d{1,3}\.)\d// || usage();
foreach my $end(0..255)
{
my $ip ="$net$end";
my ($fwd,$rev,$ud,$os) = ("unknown")x4;
my $nmap =`nmap -v -O -sT $ip`; #save for later
my @nmap =split("\n",$nmap);
#get forward and reverse DNS
chomp(my $host =`host $ip`);
if($host!~m/NXDOMAIN/)
{
$fwd=(split(" ",$host))[-1];
chomp($rev=`host $fwd`);
$rev=(split(" ",$rev))[-1];
$rev= "" unless $ip ne $rev; #only display if it doesn't equal the original ip
}
$ud = $nmap=~m/Host seems down/?'Down':'Up';
#get the o/s
$os=(grep(/Running/,@nmap))[0] || '';
if($os)
{
$os=~s/Running: //;
$os=substr $os,0,25;
}
$fwd=substr $fwd,0,40;
printf "%-16s%-5s%-28s%-43s%-20s\n",$ip,$ud,$os,$fwd,$rev;
}
sub usage
{
print "usage: >#!/usr/bin/perl
use warnings;
use strict;
#this should be run as root, otherwise nmap will probably yell at you
my $net=shift || usage();
#the lazy, lazy regex to get the subnet you're working on...
$net=~s/(\d{1,3}\.\d{1,3}\.\d{1,3}\.)\d/$1/ || usage();
foreach my $end(0..255)
{
my $ip ="$net$end";
my ($fwd,$rev,$ud,$os) = ("unknown")x4;
my $nmap =`nmap -v -O -sT $ip`; #save for later
my @nmap =split("\n",$nmap);
#get forward and reverse DNS
chomp(my $host =`host $ip`);
if($host!~m/NXDOMAIN/)
{
$fwd=(split(" ",$host))[-1];
chomp($rev=`host $fwd`);
$rev=(split(" ",$rev))[-1];
$rev= "" unless $ip ne $rev; #only display if it doesn't equal the original ip
}
$ud = $nmap=~m/Host seems down/?'Down':'Up';
#get the o/s
$os=(grep(/Running/,@nmap))[0] || '';
if($os)
{
$os=~s/Running: //;
$os=substr $os,0,25;
}
$fwd=substr $fwd,0,40;
printf "%-16s%-5s%-28s%-43s%-20s\n",$ip,$ud,$os,$fwd,$rev;
}
sub usage
{
print "usage: $0 ex: $0 192.168.0.0\n";
exit();
}< ex: >#!/usr/bin/perl
use warnings;
use strict;
#this should be run as root, otherwise nmap will probably yell at you
my $net=shift || usage();
#the lazy, lazy regex to get the subnet you're working on...
$net=~s/(\d{1,3}\.\d{1,3}\.\d{1,3}\.)\d/$1/ || usage();
foreach my $end(0..255)
{
my $ip ="$net$end";
my ($fwd,$rev,$ud,$os) = ("unknown")x4;
my $nmap =`nmap -v -O -sT $ip`; #save for later
my @nmap =split("\n",$nmap);
#get forward and reverse DNS
chomp(my $host =`host $ip`);
if($host!~m/NXDOMAIN/)
{
$fwd=(split(" ",$host))[-1];
chomp($rev=`host $fwd`);
$rev=(split(" ",$rev))[-1];
$rev= "" unless $ip ne $rev; #only display if it doesn't equal the original ip
}
$ud = $nmap=~m/Host seems down/?'Down':'Up';
#get the o/s
$os=(grep(/Running/,@nmap))[0] || '';
if($os)
{
$os=~s/Running: //;
$os=substr $os,0,25;
}
$fwd=substr $fwd,0,40;
printf "%-16s%-5s%-28s%-43s%-20s\n",$ip,$ud,$os,$fwd,$rev;
}
sub usage
{
print "usage: $0 ex: $0 192.168.0.0\n";
exit();
}< 192.168.0.0\n";
exit();
}
Example output:
monitor:~ imaginarybillboards$ sudo perl Documents/check_network.pl 192.168.2.0
192.168.2.0 Down unknown unknown
192.168.2.1 Up SonicWALL SonicOS 3.X firewall.private.blah.com.
192.168.2.2 Down switch.private.blah.com.
192.168.2.3 Up Cisco IOS 12.X ck-sw0.private.blah.com.
192.168.2.4 Down unknown unknown
192.168.2.5 Down unknown unknown
And without down hosts (a little more directly useful, perhaps):
monitor:~ imaginarybillboards$ sudo perl Documents/check_network.pl 192.168.2.0 | grep -v Down
192.168.2.102 Up Apple Mac OS X 10.5.X monitor.private.blah.com. 192.168.2.105
192.168.2.103 Up Linux 2.6.X cartman.private.blah.com.
192.168.2.104 Up Linux 2.6.X kenny.private.blah.com.
192.168.2.105 Up Apple Mac OS X 10.5.X monitor.private.blah.com.
192.168.2.107 Up Microsoft Windows XP unknown unknown
192.168.2.108 Up Apple iPhone OS 1.X|2.X|3 unknown unknown
192.168.2.110 Up Apple Mac OS X 10.5.X unknown unknown
192.168.2.112 Up Apple Mac OS X 10.5.X unknown unknown
Obviously, I have a bit of work to do with that monitor DNS. Â This gives me a decent idea of what's around. Â Servers and desktops (and iphones apparently) are all mixed on the same network.
Also, once I've (re-)written this, I put into a cron job so I can keep a running track of what's going on. Â Disk space is cheap, and it can't hurt anything.
crontab -l
0 2 * * * /bin/bash -login -c 'perl /Users/chriskaufmann/Documents/check_network.pl 192.168.200.0 > \
/Users/chriskaufmann/Documents/NetworkReports/`date +\%y-\%m-\%d`'
And then you can just diff them to see when something came onto the network.
]]>
http://www.imaginarybillboards.com/?feed=rss2&p=96
0
-
Lazy automatic ssh + key distribution
http://www.imaginarybillboards.com/?p=74
http://www.imaginarybillboards.com/?p=74#respond
Tue, 26 Jan 2010 21:00:53 +0000
http://www.imaginarybillboards.com/?p=74
I want to ssh to hosts, sometimes as a user, sometimes as root. Â I also want to distribute my public ssh key so I don’t have to login anymore. Â I want to do it without stacking tons of my keys onto the ends of files, and I want to be lazy about it. Â This is the script I use, I put it somewhere in my path as “go” with chmod +x so it’s executable. Â I can then use it like “go hostname” or “go chris@somehost”.
#!/usr/bin/env bash
#this will copy our public key to a remote host and ssh to it.
userhost=
keyfile=~/.ssh/id_rsa.pub
authkeyfile='~/.ssh/authorized_keys'
#if no username is passed (like someuser@somehost), use root by default
if [[ ! "$userhost" =~ '@' ]]
then
userhost=root@
fi
#if no ssh public key exists, create one in the default spot
if [ ! -e $keyfile ]
then
echo "Creating SSH key in $keyfile"
ssh-keygen -t rsa -f $keyfile -q -N ''
fi
#now get the key itself into a variable
mypubkey=`cat $keyfile`
#this keeps it to one time needed to enter the password,
#it'll create the .ssh directory with right perms, touch the key file,
#create a backup without our key (no dupes),
#and copy it back
ssh $userhost "mkdir -p .ssh;
chmod 700 .ssh;
touch $authkeyfile;
cp $authkeyfile ${authkeyfile}.bak;
grep -v '$mypubkey' ${authkeyfile}.bak > $authkeyfile;
echo '$mypubkey' >> $authkeyfile"
#and finally, ssh to the host.
ssh $userhost
]]>
http://www.imaginarybillboards.com/?feed=rss2&p=74
0
-
Building useful command lines, step by step
http://www.imaginarybillboards.com/?p=64
http://www.imaginarybillboards.com/?p=64#respond
Mon, 28 Sep 2009 22:06:30 +0000
http://www.imaginarybillboards.com/?p=64
1- I tend to have tons of things running at a time and want to watch out of a corner of my eye. Â Since I’m doing some pretty heavy stat stuff that can end up killing a machine’s memory in a short amount of time, I want to watch that too.
Enter ‘watch’. Â Here’s how it goes – watch -n<number of seconds to wait before refreshing> <command to do this to>
And here’s my big watch command (which I’ve aliased to watcher). Â In this I’m looking at perl and python processes, the amount of free memory and the cpu usage, and any mysql processes going on.
watch -n1 ' ps aux | egrep "(perl|python)" | grep -v grep;uptime;free -m; echo "show processlist" | mysql -uroot | grep -v Sleep'
This shows details on any perl or python processes (without the grep command itself), the load, the memory state, and any non-sleeping mysql processes. Â Every second. Â I just keep it up in a corner of the monitor.
2. Semi-related – killing a bunch of mysql processes.
Sometimes I’ll fire up a bunch of processes and decide they should go away. Â Easy – killall perl
works wonders. Â But the mysql processes remain – enter another one:
echo "show processlist" | mysql |egrep -v "(Id|processlist)" | awk {'print "kill "$1";"'} | mysql
What it does: Â 'echo "show proesslist" '
just echoes “show processlist” to standard output. Â That is then piped to the input of mysql.
#echo "show processlist" | mysql
Id User Host db Command Time State Info
455093 root localhost NULL Query 0 NULL show processlist
Next, it reverse-greps (as I like to call it) for ‘Id’ because I don’t want to see that.
# echo "show processlist" | mysql |grep -v Id
455095 root localhost NULL Query 0 NULL show processlist
Next, it inputs it into a very short awk program – what this does is split it up by spaces, and set each of those to a $<number> variable. Â So we print "kill $1;"
to standard out – that’ll be the command we want to send to mysql to kill them all. So we end up with:
# echo "show processlist" | mysql |grep -v Id| awk {'print "kill "$1";"'}
kill 455098;
Finally, pipe that into mysql, like so:
# echo "show processlist" | mysql |grep -v Id| awk {'print "kill "$1";"'} | mysql
ERROR 1094 (HY000) at line 1: Unknown thread id: 455101
What happened there? Â Well, since I’ve been killing threads for a good two minutes now while working on this shortcut the only thread left is the “show processlist” thread – which ends as soon as the processlist is shown. Â Which makes sense. Â So cheat and either add another grep -v
to get rid of it or  egrep with a simple regex: egrep -v "(Id|processlist)"
#echo "show processlist" | mysql |egrep -v "(Id|processlist)" | awk {'print "kill "$1";"'} | mysql
#
Yes, both of these could be done in better ways! Â But in my defense, part of doing these things is to share them with others and help them be better. Â Just like using simple perl is better a lot of the time than really complex code, simple things that are easy to handle are easier to show others and let them modify. Â Plus, this is actually how I go about helping someone solve one of these problems so they can do it themselves in the future.
Oh, and now I can just send this link…
]]>
http://www.imaginarybillboards.com/?feed=rss2&p=64
0
-
Stupid perl tricks (that would be better in something else)
http://www.imaginarybillboards.com/?p=56
http://www.imaginarybillboards.com/?p=56#comments
Thu, 20 Aug 2009 20:10:38 +0000
http://www.imaginarybillboards.com/?p=56
Hey, when you are really comfortable with a hammer, why not use it to open that beer too?
I have a giant (and I mean giant) dataset that I have to load and do some things with the data, then put it somewhere else. Â Once I managed to corrupt almost every single table. Â So, have to repair them all.
perl -e 'foreach $a qw{things whosit mrmr}{$cmd=qq{echo "repair table $a" | mysql -uroot mydb};print "$cmd\n";`$cmd`;}'
Silly use for the perls, but – it really works!
]]>
http://www.imaginarybillboards.com/?feed=rss2&p=56
4