查看Linux机器上端口号信息

查看端口号及对应的进程信息

注下面的示例均是在 root 帐号进行操作,示例代码可以根据实际情况调整。

  • 通过 netstat -ntlp 查看目前机器上的端口占用情况

image.png

  • 获取 port pid 信息
netstat -ntlp | awk -F'/' '{print $1}' | awk '{print $4,$NF}' | awk -F':' '{if (NR>2){print $NF}}'
复制代码

image.png

  • 根据进程查看进程下详细信息

image.png

/proc/pid/ 目录下文件说明

proc - process information pseudo-filesystem (进程信息伪文件系统)。proc文件系统中的大多数文件都是只读的,但也有一些文件是可写的,允许更改内核变量。 下面列出的文件及目录的详细描述参考

  • attr

    • current
    • exec
    • fscreate
    • keycreate
    • prev
    • sockcreate
  • autogroup

  • auxv

    包含传递给进程的ELF解释器信息,格式是每一项都是一个unsigned long长度的ID加上一个unsigned long长度的值。最后一项以连续的两个0x00开头。

    hexdump auxv
    0000000 0021 0000 0000 0000 f000 685e 7ffd 0000
    0000010 0010 0000 0000 0000 fbff bfeb 0000 0000
    0000020 0006 0000 0000 0000 1000 0000 0000 0000
    0000030 0011 0000 0000 0000 0064 0000 0000 0000
    0000040 0003 0000 0000 0000 0040 0020 0000 0000
    0000050 0004 0000 0000 0000 0038 0000 0000 0000
    0000060 0005 0000 0000 0000 000b 0000 0000 0000
    0000070 0007 0000 0000 0000 a000 b6f5 7f2e 0000
    0000080 0008 0000 0000 0000 0000 0000 0000 0000
    0000090 0009 0000 0000 0000 1000 004b 0000 0000
    00000a0 000b 0000 0000 0000 27b1 0000 0000 0000
    00000b0 000c 0000 0000 0000 27b1 0000 0000 0000
    00000c0 000d 0000 0000 0000 271a 0000 0000 0000
    00000d0 000e 0000 0000 0000 271a 0000 0000 0000
    00000e0 0017 0000 0000 0000 0000 0000 0000 0000
    00000f0 0019 0000 0000 0000 6f59 685e 7ffd 0000
    0000100 001a 0000 0000 0000 0000 0000 0000 0000
    0000110 001f 0000 0000 0000 8fdc 685e 7ffd 0000
    0000120 000f 0000 0000 0000 6f69 685e 7ffd 0000
    0000130 0000 0000 0000 0000 0000 0000 0000 0000
    0000140
    复制代码
  • cgroup

  • clear_refs

  • cmdline

    是一个只读文件,包含进程的完整命令行信息.

    # cat cmdline
    /usr/local/bin/chromedriver--port=26443
    复制代码
  • comm

    包含进程的命令名。

    # cat comm
    chromedriver
    复制代码
  • coredump_filter

  • cpuset

  • cwd

    是进程当前工作目录的符号链接。

    # ll cwd
    lrwxrwxrwx 1 xxx deploy 0 Nov 25 10:55 cwd -> /home/xxx/work/xxxx
    复制代码
  • environ

    显示进程的环境变量

    # strings environ
    XDG_SESSION_ID=282753
    SHELL=/bin/sh
    USER=xxx
    PATH=/usr/bin:/bin
    PWD=/home/xxx/work/xxxx
    LANG=en_US.UTF-8
    SHLVL=1
    HOME=/home/xxx
    LOGNAME=xxx
    XDG_RUNTIME_DIR=/run/user/10161
    OLDPWD=/home/xxx
    _=/home/xxx/venv3/bin/python
    DJANGO_SETTINGS_MODULE=settings
    TZ=Asia/Shanghai
    复制代码
  • exe

    为实际运行程序的符号链接。

  • fd

    是一个目录,包含进程打开文件的情况。

  • fdinfo

  • gid_map

  • io

  • limits

    显示当前进程的资源限制。

    # cat limits
    Limit                     Soft Limit           Hard Limit           Units
    Max cpu time              unlimited            unlimited            seconds
    Max file size             unlimited            unlimited            bytes
    Max data size             unlimited            unlimited            bytes
    Max stack size            8388608              unlimited            bytes
    Max core file size        0                    unlimited            bytes
    Max resident set          unlimited            unlimited            bytes
    Max processes             127912               127912               processes
    Max open files            65535                65535                files
    Max locked memory         65536                65536                bytes
    Max address space         unlimited            unlimited            bytes
    Max file locks            unlimited            unlimited            locks
    Max pending signals       127912               127912               signals
    Max msgqueue size         819200               819200               bytes
    Max nice priority         0                    0
    Max realtime priority     0                    0
    Max realtime timeout      unlimited            unlimited            us
    复制代码
  • loginuid

  • map_files

  • maps

    显示进程的内存区域映射信息。

    # cat maps  | head
    00200000-004b1000 r--p 00000000 08:04 4317821208                         /usr/local/bin/chromedriver
    004b1000-009ef000 r-xp 002b1000 08:04 4317821208                         /usr/local/bin/chromedriver
    009ef000-00a2b000 rw-p 007ef000 08:04 4317821208                         /usr/local/bin/chromedriver
    00a2b000-00a4b000 rw-p 00000000 00:00 0
    26108c113000-26108c114000 ---p 00000000 00:00 0
    26108c114000-26108c133000 rw-p 00000000 00:00 0
    26108c133000-26108c134000 ---p 00000000 00:00 0
    26108c134000-26108c153000 rw-p 00000000 00:00 0
    26108c153000-26108c154000 ---p 00000000 00:00 0
    26108c154000-26108c18a000 rw-p 00000000 00:00 0
    复制代码
  • mem

  • mountinfo

  • mounts

  • mountstats

  • net

  • ns

  • numa_maps

  • oom_adj

  • oom_score

  • oom_score_adj

  • pagemap

  • personality

  • projid_map

  • root

  • sched

  • schedstat

  • sessionid

  • setgroups

  • smaps

  • stack

    显示当前进程的内核调用栈信息,只有内核编译时打开了CONFIG_STACKTRACE编译选项,才会生成这个文件。

    # cat stack
    [<ffffffff810f5126>] futex_wait_queue_me+0xc6/0x130
    [<ffffffff810f5deb>] futex_wait+0x17b/0x280
    [<ffffffff810f7b26>] do_futex+0x106/0x5a0
    [<ffffffff810f8040>] SyS_futex+0x80/0x180
    [<ffffffff816b4fc9>] system_call_fastpath+0x16/0x1b
    [<ffffffffffffffff>] 0xffffffffffffffff
    复制代码
  • stat

  • statm

    显示进程所占用内存大小的统计信息,包含七个值,度量单位是pagepage大小可通过getconf PAGESIZE得到)。

    # cat statm
    51478 730 445 2031 0 12816 0
    
    # getconf PAGESIZE
    4096
    复制代码

    七个值的含义分别为

    • 进程占用的总的内存
    • 进程当前时刻占用的物理内存
    • 同其它进程共享的内存
    • 进程的代码段
    • 共享库(从2.6版本起,这个值为0)
    • 进程的堆栈
    • dirty pages(从2.6版本起,这个值为0)
    • status

    包含进程的状态信息。其很多内容与/proc/[pid]/stat/proc/[pid]/statm,但是却是以一种更清晰地方式展现出来。

    # cat status
    Name:	chromedriver
    Umask:	0022
    State:	S (sleeping)
    Tgid:	13834
    Ngid:	0
    Pid:	13834
    PPid:	1
    TracerPid:	0
    Uid:	10161	10161	10161	10161
    Gid:	10010	10010	10010	10010
    FDSize:	64
    Groups:	989 10010
    VmPeak:	  206004 kB
    VmSize:	  205912 kB
    VmLck:	       0 kB
    VmPin:	       0 kB
    VmHWM:	    5144 kB
    VmRSS:	    2920 kB
    RssAnon:	    1140 kB
    RssFile:	    1780 kB
    RssShmem:	       0 kB
    VmData:	   51132 kB
    VmStk:	     132 kB
    VmExe:	    8124 kB
    VmLib:	    4912 kB
    VmPTE:	     148 kB
    VmSwap:	       0 kB
    Threads:	5
    SigQ:	0/127912
    SigPnd:	0000000000000000
    ShdPnd:	0000000000000000
    SigBlk:	0000000000000000
    SigIgn:	0000000000000000
    SigCgt:	0000000180000000
    CapInh:	0000000000000000
    CapPrm:	0000000000000000
    CapEff:	0000000000000000
    CapBnd:	0000001fffffffff
    CapAmb:	0000000000000000
    Seccomp:	0
    Cpus_allowed:	ffffffff
    Cpus_allowed_list:	0-31
    Mems_allowed:	00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000003
    Mems_allowed_list:	0-1
    voluntary_ctxt_switches:	10
    nonvoluntary_ctxt_switches:	1
    复制代码
  • syscall

    显示当前进程正在执行的系统调用

    # cat syscall
    202 0x7ffd685e6754 0x80 0x1 0x0 0x7ffd685e6700 0x0 0x7ffd685e5fd0 0x7f2eb6b45945
    复制代码
  • task

  • timers

  • uid_map

  • wchan

    显示当进程sleep时,kernel当前运行的函数。

    # cat wchan
    futex_wait_queue_me
    复制代码

