Client auto-updater
Client auto-updater
This commit is contained in:
parent
679992db25
commit
ab016b37d1
@ -27,6 +27,11 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"net/http"
|
||||||
|
"syscall"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/fatedier/golib/crypto"
|
"github.com/fatedier/golib/crypto"
|
||||||
libdial "github.com/fatedier/golib/net/dial"
|
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/util"
|
||||||
"github.com/fatedier/frp/pkg/util/version"
|
"github.com/fatedier/frp/pkg/util/version"
|
||||||
"github.com/fatedier/frp/pkg/util/xlog"
|
"github.com/fatedier/frp/pkg/util/xlog"
|
||||||
|
"github.com/minio/selfupdate"
|
||||||
|
goversion "github.com/hashicorp/go-version"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -161,11 +168,100 @@ func (svr *Service) Run() error {
|
|||||||
log.Warn("run admin server error: %v", err)
|
log.Warn("run admin server error: %v", err)
|
||||||
}
|
}
|
||||||
log.Info("admin server listen on %s:%d", svr.cfg.AdminAddr, svr.cfg.AdminPort)
|
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()
|
<-svr.ctx.Done()
|
||||||
return nil
|
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() {
|
func (svr *Service) keepControllerWorking() {
|
||||||
xl := xlog.FromContextSafe(svr.ctx)
|
xl := xlog.FromContextSafe(svr.ctx)
|
||||||
maxDelayTime := 20 * time.Second
|
maxDelayTime := 20 * time.Second
|
||||||
|
Loading…
Reference in New Issue
Block a user