以下(正确地)不起作用:
package main
import (
"os"
"time"
)
func main() {
os.Args[0] = "custom name"
println("sleeping")
time.Sleep(1000 * time.Second)
println("done")
}
Run Code Online (Sandbox Code Playgroud)
有些语言提供了将进程名称设置为内置功能的特性(例如,在Ruby中,它只是分配给它 $0)或作为第三方库(Python).
我正在寻找一种至少适用于Linux的解决方案.
Kyl*_*ons 12
有多种方法可以实现这一点,其中许多方法仅适用于某些情况.我不建议这样做,因为(一方面)它可能导致你的进程在不同情况下显示不同的名称.它们需要使用系统调用和/或不安全,因此您故意破坏Go语言的安全性.尽管如此,您的选择似乎是:
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
}
Run Code Online (Sandbox Code Playgroud)
在Go中,您无权访问实际的argv数组本身(不调用内部运行时函数),因此您只能使用不超过当前进程名称长度的新名称.
这似乎主要适用于Darwin和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
}
Run Code Online (Sandbox Code Playgroud)
新名称最多为16个字节.
这在Darwin上不起作用,并且在Linux上似乎没什么用,尽管它成功了,PR_GET_NAME之后报告了正确的名称.不过,这可能是我的Linux VM特有的.
zzz*_*zzz -1
我不认为“流程标题”是一个定义明确的术语。不管怎样,Ruby 和 Go 有什么关系呢?os.Args 的文档没有提到任何“进程标题”,也没有说分配给切片项时会发生任何魔法。后者实际上是 Go 的通用属性。结构体字段、数组/切片项的变量没有神奇的 getters/setters,所以简单的赋值只是简单地赋值,什么也不做,也不能做任何事情。
简而言之,缺乏魔法是预期的、正确的行为。
为了摆弄除通过“os”包可移植访问的进程属性之外的进程属性,必须以特定于平台的方式使用包“syscall”。但是构建约束(此处讨论)可以帮助正确处理跨平台的内容。