代码实现

import (
    "bufio"
    "io"
    "os/exec"
    "strings"
    "sync"
    "fmt"
)

var wg sync.WaitGroup

type HasBeenUsedPortInfo struct {
    Pid     string
    Port    string
    Program string
}

// GetHostnameHasBeenUsedPort 获取当前机器占用的端口号及端口启用的进程id
func GetHostnameHasBeenUsedPortAndPid() []map[string]string {
    var portAndPid []map[string]string
    // 该命令为直接获取当前机器上运行端口号和启动端口号的进程pid
    cmd := exec.Command("/bin/sh", "-c", `netstat -ntlp | awk -F'/' '{print $1}' | awk '{print $4,$NF}' | awk -F':' '{if (NR>2){print $NF}}'`)
    stdout, _ := cmd.StdoutPipe()
    cmd.Start()
    reader := bufio.NewReader(stdout)

    for {
	line, err := reader.ReadString('\n')
	line = strings.TrimSpace(line)
	if err != nil || io.EOF == err {
            break
	}
	lines := strings.Split(line, " ")
	port, pid := lines[0], lines[1]
	
        portAndPid = append(portAndPid, map[string]string{
            "pid":  pid,
            "port": port,
	})
    }
    cmd.Wait()
    
    return portAndPid
}

func CheckPort() {
    hostname, _ := os.Hostname()
    port := GetHostnameHasBeenUsedPortAndPid()
    var usedPortInfo []HasBeenUsedPortInfo
    
    wg.Add(len(port))
    for _, v := range port {
       go func(pid, port string) {
          defer wg.Done()
          // 该命令获取进程运行的目录及启动的命令
          cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf(`sudo su -c"ls -l /proc/%s/{cwd,exe}" | awk '{print $NF}'`, pid))
          process, _ := cmd.CombinedOutput()
          line := strings.TrimSpace(string(process))

          lines := strings.Split(line, "\n")
          program := fmt.Sprintf(`{"cwd":"%s", "exe":"%s"}`, lines[0], lines[1])

          usedPortInfo = append(usedPortInfo, HasBeenUsedPortInfo{
             Pid:     pid,
             Port:    port,
             Program: program,
          })
       }(v["pid"], v["port"])
    }
    wg.Wait()

    // 获取所有已被占用的端口及进行信息
    fmt.Println("hostname:", usedPortInfo, "usedPortInfo": usedPortInfo)
}

复制代码

参考

Guess you like

Origin juejin.im/post/7034540193637990408