【问题标题】:How to find ports opened by process ID in Linux?如何在 Linux 中查找进程 ID 打开的端口?
【发布时间】:2010-10-30 21:06:50
【问题描述】:

假设进程的PID已知

【问题讨论】:

  • 这个问题不应该在 serverfault.com 上问吗?

标签: linux bash networking


【解决方案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' 也可以。命令ssiproute2 的一部分,是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 'BEGIN{FS="/"} /socket/{print $3}'` ;
            if [ "#$pid" = "#" ] ; then continue ; fi
            exefile=`ls -l /proc/$pid/exe | awk 'BEGIN{FS=" -> "}/->/{print $2;}'`
            #echo "$protocol|$pid|$ipportinode" 
            echo "$protocol|$pid|$ipportinode|$exefile" | awk '
                BEGIN{FS="|"}
                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(/(:0{1,3}|^0{1,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 'BEGIN{FS="/"} /socket/{pids[$3]} END{for (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 'BEGIN{FS=" -> "}/->/{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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-05-07
          • 2013-10-02
          • 1970-01-01
          • 2012-03-05
          • 2012-11-15
          • 1970-01-01
          • 1970-01-01
          • 2015-05-29
          相关资源
          最近更新 更多