如何在 Linux 中查找进程 ID 打开的端口?
Posted
技术标签:
【中文标题】如何在 Linux 中查找进程 ID 打开的端口?【英文标题】:How to find ports opened by process ID in Linux? 【发布时间】:2010-10-30 21:06:50 【问题描述】:假设进程的PID已知
【问题讨论】:
这个问题不应该在 serverfault.com 上问吗? 【参考方案1】:netstat --all --program | grep '3265'
--all
显示监听和非监听套接字。
--program
显示socket所属程序的PID和名称。
您也可以使用端口扫描器,例如 Nmap。
【讨论】:
嗯..我似乎没有 --all 和 --program 选项。我正在使用 OSX。 Brew 似乎也没有公式。 OSX 预装了 nettop,但 IMO 在这类事情上比 netstat 更好。-n
将通过不解析主机名来显着加快速度。 netsta -tupan
是一个很好的默认命令,而且很容易记住。
'sudo netstat -ap' 是相同的较短版本。
ss -anp | grep '3265'
也可以。命令ss
是iproute2 的一部分,是net-tool 的替代品。【参考方案2】:
您可以使用以下命令:
lsof -i -P |grep pid
【讨论】:
这个在 CENTOS7 机器上为我工作,谢谢@Watever!【参考方案3】:附带说明,netstat -ao 将读取 /proc/PID/tcp 等以查看进程打开的端口。这意味着它的读取信息由系统(linux KERNEL)提供,绝不是直接在网络接口或其他方式上查看。 lsof 也是如此。
如果您将此作为安全措施,那么您就失败了。即使您 100% 确定您实际上正在运行真正的 netstat 程序(而不是木马版本)或任何其他读取 /proc 文件系统的程序,您也不应该(永远)相信 netstat 的输出。有些人似乎认为 netstat、ls、ps 或任何其他标准 unix 工具会从源头执行某种魔术和轮询信息,事实是它们都依赖 /proc 文件系统来获取所有数据,很容易被rootkit或hypervisor破坏。
【讨论】:
如果您正在处理带有 rootkit 的系统或受感染的虚拟机管理程序,您不能信任 任何东西,包括声称直接查看网络接口的东西。跨度> 【参考方案4】:您可以将netstat 命令行工具与-p
命令行参数一起使用:
-p
(Linux):Process:显示哪些进程正在使用哪些套接字(类似于Windows下的
-b
)。您必须是 root 才能执行此操作。
example section 给出了这个例子:
显示由 id
$PID
的进程打开的所有端口:netstat -ao | grep '\b'$PID'\b'
【讨论】:
【参考方案5】:在某些嵌入式设备或旧版本的 Linux 中,问题是netstat
没有可用的--process
或-p
选项。
以下脚本显示进程及其 IP 和端口,您必须是 root。
#!/bin/bash
for protocol in tcp udp ;
do
#echo "protocol $protocol" ;
for ipportinode in `cat /proc/net/$protocol | awk '/.*:.*:.*/print $2"|"$3"|"$10 ;'` ;
do
#echo "#ipportinode=$ipportinode"
inode=`echo "$ipportinode" | cut -d"|" -f3` ;
if [ "#$inode" = "#" ] ; then continue ; fi
lspid=`ls -l /proc/*/fd/* 2>/dev/null | grep "socket:\[$inode\]" 2>/dev/null` ;
pid=`echo "lspid=$lspid" | awk 'BEGINFS="/" /socket/print $3'` ;
if [ "#$pid" = "#" ] ; then continue ; fi
exefile=`ls -l /proc/$pid/exe | awk 'BEGINFS=" -> "/->/print $2;'`
#echo "$protocol|$pid|$ipportinode"
echo "$protocol|$pid|$ipportinode|$exefile" | awk '
BEGINFS="|"
function iphex2dec(ipport)
ret=sprintf("%d.%d.%d.%d: %d","0x"substr(ipport,1,2),"0x"substr(ipport,3,2),
"0x"substr(ipport,5,2),"0x"substr(ipport,7,2),"0x"substr(ipport,10,4)) ;
if( ret == "0.0.0.0:0" ) #compatibility others awk versions
ret= strtonum("0x"substr(ipport,1,2)) ;
ret=ret "." strtonum("0x"substr(ipport,3,2)) ;
ret=ret "." strtonum("0x"substr(ipport,5,2)) ;
ret=ret "." strtonum("0x"substr(ipport,7,2)) ;
ret=ret ":" strtonum("0x"substr(ipport,10)) ;
return ret ;
print $1" pid:"$2" local="iphex2dec($3)" remote="iphex2dec($4)" inode:"$5" exe=" $6 ;
' ;
#ls -l /proc/$pid/exe ;
done ;
done
输出如下:
tcp pid:1454 local=1.0.0.127:5939 remote=0.0.0.0:0 inode:13955 exe=/opt/teamviewer/tv_bin/teamviewerd
tcp pid:1468 local=1.1.0.127:53 remote=0.0.0.0:0 inode:12757 exe=/usr/sbin/dnsmasq
tcp pid:1292 local=0.0.0.0:22 remote=0.0.0.0:0 inode:12599 exe=/usr/sbin/sshd
tcp pid:4361 local=1.0.0.127:631 remote=0.0.0.0:0 inode:30576 exe=/usr/sbin/cupsd
tcp pid:1375 local=1.0.0.127:5432 remote=0.0.0.0:0 inode:12650 exe=/usr/lib/postgresql/9.3/bin/postgres
【讨论】:
【参考方案6】:我添加了 IPv6 支持并进行了一些修复。此外,在我的系统上,IP 地址的八位字节是相反的。依赖项仅适用于 posix shell、awk 和 cut。
我的版本可以在 Github
#!/bin/sh
# prints all open ports from /proc/net/*
#
# for pretty output (if available) start with
# ./linux-get-programm-to-port.sh | column -t -s $'\t'
#set -x
ip4hex2dec ()
local ip4_1octet="0x$1%???????????"
local ip4_2octet="$1%?????????"
ip4_2octet="0x$ip4_2octet#??"
local ip4_3octet="$1%???????"
ip4_3octet="0x$ip4_3octet#????"
local ip4_4octet="$1%?????"
ip4_4octet="0x$ip4_4octet#??????"
local ip4_port="0x$1##*:"
# if not used inverse
#printf "%d.%d.%d.%d:%d" "$ip4_1octet" "$ip4_2octet" "$ip4_3octet" "$ip4_4octet" "$ip4_port"
printf "%d.%d.%d.%d:%d" "$ip4_4octet" "$ip4_3octet" "$ip4_2octet" "$ip4_1octet" "$ip4_port"
# reoder bytes, byte4 is byte1 byte2 is byte3 ...
reorderByte()
if [ $#1 -ne 8 ]; then echo "missuse of function reorderByte"; exit; fi
local byte1="$1%??????"
local byte2="$1%????"
byte2="$byte2#??"
local byte3="$1%??"
byte3="$byte3#????"
local byte4="$1#??????"
echo "$byte4$byte3:$byte2$byte1"
# on normal intel platform the byte order of the ipv6 address in /proc/net/*6 has to be reordered.
ip6hex2dec()
local ip_str="$1%%:*"
local ip6_port="0x$1##*:"
local ipv6="$(reorderByte $ip_str%????????????????????????)"
local shiftmask="$ip_str%????????????????"
ipv6="$ipv6:$(reorderByte $shiftmask#????????)"
shiftmask="$ip_str%????????"
ipv6="$ipv6:$(reorderByte $shiftmask#????????????????)"
ipv6="$ipv6:$(reorderByte $ip_str#????????????????????????)"
ipv6=$(echo $ipv6 | awk ' gsub(/(:01,3|^01,3)/, ":"); sub(/(:0)+:/, "::");print')
printf "%s:%d" "$ipv6" "$ip6_port"
for protocol in tcp tcp6 udp udp6 raw raw6;
do
#echo "protocol $protocol" ;
for ipportinode in `cat /proc/net/$protocol | awk '/.*:.*:.*/print $2"|"$3"|"$10 ;'` ;
do
#echo "#ipportinode=$ipportinode"
inode=$ipportinode##*|
if [ "#$inode" = "#" ] ; then continue ; fi
lspid=`ls -l /proc/*/fd/* 2>/dev/null | grep "socket:\[$inode\]" 2>/dev/null` ;
pids=`echo "$lspid" | awk 'BEGINFS="/" /socket/pids[$3] ENDfor (pid in pids) print pid;'` ; # removes duplicats for this pid
#echo "#lspid:$lspid #pids:$pids"
for pid in $pids; do
if [ "#$pid" = "#" ] ; then continue ; fi
exefile=`ls -l /proc/$pid/exe | awk 'BEGINFS=" -> "/->/print $2;'`;
cmdline=`cat /proc/$pid/cmdline`
local_adr_hex=$ipportinode%%|*
remote_adr_hex=$ipportinode#*|
remote_adr_hex=$remote_adr_hex%%|*
if [ "#$protocol#???" = "#6" ]; then
local_adr=$(ip6hex2dec $local_adr_hex)
remote_adr=$(ip6hex2dec $remote_adr_hex)
else
local_adr=$(ip4hex2dec $local_adr_hex)
remote_adr=$(ip4hex2dec $remote_adr_hex)
fi
echo "$protocol pid:$pid \t$local_adr \t$remote_adr \tinode:$inode \t$exefile $cmdline"
done
done
done
【讨论】:
【参考方案7】:通过ls可以知道流程路线。
例子:
fuser 25/tcp
fuser命令说进程是:2054
ls -l /proc/2054/exe
出现进程路径
摘自:https://www.sysadmit.com/2018/06/linux-que-proceso-usa-un-puerto.html
Image example
【讨论】:
以上是关于如何在 Linux 中查找进程 ID 打开的端口?的主要内容,如果未能解决你的问题,请参考以下文章