我如何确定哪个进程正在打开某个 tcp 端口?
How can I figure out which process is opening the certain tcp port?
我通常使用 fuser 命令来检查 pid 打开某个 tcp 端口,如下所示
fuser 22/tcp //To get pid opening the 22 tcp port
我有一块参考板,其中 运行 嵌入了 linux。
它已经为 ssh 连接打开了 22 个 tcp 端口。
但是 fuser 不显示任何关于 22 端口的输出。
所以我尝试了另一个 ssh 守护进程打开 322 端口,然后尝试使用 fuser 检查 pid,它工作正常。
root@imx6qsabreauto:~# netstat -nlt | grep 22
tcp 0 0 0.0.0.0:4224 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:322 0.0.0.0:* LISTEN
tcp 0 0 :::322 :::* LISTEN
tcp 0 0 :::22 :::* LISTEN
root@imx6qsabreauto:~# fuser 322/tcp
351
root@imx6qsabreauto:~# ps -ef | grep 351
root 351 1 0 01:46 ? 00:00:00 /usr/sbin/dropbear -r /etc/dropbear/dropbear_rsa_host_key -p 322 -B
root 379 315 0 02:11 ttymxc3 00:00:00 grep 351
root@imx6qsabreauto:~# fuser 22/tcp
==> This output nothing !!
如何确定哪个进程正在打开 tcp 22 端口。
(在开发板中,lsof 命令不可用并且.. netstat 没有-p 选项。)
我安装了 /proc
并且安装了 bash
和 readlink
,
可以写一个小的bash脚本解析/proc/net/tcp
,扫描/proc/*/fd/
找到对应的socket
我对嵌入式linux不太熟悉,但如果找不到readlink
,它可能包含在busybox
.
/proc/net/tcp
类似于
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:4E7A 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 13128 1 ffff8800cf960740 99 0 0 10 0
local_address
是HOST:PORT
的十六进制字符串,所以当你想搜索tcp 22端口时,脚本会搜索:0016
。
一旦找到 local_address
中包含 :0016
的行,
inode
是相应的套接字号。
然后它使用readlink
命令搜索具有套接字号的/proc/*/fd/*
。
#!/bin/bash
PORT=""
HEX_PORT=$(printf %04X $PORT)
INODE=""
if ! [ "$PORT" ];then
echo "usage [=11=] [PORT]"
exit
fi
while read num host_port _ _ _ _ _ _ _ inode _; do
if [[ $host_port =~ :"$HEX_PORT"$ ]];then
INODE=$inode
fi
done < /proc/net/tcp
if ! [ "$INODE" ];then
echo "no process using $PORT"
exit
fi
for fn in /proc/[1-9]*/fd/*; do
if [ "$(readlink $fn)" = "socket:[$INODE]" ];then
tmp=${fn%/fd*}
echo ${tmp#/proc/}
fi
done
谢谢@ymonad!! :)
正如你提到的,我已经能够像下面这样获得对应于端口的 pid。
root@imx6qsabreauto:~# cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:1080 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 1018 1 d8d90a00 100 0 0 10 0
1: 00000000:0DA2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 842 1 d8d90000 100 0 0 10 0
2: 00000000:006F 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 2515 1 d8dc8000 100 0 0 10 0
3: 0100007F:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 877 1 d8d90500 100 0 0 10 0
root@imx6qsabreauto:~# cat /proc/net/tcp6
sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeo
ut inode
0: 00000000000000000000000000000000:006F 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0
0 2518 1 d8dd0000 100 0 0 10 -1
1: 00000000000000000000000001000000:0035 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0
0 881 1 d8de0000 100 0 0 10 -1
2: 00000000000000000000000000000000:0016 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0
0 4933 1 d8da0000 100 0 0 10 -1
您的 shell 脚本工作正常,它可以像下面这样正确获取 pid。
root@imx6qsabreauto:~# /tmp/find.sh 22
1
奇怪的是结果 pid 是 1。
这是初始化过程;;
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 04:21 ? 00:00:04 /sbin/init
我想我需要弄清楚 init 进程如何打开 22 tcp 端口。
真的很谢谢你。 :D 我学到了很多东西。再次感谢!!
这是在 Tomato/BusyBox 路由器上运行的 ymonad 脚本的一个版本:
#!/bin/sh
# This works with BusyBox on a Tomato router
PORT=""
HEX_PORT=`printf %04X $PORT`
INODE=""
if ! [ "$PORT" ]; then
echo "Find the process that is listening on an open TCP network port."
echo "usage [=10=] [PORT]"
exit 2
fi
# sl localip:port remip:port st tx_q:rx_q tr:when retrns uid timeout inode ...
while read num host_port _ _ _ _ _ _ _ inode _; do
port=`echo "$host_port" | awk -F: '{print }'`
if [ "$port" = "$HEX_PORT" ]; then
INODE=$inode
fi
done < /proc/net/tcp
if ! [ "$INODE" ]; then
echo "no process using $PORT"
exit 1
fi
echo "found inode $INODE"
f=`ls -l /proc/[1-9]*/fd/* 2>/dev/null | fgrep "socket:[$INODE]" | awk '{print }'`
if ! [ "$f" ] ; then
echo "no process found using inode $INODE"
exit 1
fi
pid=`echo "$f" | awk -F/ '{print }'`
echo "Process matching PID=$pid:"
ps w | awk "$1==$pid {print}"
如果您的设备上有或可以获得 ss
,它可以向您显示 PID:
ss -ltp # for TCP
ss -lup # for UDP
我通常使用 fuser 命令来检查 pid 打开某个 tcp 端口,如下所示
fuser 22/tcp //To get pid opening the 22 tcp port
我有一块参考板,其中 运行 嵌入了 linux。 它已经为 ssh 连接打开了 22 个 tcp 端口。 但是 fuser 不显示任何关于 22 端口的输出。 所以我尝试了另一个 ssh 守护进程打开 322 端口,然后尝试使用 fuser 检查 pid,它工作正常。
root@imx6qsabreauto:~# netstat -nlt | grep 22
tcp 0 0 0.0.0.0:4224 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:322 0.0.0.0:* LISTEN
tcp 0 0 :::322 :::* LISTEN
tcp 0 0 :::22 :::* LISTEN
root@imx6qsabreauto:~# fuser 322/tcp
351
root@imx6qsabreauto:~# ps -ef | grep 351
root 351 1 0 01:46 ? 00:00:00 /usr/sbin/dropbear -r /etc/dropbear/dropbear_rsa_host_key -p 322 -B
root 379 315 0 02:11 ttymxc3 00:00:00 grep 351
root@imx6qsabreauto:~# fuser 22/tcp
==> This output nothing !!
如何确定哪个进程正在打开 tcp 22 端口。 (在开发板中,lsof 命令不可用并且.. netstat 没有-p 选项。)
我安装了 /proc
并且安装了 bash
和 readlink
,
可以写一个小的bash脚本解析/proc/net/tcp
,扫描/proc/*/fd/
找到对应的socket
我对嵌入式linux不太熟悉,但如果找不到readlink
,它可能包含在busybox
.
/proc/net/tcp
类似于
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:4E7A 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 13128 1 ffff8800cf960740 99 0 0 10 0
local_address
是HOST:PORT
的十六进制字符串,所以当你想搜索tcp 22端口时,脚本会搜索:0016
。
一旦找到 local_address
中包含 :0016
的行,
inode
是相应的套接字号。
然后它使用readlink
命令搜索具有套接字号的/proc/*/fd/*
。
#!/bin/bash
PORT=""
HEX_PORT=$(printf %04X $PORT)
INODE=""
if ! [ "$PORT" ];then
echo "usage [=11=] [PORT]"
exit
fi
while read num host_port _ _ _ _ _ _ _ inode _; do
if [[ $host_port =~ :"$HEX_PORT"$ ]];then
INODE=$inode
fi
done < /proc/net/tcp
if ! [ "$INODE" ];then
echo "no process using $PORT"
exit
fi
for fn in /proc/[1-9]*/fd/*; do
if [ "$(readlink $fn)" = "socket:[$INODE]" ];then
tmp=${fn%/fd*}
echo ${tmp#/proc/}
fi
done
谢谢@ymonad!! :) 正如你提到的,我已经能够像下面这样获得对应于端口的 pid。
root@imx6qsabreauto:~# cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:1080 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 1018 1 d8d90a00 100 0 0 10 0
1: 00000000:0DA2 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 842 1 d8d90000 100 0 0 10 0
2: 00000000:006F 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 2515 1 d8dc8000 100 0 0 10 0
3: 0100007F:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 877 1 d8d90500 100 0 0 10 0
root@imx6qsabreauto:~# cat /proc/net/tcp6
sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeo
ut inode
0: 00000000000000000000000000000000:006F 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0
0 2518 1 d8dd0000 100 0 0 10 -1
1: 00000000000000000000000001000000:0035 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0
0 881 1 d8de0000 100 0 0 10 -1
2: 00000000000000000000000000000000:0016 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0
0 4933 1 d8da0000 100 0 0 10 -1
您的 shell 脚本工作正常,它可以像下面这样正确获取 pid。
root@imx6qsabreauto:~# /tmp/find.sh 22
1
奇怪的是结果 pid 是 1。 这是初始化过程;;
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 04:21 ? 00:00:04 /sbin/init
我想我需要弄清楚 init 进程如何打开 22 tcp 端口。 真的很谢谢你。 :D 我学到了很多东西。再次感谢!!
这是在 Tomato/BusyBox 路由器上运行的 ymonad 脚本的一个版本:
#!/bin/sh
# This works with BusyBox on a Tomato router
PORT=""
HEX_PORT=`printf %04X $PORT`
INODE=""
if ! [ "$PORT" ]; then
echo "Find the process that is listening on an open TCP network port."
echo "usage [=10=] [PORT]"
exit 2
fi
# sl localip:port remip:port st tx_q:rx_q tr:when retrns uid timeout inode ...
while read num host_port _ _ _ _ _ _ _ inode _; do
port=`echo "$host_port" | awk -F: '{print }'`
if [ "$port" = "$HEX_PORT" ]; then
INODE=$inode
fi
done < /proc/net/tcp
if ! [ "$INODE" ]; then
echo "no process using $PORT"
exit 1
fi
echo "found inode $INODE"
f=`ls -l /proc/[1-9]*/fd/* 2>/dev/null | fgrep "socket:[$INODE]" | awk '{print }'`
if ! [ "$f" ] ; then
echo "no process found using inode $INODE"
exit 1
fi
pid=`echo "$f" | awk -F/ '{print }'`
echo "Process matching PID=$pid:"
ps w | awk "$1==$pid {print}"
如果您的设备上有或可以获得 ss
,它可以向您显示 PID:
ss -ltp # for TCP
ss -lup # for UDP