Sep 252012
 

After beating on some really anemic linux installations that had… well, just about nothing installed (one didn’t have “tr”, one didn’t have “df”, etc… come on, that’s pretty sad ;)), I decided to start writing some shell scripts in very, very basic shell (you can do a lot with shell, awk, and sed!)

Here’s one that while not perfect, at least seems to work (so far!) – I <3 lsof, but it turns out you can get a bit of its functionality via /proc (plus it saved me from cursing more at the stupid people who made it so fucking difficult to make a cross compiled frickin’ static binary.) Here’s one that shows all the network connections and tries to show the pid associated with them. I didn’t bother trying to make it really work, hoping that I’d stop fooling around with these damn things, but it was useful enough to post. It currently also doesn’t distinguish on the interface, so ports open on 127.0.0.1, say, are listed. That said, try doing this by hand, esp without netstat -p, lsof, nn, and all the other billion tools that do this for you. Bleah.

Ouput looks something like:

[WPCM450 ~]$ ./lsof-net-pid.sh
collecting port data...
machine is listening on:
tcp:     8195   1317 = /usr/local/bin/guiDataServer
        1391 = /usr/local/bin/guiDataServer
        1392 = /usr/local/bin/guiDataServer
        3925 = /usr/local/bin/guiDataServer
tcp:     5988   1162 = /sbin/sfcbd -d
tcp:     22 1263 = /sbin/sshd -g 60
tcp:     22 6536 = sshd: root@pts/0
[...]

Script below. Blindingly fast on a real system, dog slow on a BMC, say :) Should be sorted, should be not necessary, too.

:

#
# busybox - find network ports being listened to by pid
#

fd="/proc/*/fd"

#
# list of all the stuff everyone is listening to
#
echo "collecting port data..."

# slooow... jumping through more hoops than michael jordon.. ls will produce lines like:
#
# [...]
# /proc/1261/fd:
# /proc/1262/fd:
# /proc/1263/fd:
#  0 lrwx------    1 root     root           64 Sep 25 15:03 3 -> socket:[4535]
# [...]
#
# this will have matching pairs of pid's & inodes of sockets
#
# grab the line before the match as the pid, since ls won't say what is going on
# and find won't work on this
#
all_sox=`ls -asl /proc/[0-9]*/fd 2> /dev/null | egrep 'socket:|fd' |  awk '{ if (/fd:/) { split($1,fd,"/"); } if (/socket/) print fd[3], $NF ; }' | sed -e 's/socket:\[//' -e 's/\]//'`

echo "machine is listening on:"
grep -v local_address /proc/net/?[cd]p* | awk '{print $1, $3, $11}' | while read proto port inode ; do
   if [ "X$proto" != "X" ] ; then
   
     # echo "$proto, $port, $inode"
   
     echo -n $proto | sed -e 's@^.*net/@@' -e 's/://'
     echo -n ":"
     
     #
     # more busybox hoop jumping... sometimes like ice skating with roller skates
     #
     # the amazing sed+ stuff courtesy of http://stackoverflow.com/questions/3675012/hex-to-dec-con
     #
     echo $port | awk -F: '{print $2}' | sed 's,\(..\)\(..\)\(..\)\(..\),\4\3\2\1,g' | (read hex; echo -en "\t" $(( 0x${hex} )))

     if [ "X$inode" != "X" ] ; then

        pid=`echo "$all_sox" | grep " $inode"`

# fd=`ls -asl /proc/[0-9]*/fd 2> /dev/null | egrep 'socket:\[4535\]|fd' |  awk '{ if (/fd:/) { split($1,fd,"/"); } if (/socket/) print "FD: ", fd[3]; }'`

        if [ "X$pid" == "X" ] ; then
           echo -e "\t*** can't find process for inode $inode ***"
        else

           matching_pids=`echo "$pid" | awk '{ pids=sprintf("%s %s", pids, $1);} END { print pids }'`
 
           # echo "MATCHING: $matching_pids"
   
           spacing="\\t"
           for p in $matching_pids ; do
              if [ -f /proc/$p/cmdline ] ; then
                 name=`tr '\000' " " <  /proc/$p/cmdline | sed 's/ *$//' `
              else
                 name="?"
              fi
              echo -e "$spacing$p = $name"
              spacing="\\t\\t"
           done

         fi
      else
         echo "no inode found associated with port $port"
      fi
   fi
   done

Sorry, the comment form is closed at this time.