You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 12:54:21