在Go中设置进程名称(如`ps`所示)

以下(正确)不起作用:

package main import ( "os" "time" ) func main() { os.Args[0] = "custom name" println("sleeping") time.Sleep(1000 * time.Second) println("done") } 

有些语言提供了将进程名称设置为内置function的特性(在Ruby中,例如,只是分配给 $0 )或作为第三方库( Python )。

我正在寻找一个至less在Linux上运行的解决scheme。

有多种方法可以完成这个任务,其中很多只能在某些情况下工作。 我不建议这样做,因为(有一点)它会导致你的过程在不同的情况下出现不同的名字。 他们需要使用系统调用和/或不安全的,所以你故意颠覆Go语言的安全性。 这就是说,但是,你的选择似乎是:

修改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 } 

在Go中,你没有访问实际的argv数组本身(没有调用内部运行时函数),所以你被限制到一个新的名字不能超过当前进程名的长度。

这似乎主要在达尔文和Linux上工作。

致电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 } 

新名称最多可以是16个字节。

这在Darwin上不起作用,并且在Linux上似乎没有多大作用,虽然它成功了,PR_GET_NAME之后报告了正确的名称。 不过,这可能是我的Linux VM特有的。

要在Linux上更改进程名称,您需要使用与PR_SET_NAME选项结合使用的prctl系统调用 。

目前,我不认为你可以在Go代码中做到这一点。 但是,您可以构建一个小型C模块来完成此任务,然后将其集成到您的Go版本中。

我不认为“程序标题”是一个明确的术语。 无论如何,Ruby和Go有什么关系? os.Args的文档没有提到任何“进程标题”,也没有说任何魔术将发生在分配到一个切片项目。 后者实际上是Go的一般属性。 没有什么魔术getters / setters结构字段,数组/分片项目的变量,所以一个简单的任务只是分配 ,什么也不做,什么不了

总之,缺乏魔法是预期的,正确的行为。

为了通过'os'包来处理除了可移植访问以外的进程属性,必须以平台特定的方式使用包'syscall'。 但是那么构建约束(在这里讨论)可以帮助正确处理跨平台的东西。