You are writing a CLI client in Go and your users would love to be able to update this client seamlessly.
I'm talking replacing a currently running executable on UNIX platforms.
// exa.go
package main
import (
"os"
"path"
"syscall"
)
func main() {
binary := "./replace.sh"
args := []string{path.Base(binary)}
env := os.Environ()
if err := syscall.Exec(binary, args, env); err != nil {
panic(err)
}
}
// exa.go
package main
import "os"
import "io/ioutil"
func main() {
src, dst := "./replace.sh", "./exa_"
data, err := ioutil.ReadFile(src)
if err != nil {
panic(err)
}
if err := ioutil.WriteFile(dst, data, 0744); err != nil {
panic(err)
}
if err := os.Rename("./exa_", "./exa"); err != nil {
panic(err)
}
}
#!/bin/bash -eux
# replace.sh
cp ./replace.sh exa_
mv exa_ exa
go build -o exa
./exa
diff -q replace.sh exa && echo It worked!
# It worked!