Setting process name (as seen by `ps`) in Go

前端 未结 3 1863
名媛妹妹
名媛妹妹 2020-12-16 22:28

The following (rightfully) doesn\'t work:

package main

import (
        \"os\"
        \"time\"
)

func main() {
        os.Args[0] = \"custom name\"
               


        
相关标签:
3条回答
  • 2020-12-16 22:39

    There are multiple ways to accomplish this, and many of them only work in certain situations. I don't really recommend doing it, as (for one thing) it can result in your process showing up with different names in different situations. They require using syscall and/or unsafe, and so you're deliberately subverting the safety of the Go language. That said, however, your options seem to be:

    Modify argv[0]

    func SetProcessName(name string) error {
        argv0str := (*reflect.StringHeader)(unsafe.Pointer(&os.Args[0]))
        argv0 := (*[1 << 30]byte)(unsafe.Pointer(argv0str.Data))[:argv0str.Len]
    
        n := copy(argv0, name)
        if n < len(argv0) {
                argv0[n] = 0
        }
    
        return nil
    }
    

    In Go, you don't have access to the actual argv array itself (without calling internal runtime functions), so you are limited to a new name no longer than the length of the current process name.

    This seems to mostly work on both Darwin and Linux.

    Call PR_SET_NAME

    func SetProcessName(name string) error {
        bytes := append([]byte(name), 0)
        ptr := unsafe.Pointer(&bytes[0])
        if _, _, errno := syscall.RawSyscall6(syscall.SYS_PRCTL, syscall.PR_SET_NAME, uintptr(ptr), 0, 0, 0, 0); errno != 0 {
                return syscall.Errno(errno)
        }
        return nil
    }
    

    The new name can be at most 16 bytes.

    This doesn't work on Darwin, and doesn't seem to do much on Linux, though it succeeds and PR_GET_NAME reports the correct name afterward. This may be something peculiar about my Linux VM, though.

    0 讨论(0)
  • 2020-12-16 22:42

    I don't think that "process title" is a well defined term. Anyway, what has Ruby to do with Go? The documentation for os.Args doesn't mention any "process title", nor it says any magic will happen on assigning to a slice item. The later is actually a general property of Go. There's no magic getters/setters for struct fields, variables of array/slice items, so a simple assignment simply assigns and does nothing more and cannot do anything more.

    In short, the lack of magic is the expected, correct behavior.

    For fiddling with process properties other than the portably accessible ones via the 'os' package, one has to use package 'syscall' in a platform specific way. But then the build constraints (discussed here) can help to correctly handle stuff across platforms.

    0 讨论(0)
  • 2020-12-16 22:43

    To change a process name on Linux, you need to use the prctl system call combined with the PR_SET_NAME option.

    At the moment, I don't think you can do this in Go code. You can, however, build a small C module to do this and then integrate it into your Go build.

    0 讨论(0)
提交回复
热议问题