I have an ultra old (don't ask why) BusyBox (BusyBox v1.01 (2008.12.19-21:31+0000) Built-in shell (ash)) on my DreamBox. I would like to find out which process opened which connection using netstat. But I found out that BusyBox's netstat doesn't contain the -p option. What other possibilites do I have to find out which process has opened (and is using) the corresponding socket?
-
Is lsof part of that version of busybox? – Zoredache Jan 07 '11 at 21:07
-
Unfortunately not. – a1337q Jan 07 '11 at 21:10
5 Answers
You can find the equivalent information in slightly uglier form (a.k.a. hexadecimal) in /proc/net/tcp
. There, you can find the inode of the connection, which you can look up under /proc/$pid/fd/
.
For example:
$ cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 6115 1 f5adc4c0 300 0 0 2 -1
...
(In normal netstat, but not in busybox netstat, the -e
option also gives you that extra information.)
You can find the process which corresponds to the inode with the following command:
# for x in $(find /proc/ | grep /fd/); do ls -la $x 2>/dev/null done | grep 6115
...
lrwx------ 1 root root 64 7 jan 22.50 /proc/2560/fd/3 -> socket:[6115]
You need root access for the second step.
Not as convenient as the -p
option, obviously, but works in a bind. Could be scripted, if necessary.
- 7
- 2
- 3,575
- 1
- 23
- 21
-
Sounds cool, but my netstat doesn't work as it should, it outputs nothing additional with the **-e** option. I have 6 columns also with **-e**: Proto, Recv-Q, Send-Q, Local Address, Foreign Address, State. Is there a way with the ports? I can see the port.. – a1337q Jan 07 '11 at 21:05
-
You're right, I must have messed up my tests. I edited it to give you a working solution. – Peter Eisentraut Jan 08 '11 at 08:39
-
2How do you find the number "2560" you type in your second command? That's the question. – ygoe Mar 22 '19 at 11:17
-
1@ygoe you have to use `6115` and use it like this: `find /proc/ -type l | grep /fd/ | xargs ls -la 2>/dev/null | grep 6115` – Sam Jun 27 '19 at 12:44
-
This may not help, if you don't have the opportunity to rebuild Busybox, but in case it helps anyone...
Busybox does have a configuration option to support the -p
switch of Busybox netstat
. See option CONFIG_FEATURE_NETSTAT_PRG
, selected in busybox menuconfig via Networking Utilities → netstat → Enable PID/Program name output.
- 720
- 6
- 18
If you have or can get ss
on your device it can show you the PID too:
ss -ltp # for TCP
ss -lup # for UDP
- 141
- 4
A slight variant that might be easier for some:
- Identify interesting protocol and port from netstat or other source
- Convert port to hex: echo | awk '{ printf "%x\n", $1 }'
- cd /proc/net
- grep -i <hex_port> {upd|tcp} | awk '{ printf "local: %s inode: %s", $2, $10 }' If you get multiple lines, look for the one that has the matching hex_port in the second half of the "local" string.
- ls -al /proc//fd/ 2>/dev/null | grep
This should return a line similar to: lrwx------ 1 root root 64 May 22 20:02 /proc/1148/fd/26 -> socket:[4520]
Telling you that PID 1148 has a socket open on inode 4520
Example: Looking for the SSDP process on a Philips Hue Bridge V2.x:
root@Philips-hue:/proc# netstat -an | grep 1900
udp 2176 0 0.0.0.0:1900 0.0.0.0:*
root@Philips-hue:/proc# echo 1900 | awk '{ printf "%x\n", $1 }'
76c
root@Philips-hue:/proc# grep -i 76c /proc/net/udp | awk '{ printf "local: %s ino
de: %s\n", $2, $10 }'
local: 00000000:076C inode: 4520
root@Philips-hue:/proc# ls -al /proc/*/fd/* 2>/dev/null | grep 4520
lrwx------ 1 root root 64 May 22 20:02 /proc/1148/fd/26 -> socket:[4520]
So we identified process PID=1148 as the listener:
root@Philips-hue:/proc# ps w | grep 1148
1148 root 64016 S /usr/sbin/ipbridge -p /home/ipbridge/var -z /dev/ttyZigbee -u /etc/channel/channel-config -h /home -e ecb
1696 root 1284 S grep 1148
So now I know that the ipbridge daemon controls the SSDP listener among the many other things it controls on the Hue Bridge.
- 39
- 3
Here's a complete awk script for it. It's ugly but it works.
{ cat /proc/net/tcp; lsof; } | awk -vMACH=$(uname -m) 'BEGIN { if (MACH == "i686") { M=-2; B=7; } else { M=2; B=1 } } function addr(a) { if (a) { return sprintf("%d.%d.%d.%d:%d", "0x" substr(a, M*0+B, 2), "0x" substr(a, M*1+B, 2), "0x" substr(a, M*2+B, 2), "0x" substr(a, M*3+B, 2), "0x" substr(a, 10, 4)); } } substr($0,5,1)==":" { sock[$10]=$0; next } $3~/socket:/ { if (match($3, /[0-9]+/) == 0) { exit; } l = sock[substr($3, RSTART, RLENGTH)]; print $0 " " addr(substr(l, 7, 13)) " " addr(substr(l, 21, 13)) }'
- 29
- 1
- 1
- 4