1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package main
import (
"fmt"
"os"
"syscall"
"time"
)
var build = "unset"
func main() {
exe, err := os.Executable()
link, _ := os.Readlink("/proc/self/exe")
var st syscall.Stat_t
_ = syscall.Stat("/proc/self/exe", &st)
stage := "start"
if len(os.Args) > 1 {
stage = os.Args[1]
}
fmt.Printf("[%s] build=%s pid=%d os.Executable=%q err=%v /proc/self/exe->%q inode=%d\n", stage, build, os.Getpid(), exe, err, link, st.Ino)
if stage != "start" {
return
}
fmt.Println("[start] waiting for rename-over signal file")
for {
if _, err := os.Stat(os.Getenv("SIGNAL_FILE")); err == nil {
break
}
time.Sleep(50 * time.Millisecond)
}
exe2, err2 := os.Executable()
link2, _ := os.Readlink("/proc/self/exe")
fmt.Printf("[after-rename] os.Executable=%q err=%v /proc/self/exe->%q\n", exe2, err2, link2)
target := exe2
if os.Getenv("REEXEC") == "procself" {
target = "/proc/self/exe"
}
fmt.Printf("[after-rename] execve(%q)\n", target)
if err := syscall.Exec(target, []string{target, "reexec-via-" + os.Getenv("REEXEC")}, os.Environ()); err != nil {
fmt.Println("exec:", err)
}
}