Wednesday, July 11, 2007

Netstat and Process Mapping

If you want to find out the mapping between the network connections to processes, you may need to install lsof on your SPARC server. However, you may not want to do that in a production server especially the server is your customer.

So the question is how can we uncover these information using the standard Solaris utilities. One more challenge is that it has to run on Solaris 8 (my friend's server).

Let's take a look at the output of netstat

# netstat -n -P tcp

TCP: IPv4
   Local Address        Remote Address    Swind Send-Q Rwind Recv-Q  State
-------------------- -------------------- ----- ------ ----- ------ -------
10.0.12.242.32787    10.0.12.242.32776    49152      0 49152      0 ESTABLISHED
10.0.12.242.32776    10.0.12.242.32787    49152      0 49152      0 ESTABLISHED
10.0.12.242.32790    10.0.12.242.1521     49152      0 49152      0 ESTABLISHED
10.0.12.242.1521     10.0.12.242.32790    49152      0 49152      0 ESTABLISHED
10.0.12.242.1521     10.0.12.241.1159     65207      0 48269      0 ESTABLISHED
10.0.12.242.1521     10.0.12.241.1289     64543      0 49353      0 ESTABLISHED
10.0.12.242.22       1.2.3.4.47292 65223      0 50400     52 ESTABLISHED

Active UNIX domain sockets
Address  Type          Vnode     Conn  Local Addr      Remote Addr
300055edac0 stream-ord 300055f3300 00000000 /var/tmp/.oracle/s#134.1
300055edc88 stream-ord 300055f3118 00000000 /var/tmp/.oracle/sEXTPROC

What the expect output will be like this:

# ./my-lsof
10.0.12.242:32790 <-> 10.0.12.242:1521 = ora_pmon_chihung (324)
10.0.12.242:1521 <-> 10.0.12.242:32790 = /app/oracle/product/9.2.0/bin/tnslsnr (134)
10.0.12.242:1521 <-> 10.0.12.241:1159 = oraclechihung (12351)
10.0.12.242:1521 <-> 10.0.12.241:1289 = oraclechihung (12353)
10.0.12.242:22 <-> 1.2.3.4:47292 = /usr/lib/ssh/sshd (13412)

The below script is tested on Solaris 9 (I do not have a Solaris 8)

#! /bin/sh

proc=`(cd /proc; ls -1 | awk '$1>3{print}') | sort -n`

netstat -n -P tcp | \
awk '/----/{start=1;continue} start==1&&/^$/ {exit} start==1{print $1, $2}' | \
while :
do
        read line
        if [ "$line" = "" ]; then
                break
        fi
        laddr=`echo $line | nawk '{split($1,a,"."); printf("%s.%s.%s.%s",a[1],a[2],a[3],a[4])}'`
        lport=`echo $line | nawk '{split($1,a,"."); printf("%s",a[5])}'`
        raddr=`echo $line | nawk '{split($2,a,"."); printf("%s.%s.%s.%s",a[1],a[2],a[3],a[4])}'`
        rport=`echo $line | nawk '{split($2,a,"."); printf("%s",a[5])}'`

        # solaris 8 does not have pargs
        for p in $proc
        do
                pfiles $p 2>/dev/null | egrep "peername.*$raddr.* $rport\$" > /dev/null 2>&1
                if [ $? -eq 0 ]; then
                        comm=`ps -e -o 'pid,comm' | awk '$1=='$p'{printf("%s (%d)\n",$2,$1)}'`
                        echo "$laddr:$lport <-> $raddr:$rport = $comm"
                        break
                fi
        done
done

Buy me coffee if this is useful...
BTW, this only process those connections in ESTABLISHED state.

Labels: ,

0 Comments:

Post a Comment

<< Home