macOS下用Go调用sysctl获取进程绝对路径报错求助
在macOS上用Go通过sysctl获取进程绝对路径时遇到"no such file or directory"错误
问题描述
我是Go和macOS的新手,尝试使用sysctl获取运行中进程的完整路径名,编写了如下代码:
kprocs, err := unix.SysctlKinfoProcSlice("kern.proc.all") if err != nil { fmt.Println("error: ", err) } for _, proc := range kprocs { name := string(proc.Proc.P_comm[:]) pid := proc.Proc.P_pid extName, err := unix.SysctlKinfoProc("kern.proc.pathname", int(pid)) if err != nil { fmt.Println("error: ", err) }
运行后报错:no such file or directory,请问我是否正确使用了该函数?
补充说明:若通过./processName启动进程,我无法获取其绝对路径(如/Users/username/go/src/processName),而ps命令仅返回相对路径,我需要能获取进程绝对路径的方案。
解答
你错误使用了SysctlKinfoProc函数——这个函数专门用于获取返回KinfoProc结构体类型的sysctl节点(比如kern.proc.all),但kern.proc.pathname返回的是字符串类型的进程路径,并非KinfoProc结构,因此调用该函数会触发错误。
下面提供两种可行的解决方案,都能获取进程的绝对路径:
方法一:使用unix.Sysctl构造正确的sysctl键
直接构造包含PID的sysctl键,调用unix.Sysctl获取路径字符串:
package main import ( "fmt" "golang.org/x/sys/unix" ) func main() { kprocs, err := unix.SysctlKinfoProcSlice("kern.proc.all") if err != nil { fmt.Println("error: ", err) return } for _, proc := range kprocs { pid := proc.Proc.P_pid // 构造格式为 kern.proc.pathname.<pid> 的sysctl键 path, err := unix.Sysctl(fmt.Sprintf("kern.proc.pathname.%d", pid)) if err != nil { fmt.Printf("pid %d error: %v\n", pid, err) continue } fmt.Printf("pid: %d, absolute path: %s\n", pid, path) } }
方法二:读取macOS的/proc文件系统路径
macOS原生支持/proc/<pid>/path文件,读取该文件即可获取进程的绝对路径:
package main import ( "fmt" "os" "strings" "golang.org/x/sys/unix" ) func main() { kprocs, err := unix.SysctlKinfoProcSlice("kern.proc.all") if err != nil { fmt.Println("error: ", err) return } for _, proc := range kprocs { pid := proc.Proc.P_pid pathFile := fmt.Sprintf("/proc/%d/path", pid) pathBytes, err := os.ReadFile(pathFile) if err != nil { fmt.Printf("pid %d error: %v\n", pid, err) continue } // 去除文件末尾的换行符 path := strings.TrimSpace(string(pathBytes)) fmt.Printf("pid: %d, absolute path: %s\n", pid, path) } }
这两种方法都能正确返回你通过./processName启动进程的完整绝对路径。需要注意的是,对于系统核心进程或你无权限访问的进程,可能会出现权限错误,这属于正常的系统权限限制。
内容的提问来源于stack exchange,提问作者sbs_il
相关产品推荐
相关产品推荐

