根据ip:port快速获取进程pid
2017-10-21 22:36
429 查看
常规pid与ip:port信息的相互查找
对于如何由进程号获取端口号以及由端口号获取进程号,使用lsof命令都可以做到,以sshd 服务为例:
//ps -ef | grep sshd root 1 0 0 Jul31 ? 00:00:07 /usr/sbin/sshd -D //lsof -i:22 由端口获取进程 sshd 1 root 3u IPv4 1649695748 0t0 TCP *:ssh (LISTEN) // lsof -anP -itcp -p1 由进程获取端口 sshd 1 root 3u IPv4 1649695748 0t0 TCP *:22 (LISTEN)
由pid查找ip:port信息
对于lsof而言,使用的办法就是查/proc下的文件,使用pid查端口无疑会很快捷,因为/proc下的文件就是以pid来命令的,查找的大致过程如下:
通过pid进入/proc/pid/fd目录,找到进程打开的所有文件描述,其中正在打开的链接内容为socket:[id],可使用readlink读取,拿到Socket的id。
lr-x------ 1 root root 64 7月 31 18:14 0 -> pipe:[1649692705] l-wx------ 1 root root 64 7月 31 18:14 1 -> pipe:[1649692706] l-wx------ 1 root root 64 7月 31 18:14 2 -> pipe:[1649692707] lrwx------ 1 root root 64 7月 31 18:14 3 -> socket:[1649695748] [root@99b54f61ad38 fd]# readlink 3 socket:[1649695748]
读取/proc/net/tcp ,就可以看到关于这个id的链接信息。
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode 4: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 1649695748 1 ffff881274789e00 100 0 0 10 0
由ip:port 获取pid
由pid获取ip:port信息,lsof只需到对应的proc目录下读取相应的socketid,然后查找/proc/net下的文件即可,但是反过来,就没那么容易了。系统并不没有使用IP:Port存储对应的进程信息,换句话说,想通过端口号查找pid,lsof的工作将会很笨重。
首先从/proc/net/tcp(或者其他文件)下读取该Ip:port对应的socketid信息;
拿着这个socket id信息遍历/proc下所有pid文件的fd目录,匹配到socketid则记录下该pid,返回。
实现通过端口查pid
在有时候使用lsof命令是很危险的,比如机器复杂过高的情况下,这个命令可能成为压倒他的最后一根稻草。并且,lsof功能过于强大,他的遍历附带东西太多,所以很耗费时间。这里实现了一种轻便的方式快速实现了由端口获取pid。 本质上下面的程序并没有改变遍历的方式,只不过没有像lsof那样附加太多东西,只是单存的由端口查找pid。
func GetPid(addr int64) (pid string, err error) { port := fmt.Sprintf("%04X", addr) SocketId, err := GetSocketId(port) if err != nil { return } SocketInfo := fmt.Sprintf("socket:[%s]", SocketId) procDirList, err := ioutil.ReadDir("/proc") if err != nil { return } for _, procDir := range procDirList { _, err := strconv.Atoi(procDir.Name()) if err != nil { continue } fdDir := fmt.Sprintf("/proc/%s/fd", procDir.Name()) fdSonDirList, err := ioutil.ReadDir(fdDir) for _, socketFile := range fdSonDirList { socket := fmt.Sprintf("/proc/%s/fd/%s", procDir.Name(), socketFile.Name()) data, err := os.Readlink(socket) if err != nil { continue } if SocketInfo == data { return procDir.Name(), nil } } } return "", errors.New("get pid fail") } func GetSocketId(port string) (SocketId string, err error) { fi, err := os.Open("/proc/net/tcp") if err != nil { return } defer fi.Close() br := bufio.NewReader(fi) for { a, _, c := br.ReadLine() if c == io.EOF { break } Info := strings.Fields(string(a)) // Info不同位置代表不同,想从哪查就获取啥 remPort := strings.Split(Info[1], ":") if len(remPort) == 2 { if remPort[1] == port { SocketId = Info[9] return } } } return "", errors.New("get SocketId fail") }
相关文章推荐
- linux 下根据进程名字获取进程的进程号PID
- AIX如何根据监听端口(Listening Port)查找进程号(PID)
- 根据客户端套接字获取客户机的IP和端口号,其形式为IP:port
- Android根据进程名获取对应的进程pid
- 如何在命令行(cmd)通过TCP/IP端口(port)查询所在的进程号(pid)或进程名称,并终止该进程
- VB6 根据进程ID(PID)获取窗体句柄
- 根据系统进程pid获取sql【脚本收藏】
- 根据PID获取进程名 或者 根据进程名获取PID
- 根据进程名称获取进程pid,结束进程,执行exe文件
- delphi根据进程PID获取程序所在路径的函数(用OpenProcess取得句柄,用GetModuleFileNameEx取得程序名)
- 根据PID获取进程名&根据进程名获取PID
- 根据包名获取进程pid
- linux根据pid获取进程名和获取进程pid(c语言获取pid)
- linux 根据 进程名 获取 对应 PID 来 判断 使用 内存情况
- 根据进程名获取进程PID以及进程
- linux shell 根据进程名获取pid
- linux根据pid获取进程名和获取进程pid(c语言获取pid)
- 获取进程pid、根据进程pid获取线程pid、获取线程进程句柄
- delphi根据进程PID获取程序所在路径的函数
- linux 下根据进程名字获取进程的进程号PID,类似pidof,C函数