mirror of
https://github.com/ayflying/p2p.git
synced 2026-03-04 17:29:22 +00:00
99 lines
2.6 KiB
Go
99 lines
2.6 KiB
Go
package system
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
"os/exec"
|
||
"path"
|
||
"path/filepath"
|
||
"runtime"
|
||
"time"
|
||
|
||
"github.com/ayflying/p2p/internal/service"
|
||
"github.com/gogf/gf/v2/encoding/gcompress"
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
"github.com/gogf/gf/v2/os/gcmd"
|
||
)
|
||
|
||
func (s *sSystem) Update(ctx context.Context) (err error) {
|
||
//拼接操作系统和架构(格式:OS_ARCH)
|
||
platform := fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)
|
||
|
||
runFile := gcmd.GetArg(0).String()
|
||
oldFile, err := service.System().RenameRunningFile(runFile)
|
||
g.Log().Debugf(ctx, "执行文件改名为%v", oldFile)
|
||
gz := path.Join("download", platform+".gz")
|
||
err = gcompress.UnGzipFile(gz, runFile)
|
||
|
||
go func() {
|
||
log.Println("5秒后开始重启...")
|
||
time.Sleep(5 * time.Second)
|
||
|
||
if err = service.System().RestartSelf(); err != nil {
|
||
log.Fatalf("重启失败:%v", err)
|
||
}
|
||
}()
|
||
return
|
||
}
|
||
|
||
// RestartSelf 实现 Windows 平台下的程序自重启
|
||
func (s *sSystem) RestartSelf() error {
|
||
// 1. 获取当前程序的绝对路径
|
||
exePath, err := os.Executable()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
// 处理路径中的符号链接(确保路径正确)
|
||
exePath, err = filepath.EvalSymlinks(exePath)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 2. 获取命令行参数(os.Args[0] 是程序名,实际参数从 os.Args[1:] 开始)
|
||
args := os.Args[1:]
|
||
|
||
// 3. 构建新进程命令(路径为当前程序,参数为原参数)
|
||
cmd := exec.Command(exePath, args...)
|
||
// 设置新进程的工作目录与当前进程一致
|
||
cmd.Dir, err = os.Getwd()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 新进程的输出继承当前进程的标准输出(可选,根据需求调整)
|
||
cmd.Stdout = os.Stdout
|
||
cmd.Stderr = os.Stderr
|
||
cmd.Stdin = os.Stdin
|
||
|
||
// 4. 启动新进程(非阻塞,Start() 后立即返回)
|
||
if err := cmd.Start(); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 5. 新进程启动成功后,退出当前进程
|
||
os.Exit(0)
|
||
return nil // 理论上不会执行到这里
|
||
}
|
||
|
||
// RenameRunningFile 重命名正在运行的程序文件(如 message.exe → message.exe~)
|
||
func (s *sSystem) RenameRunningFile(exePath string) (string, error) {
|
||
// 目标备份文件名(message.exe → message.exe~)
|
||
backupPath := exePath + "~"
|
||
|
||
// 先删除已存在的备份文件(若有)
|
||
if _, err := os.Stat(backupPath); err == nil {
|
||
if err := os.Remove(backupPath); err != nil {
|
||
return "", fmt.Errorf("删除旧备份文件失败: %v", err)
|
||
}
|
||
}
|
||
|
||
// 重命名正在运行的 exe 文件
|
||
// 关键:Windows 允许对锁定的文件执行重命名操作
|
||
if err := os.Rename(exePath, backupPath); err != nil {
|
||
return "", fmt.Errorf("重命名运行中文件失败: %v", err)
|
||
}
|
||
return backupPath, nil
|
||
}
|