什么可以破坏 /proc/self/exe?

What could break /proc/self/exe?

我有一个简单的 Go 程序调用 os.Executable()。在较旧的 Linux 系统 (2.6.32) 上,它无法读取 /proc/self/exe,如 strace -f myexe -v public_html/ |& head -30:

所示
execve("/home/willem/myexe", ["myexe", "-v", "public_html/"], [/* 45 vars */]) = 0
mmap(0x1200000, 13352277, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, 0, 0) = 0x1200000
readlink("/proc/self/exe", "/hom/willem/my"..., 4096) = 37
mmap(0x400000, 13463552, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x400000
mmap(0x400000, 10254571, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x400000
mprotect(0x400000, 10254571, PROT_READ|PROT_EXEC) = 0
mmap(0xfc7000, 938770, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0x9c7000) = 0xfc7000
mprotect(0xfc7000, 938770, PROT_READ|PROT_WRITE) = 0
mmap(0x10ad000, 170408, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x10ad000
munmap(0x1201000, 13348181)             = 0
uname({sys="Linux", node="sip5-83.nexcess.net", ...}) = 0
brk(0)                                  = 0x10d7000
brk(0x10d81c0)                          = 0x10d81c0
arch_prctl(ARCH_SET_FS, 0x10d7880)      = 0
set_tid_address(0x10d7b50)              = 16193
set_robust_list(0x10d7b60, 24)          = 0
rt_sigaction(SIGRTMIN, {0x83c310, [], SA_RESTORER|SA_SIGINFO, 0x83ba20}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {0x83c3a0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x83ba20}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
getrlimit(RLIMIT_STACK, {rlim_cur=10240*1024, rlim_max=RLIM64_INFINITY}) = 0
readlink("/proc/self/exe", 0x7ffcfec64dc0, 4096) = -1 ENOENT (No such file or directory)

我不明白为什么第一个阅读链接有效而第二个无效。没有分叉,可执行文件也没有移动。有什么想法吗?

我可以通过将 os.Executable() 移动到程序的 init 来修复它,但我想了解为什么它不能按原样工作。

所以原因竟然是UPX(可执行压缩器)。我之前没有想到它,因为它包含在我的构建管道中。显然,在某些系统上,它不会提取到内存中,而是使用临时文件,这会导致此错误。我仍然对为什么跟踪输出不显示重命名感到困惑,但是唉。