func updateBinaryFile(url string, checksum []byte) { fmt.Println("Downloading updated binary") httpResp, err := http.Get(url) if err != nil { glog.Errorf("Cannot download binary: %s", err) os.Exit(1) } defer httpResp.Body.Close() binary := httpResp.Body if httpResp.ContentLength > 0 { bar := pb.New64(httpResp.ContentLength).SetUnits(pb.U_BYTES) bar.Start() binary = bar.NewProxyReader(binary) defer func() { <-time.After(bar.RefreshRate) fmt.Println() }() } err = update.Apply(binary, update.Options{ Hash: crypto.SHA256, Checksum: checksum, }) if err != nil { glog.Errorf("Cannot apply binary update: %s", err) err := update.RollbackError(err) if err != nil { glog.Errorf("Failed to rollback update: %s", err) } os.Exit(1) } }
func updateBinary(v semver.Version, downloadBinary, updateLinkPrefix, downloadLinkFormat string) { checksum, err := downloadChecksum(v, downloadBinary, downloadLinkFormat) if err != nil { glog.Errorf("Cannot download checksum: %s", err) os.Exit(1) } binary, err := http.Get(fmt.Sprintf(downloadLinkFormat, v, downloadBinary)) if err != nil { glog.Errorf("Cannot download binary: %s", err) os.Exit(1) } defer binary.Body.Close() err = update.Apply(binary.Body, update.Options{ Hash: crypto.SHA256, Checksum: checksum, }) if err != nil { glog.Errorf("Cannot apply binary update: %s", err) os.Exit(1) } env := os.Environ() args := os.Args currentBinary, err := osext.Executable() if err != nil { glog.Errorf("Cannot find current binary to exec: %s", err) os.Exit(1) } err = syscall.Exec(currentBinary, args, env) if err != nil { glog.Errorf("Failed to exec updated binary: %s", err) os.Exit(1) } }
// SelfUpdate updates the zmon binary. It has several limitations: // // - It always performs updates, unconditionally. // // - It downloads the entire binary, not patches. // // - Binaries are not compressed. // // - There is no forced shutdown of old binaries. func SelfUpdate() error { resp, err := http.Get(updateURL()) if err != nil { return err } defer resp.Body.Close() if err := update.Apply(resp.Body, update.Options{}); err != nil { return fmt.Errorf("Update failed: %v\n", err) } log.Println("Update succeeded") return nil }
func (u *Updater) updateBinary(url string, latest *version.Version) error { u.Log.Info("Current version: %s is old. Going to update to: %s", u.CurrentVersion, latest) self, err := osext.Executable() if err != nil { return err } u.Log.Info("Going to update binary at: %s", self) bin, err := u.fetch(url) if err != nil { return err } u.Wait.Add(1) defer u.Wait.Done() u.Log.Info("Replacing new binary with the old one.") if err = update.Apply(bytes.NewBuffer(bin), update.Options{}); err != nil { return err } env := os.Environ() // TODO: os.Args[1:] should come also from the endpoint if the new binary // has a different flag! args := []string{self} args = append(args, os.Args[1:]...) // we need to call it here now too, because syscall.Exec will prevent to // call the defer that we've defined in the beginning. u.Log.Info("Updating was successfull. Replacing current process with args: %v\n=====> RESTARTING...\n\n", args) execErr := syscall.Exec(self, args, env) if execErr != nil { return err } return nil }