查看端口号及对应的进程信息
注下面的示例均是在 root 帐号进行操作,示例代码可以根据实际情况调整。
- 通过
netstat -ntlp
查看目前机器上的端口占用情况
- 获取
port
pid
信息
netstat -ntlp | awk -F'/' '{print $1}' | awk '{print $4,$NF}' | awk -F':' '{if (NR>2){print $NF}}'
复制代码
- 根据进程查看进程下详细信息
/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
显示进程所占用内存大小的统计信息,包含七个值,度量单位是
page
(page
大小可通过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)
}
复制代码