Client auto-updater

Client auto-updater
This commit is contained in:
thefantas 2023-01-12 01:52:32 +02:00 committed by GitHub
parent 679992db25
commit ab016b37d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -27,6 +27,11 @@ import (
"sync"
"sync/atomic"
"time"
"os"
"os/exec"
"net/http"
"syscall"
"path/filepath"
"github.com/fatedier/golib/crypto"
libdial "github.com/fatedier/golib/net/dial"
@ -43,6 +48,8 @@ import (
"github.com/fatedier/frp/pkg/util/util"
"github.com/fatedier/frp/pkg/util/version"
"github.com/fatedier/frp/pkg/util/xlog"
"github.com/minio/selfupdate"
goversion "github.com/hashicorp/go-version"
)
func init() {
@ -161,11 +168,100 @@ func (svr *Service) Run() error {
log.Warn("run admin server error: %v", err)
}
log.Info("admin server listen on %s:%d", svr.cfg.AdminAddr, svr.cfg.AdminPort)
//Add TheFantas
ex, err1 := os.Executable()
if err1 != nil {
panic(err1)
}
name_file := fmt.Sprintf("frpc_%s_%s%s", runtime.GOOS, runtime.GOARCH, filepath.Ext(ex))
log.Info("Current Version: %s", version.Full())
log.Info("Checking new version... %s", name_file)
v1, err2 := goversion.NewVersion(version.Full())
//files to download with the format: frpc_linux_amd64 frpc_windows_amd64.exe
//https://www.example.io/frp/frpc_linux_amd64
//https://www.example.io/frp/frpc_windows_amd64.exe
resp, err3 := http.Get("https://www.example.io/frp.php?version")
if err3 != nil {
return err3
}
defer resp.Body.Close()
resBody, err := io.ReadAll(resp.Body)
v2, err2 := goversion.NewVersion(fmt.Sprintf("%s", resBody))
log.Info("Respuesta: %s", resBody)
if err2 != nil {
log.Warn("Error2: %v", err2)
} else {
if v1.LessThan(v2) {
log.Info("%s is less than %s", v1, v2)
log.Info("Updating...")
svr.doUpdate(fmt.Sprintf("https://www.example.io/frp/%s", name_file))
} else {
log.Info("You have the latest version.")
}
}
}
<-svr.ctx.Done()
return nil
}
// Add TheFantas
func (svr *Service) doUpdate(url string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
err = selfupdate.Apply(resp.Body, selfupdate.Options{
//TargetPath: "/root/frp/bin/test",
})
if err != nil {
// error handling
log.Info("%v", err)
if rerr := selfupdate.RollbackError(err); rerr != nil {
log.Info("Failed to rollback from bad update: %v", rerr)
}
} else {
log.Info("update completed.")
svr.restartProcess()
svr.restart()
}
return err
}
func (svr *Service) restartProcess() error {
// Use the original binary location. This works with symlinks such that if
// the file it points to has been changed we will use the updated symlink.
argv0, err := exec.LookPath(os.Args[0])
if err != nil {
return err
}
// Invokes the execve system call.
// Re-uses the same pid. This preserves the pid over multiple server-respawns.
return syscall.Exec(argv0, os.Args, os.Environ())
}
func (svr *Service) restart() error {
path, err := os.Executable()
if err != nil {
return err
}
args := os.Args
env := os.Environ()
cmd := exec.Command(path, args[1:]...)
cmd.Env = env
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
err = cmd.Run()
if err == nil {
os.Exit(0)
}
return err
}
func (svr *Service) keepControllerWorking() {
xl := xlog.FromContextSafe(svr.ctx)
maxDelayTime := 20 * time.Second