无法打开执行命令的实时记忆分析的`proc/pid]/status”

发布于 2025-01-18 06:27:35 字数 3372 浏览 4 评论 0原文

动机:

我一直在尝试分析代码执行的时间和内存消耗,并在达到任一参数的限制后终止正在执行的命令。

障碍:

我正在尝试编写一个 go 例程,通过每隔 100 毫秒间隔从 proc/[pid]/status 读取状态来持续监控进程内存消耗。

命令执行代码块

// code block:

// define a resource group with limited memory
    rlimit := syscall.Rlimit{
        Cur: uint64(2048 * 1024 * 1024), // 1GB
        Max: uint64(2048 * 1024 * 1024), // 1GB
    }

// Create a new command
    cmd = exec.Command("/bin/bash", "-c", execCmd)

// Set command as separate process
    cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
    // Set resource limit
    err = syscall.Setrlimit(syscall.RLIMIT_AS, &rlimit)
    if err != nil {
        log.Fatal("Error in setting rlimit: ", err)
    }
    start := time.Now()

内存使用计算实用程序

Go 库 我正在使用 pidusage

// memoryUsage returns the memory usage of a process in bytes.
func memoryUsage(pid int) (float64, error) {
    stats, err := pidusage.GetStat(pid)
    if err != nil {
        return 0, err
    }
    return stats.Memory / 1024, nil
}

Go-routine

// call the function monitorMemory every 10 milli-seconds
// Get the current memory usage in the background
    go func(start time.Time) {
        // Print the memory usage every 10 milli-seconds
        for {
            // Get the current memory usage
            memoryUsage, err := memoryUsage(cmd.Process.Pid)
            if err != nil {
                fmt.Println(err)
                os.Exit(1)
            }

            // kill process if memory usage is greater than 2MB
            if memoryUsage > 500*1024 {
                err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
                if err != nil {
                    log.Fatal(err)
                    os.Exit(1)
                }
                result.ErrorCode = "MLE"
                result.RunTimeErr = "Memory Limit Exceeded. Took more than 500MB."
                result.MemoryUsage = memoryUsage
                result.RunTime = time.Since(start)
                printformattedResult(*result)

                // Exit the loop
                break
            }

            time.Sleep(1 * time.Nanosecond)
        }
    }(start)

如果将内存限制设置为小于 50 MB,但一旦我增加了监视限制并等待我开始,该方法效果很好得到的错误为:

open /proc/110050/stat: no such file or directory

其他尝试过方法:

我还尝试将内存使用情况读取为 float64(cmd.ProcessState.SysUsage((*syscall.Rusage).Maxrss) 但由于某种原因,go 例程会抛出错误“未找到内存地址”。对 go-routine 没有非常深入的了解,但我认为这可能是由于它试图访问单独运行的子进程。

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x4bb794]

goroutine 33 [running]:
os.(*ProcessState).sysUsage(...)
        /usr/local/go/src/os/exec_posix.go:96
os.(*ProcessState).SysUsage(...)
        /usr/local/go/src/os/exec.go:175
main.main.func2({0x0, 0x0, 0x5a0360})
        /path/to/my/go/file.go:149 +0x74
created by main.main
        /path/to/my/go/file.go:145 +0x7cf

Motive:

I have been trying to profile code execution for time as well as memory consumption and kill the executing command once a limit for either parameter is reached.

Roadblock:

I am trying to write a go-routine that constantly monitors the process memory consumption by reading the status from proc/[pid]/status at every 100-millisecond interval.

Command Execution Code Block

// code block:

// define a resource group with limited memory
    rlimit := syscall.Rlimit{
        Cur: uint64(2048 * 1024 * 1024), // 1GB
        Max: uint64(2048 * 1024 * 1024), // 1GB
    }

// Create a new command
    cmd = exec.Command("/bin/bash", "-c", execCmd)

// Set command as separate process
    cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
    // Set resource limit
    err = syscall.Setrlimit(syscall.RLIMIT_AS, &rlimit)
    if err != nil {
        log.Fatal("Error in setting rlimit: ", err)
    }
    start := time.Now()

Memory Usage calculation Utility

Go Library I am using pidusage

// memoryUsage returns the memory usage of a process in bytes.
func memoryUsage(pid int) (float64, error) {
    stats, err := pidusage.GetStat(pid)
    if err != nil {
        return 0, err
    }
    return stats.Memory / 1024, nil
}

Go-routine

// call the function monitorMemory every 10 milli-seconds
// Get the current memory usage in the background
    go func(start time.Time) {
        // Print the memory usage every 10 milli-seconds
        for {
            // Get the current memory usage
            memoryUsage, err := memoryUsage(cmd.Process.Pid)
            if err != nil {
                fmt.Println(err)
                os.Exit(1)
            }

            // kill process if memory usage is greater than 2MB
            if memoryUsage > 500*1024 {
                err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
                if err != nil {
                    log.Fatal(err)
                    os.Exit(1)
                }
                result.ErrorCode = "MLE"
                result.RunTimeErr = "Memory Limit Exceeded. Took more than 500MB."
                result.MemoryUsage = memoryUsage
                result.RunTime = time.Since(start)
                printformattedResult(*result)

                // Exit the loop
                break
            }

            time.Sleep(1 * time.Nanosecond)
        }
    }(start)

The approach works fine If set a memory limit for less than 50 MB but once I increase the limit to monitor and wait for I start getting the error as:

open /proc/110050/stat: no such file or directory

Other Tried approaches:

I also tried reading memory usage as float64(cmd.ProcessState.SysUsage((*syscall.Rusage).Maxrss) but for some reason go routine throws an error as `memory address not found. I do not have very in-depth knowledge of go-routine but I assumed this might be due to it trying to access a child process that is running separately.

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x4bb794]

goroutine 33 [running]:
os.(*ProcessState).sysUsage(...)
        /usr/local/go/src/os/exec_posix.go:96
os.(*ProcessState).SysUsage(...)
        /usr/local/go/src/os/exec.go:175
main.main.func2({0x0, 0x0, 0x5a0360})
        /path/to/my/go/file.go:149 +0x74
created by main.main
        /path/to/my/go/file.go:145 +0x7cf

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文