【问题标题】:How can I figure out which process is opening the certain tcp port?如何确定哪个进程正在打开某个 tcp 端口?
【发布时间】:2015-08-25 02:17:34
【问题描述】:

我通常使用 fuser 命令来检查打开某个 tcp 端口的 pid,如下所示

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 选项。)

【问题讨论】:

    标签: linux ssh netstat fuser


    【解决方案1】:

    我已经安装了 /procbashreadlink 两者, 你可以写一个小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_addressHOST:PORT的十六进制字符串,所以当你要搜索tcp 22端口时,脚本会搜索:0016

    一旦在local_address 中找到包含:0016 的行, inode 是对应的套接字号。

    然后它使用readlink 命令搜索具有套接字号的/proc/*/fd/*

    #!/bin/bash
    PORT="$1"
    HEX_PORT=$(printf %04X $PORT)
    INODE=""
    if ! [ "$PORT" ];then
      echo "usage $0 [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
    

    【讨论】:

      【解决方案2】:

      这是在 Tomato/BusyBox 路由器上运行的 ymonad 脚本的一个版本:

      #!/bin/sh
      
      # This works with BusyBox on a Tomato router
      
      PORT="$1"
      HEX_PORT=`printf %04X $PORT`
      INODE=""
      if ! [ "$PORT" ]; then
          echo "Find the process that is listening on an open TCP network port."
          echo "usage $0 [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 $2}'`
          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 $9}'`
      if ! [ "$f" ] ; then
          echo "no process found using inode $INODE"
          exit 1
      fi
      pid=`echo "$f" | awk -F/ '{print $3}'`
      echo "Process matching PID=$pid:"
      ps w | awk "\$1==$pid {print}"
      

      【讨论】:

      • 答案中包含的期望会很酷,它应该在哪些系统上运行。
      • 建议将fgrep更改为grep -F
      【解决方案3】:

      如果您有或可以在您的设备上获得ss,它可以向您显示 PID:

      ss -ltp # for TCP
      ss -lup # for UDP
      

      【讨论】:

        【解决方案4】:

        谢谢@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 我学到了很多。再次感谢!!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-08
          • 2012-04-09
          • 2010-09-08
          • 2011-07-22
          • 1970-01-01
          相关资源
          最近更新 更多