The following (rightfully) doesn\'t work:
package main
import (
\"os\"
\"time\"
)
func main() {
os.Args[0] = \"custom name\"
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:
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.
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.