Files
OpenFlare/openflare_server/service/update_restart_unix.go
T
2026-03-15 16:26:56 +08:00

74 lines
1.6 KiB
Go

//go:build !windows
package service
import (
"fmt"
"io"
"os"
"syscall"
)
var unixRename = os.Rename
func replaceAndRestartServer(execPath string, tmpPath string) error {
backupPath := execPath + ".bak"
_ = os.Remove(backupPath)
if err := unixRename(execPath, backupPath); err != nil {
_ = os.Remove(tmpPath)
return fmt.Errorf("备份当前服务端二进制失败: %w", err)
}
if err := replaceFileUnix(tmpPath, execPath); err != nil {
_ = unixRename(backupPath, execPath)
return fmt.Errorf("替换服务端二进制失败: %w", err)
}
_ = os.Remove(backupPath)
if err := syscall.Exec(execPath, os.Args, os.Environ()); err != nil {
return fmt.Errorf("重启服务失败: %w", err)
}
return fmt.Errorf("unreachable after exec")
}
func replaceFileUnix(srcPath string, dstPath string) error {
if err := unixRename(srcPath, dstPath); err == nil {
return nil
} else if linkErr, ok := err.(*os.LinkError); !ok || linkErr.Err != syscall.EXDEV {
return err
}
sourceFile, err := os.Open(srcPath)
if err != nil {
return err
}
defer sourceFile.Close()
info, err := sourceFile.Stat()
if err != nil {
return err
}
destinationFile, err := os.OpenFile(dstPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode().Perm())
if err != nil {
return err
}
copyErr := func() error {
defer destinationFile.Close()
if _, err = io.Copy(destinationFile, sourceFile); err != nil {
return err
}
if err = destinationFile.Sync(); err != nil {
return err
}
return nil
}()
if copyErr != nil {
return copyErr
}
if err = os.Chmod(dstPath, info.Mode().Perm()); err != nil {
return err
}
return os.Remove(srcPath)
}