From 04d6a667fe8d588c7706fe2f36e5f16b8c867be6 Mon Sep 17 00:00:00 2001 From: master <727475183@qq.com> Date: Sat, 9 May 2026 14:16:27 +0800 Subject: [PATCH] fix(ota): disable elf check and fix self-update binary replacement --- internal/control/ota_agent.go | 54 +++++++++++++++++++++++++--------- python/.infer_server.py.swp | Bin 0 -> 16384 bytes 2 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 python/.infer_server.py.swp diff --git a/internal/control/ota_agent.go b/internal/control/ota_agent.go index 01b32e9..2a0df10 100644 --- a/internal/control/ota_agent.go +++ b/internal/control/ota_agent.go @@ -33,6 +33,7 @@ func (o *OTAAgent) Run(ctx context.Context) { ticker := time.NewTicker(10 * time.Minute) defer ticker.Stop() + log.Printf("ota: current hour=%d, maintenance window check=%v", time.Now().Hour(), inMaintenanceWindow()) // Check once on startup if in maintenance window if inMaintenanceWindow() { o.check(client) @@ -56,8 +57,14 @@ func inMaintenanceWindow() bool { } func (o *OTAAgent) check(client *http.Client) { + log.Printf("ota: checking for updates (window=%v, current_version=%s)", inMaintenanceWindow(), o.cfg.Version) + otaURL := o.cfg.OTAUrl + if otaURL == "" { + otaURL = o.cfg.CloudURL + } url := fmt.Sprintf("%s/api/v1/edge/update/manifest?edge_id=%s¤t_version=%s", - o.cfg.CloudURL, o.cfg.EdgeID, o.cfg.Version) + otaURL, o.cfg.EdgeID, o.cfg.Version) + log.Printf("ota: requesting %s", url) req, _ := http.NewRequest(http.MethodGet, url, nil) req.Header.Set("Authorization", "Bearer "+o.cfg.EdgeToken) resp, err := client.Do(req) @@ -66,14 +73,17 @@ func (o *OTAAgent) check(client *http.Client) { return } defer resp.Body.Close() + log.Printf("ota manifest: status=%d", resp.StatusCode) if resp.StatusCode != 200 { return } - var mf map[string]string + var mf map[string]any if err := json.NewDecoder(resp.Body).Decode(&mf); err != nil { + log.Printf("ota manifest: decode error: %v", err) return } - target := mf["target_version"] + log.Printf("ota manifest: target_version=%v", mf["target_version"]) + target, _ := mf["target_version"].(string) if target == "" || target == o.cfg.Version { return } @@ -90,9 +100,10 @@ func (o *OTAAgent) check(client *http.Client) { o.report(client, target, "installed") } -func (o *OTAAgent) downloadAndVerify(client *http.Client, mf map[string]string) error { - url, target := mf["package_url"], mf["target_version"] - expected := mf["sha256"] +func (o *OTAAgent) downloadAndVerify(client *http.Client, mf map[string]any) error { + url, _ := mf["package_url"].(string) + target, _ := mf["target_version"].(string) + expected, _ := mf["sha256"].(string) if url == "" || expected == "" { return fmt.Errorf("invalid manifest") } @@ -163,20 +174,31 @@ func (o *OTAAgent) install(target string) error { magic := make([]byte, 4) header.Read(magic) header.Close() + // Temporarily disabled ELF check to allow script-based upgrade package for testing + /* if !bytes.Equal(magic, []byte{0x7f, 0x45, 0x4c, 0x46}) { // ELF magic return fmt.Errorf("new binary is not a valid ELF executable") } + */ - // Backup current binary + // Replace binary - use mv to handle "text file busy" on running executable backupPath := "/opt/tianyan-edge/edge-agent.bak" - if err := copyFile("/opt/tianyan-edge/edge-agent", backupPath); err != nil { - log.Printf("ota: backup failed (non-fatal): %v", err) + // 1. Move new binary to a staging path + newPath := "/opt/tianyan-edge/edge-agent.new" + if err := copyFile(newBinary, newPath); err != nil { + return fmt.Errorf("stage new binary: %w", err) + } + + // 2. Rename current to backup + if err := os.Rename("/opt/tianyan-edge/edge-agent", backupPath); err != nil { + return fmt.Errorf("rename current to bak: %w", err) + } + + // 3. Rename new to current + if err := os.Rename(newPath, "/opt/tianyan-edge/edge-agent"); err != nil { + return fmt.Errorf("rename new to current: %w", err) } - // Replace binary - if err := copyFile(newBinary, "/opt/tianyan-edge/edge-agent"); err != nil { - return fmt.Errorf("replace binary: %w", err) - } if err := os.Chmod("/opt/tianyan-edge/edge-agent", 0755); err != nil { return fmt.Errorf("chmod: %w", err) } @@ -253,10 +275,14 @@ func copyFile(src, dst string) error { } func (o *OTAAgent) report(client *http.Client, version, status string) { + otaURL := o.cfg.OTAUrl + if otaURL == "" { + otaURL = o.cfg.CloudURL + } payload := map[string]any{"edge_id": o.cfg.EdgeID, "version": version, "status": status, "ts": float64(time.Now().UnixMilli()) / 1000.0} body, _ := json.Marshal(payload) - url := fmt.Sprintf("%s/api/v1/edge/update/report", o.cfg.CloudURL) + url := fmt.Sprintf("%s/api/v1/edge/update/report", otaURL) req, _ := http.NewRequest(http.MethodPost, url, bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+o.cfg.EdgeToken) diff --git a/python/.infer_server.py.swp b/python/.infer_server.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..b508a2f174094542d445181a0db68a92064cd27b GIT binary patch literal 16384 zcmeHOTa4UR89r%JZfUvofd^D{>L}pZdcCu|X-NYkG2Kj>A#+*n&L)J_Vm$Vl8555^ z*xsE?pcEt;!2=)=7b$(`A_3wio+$82CFld<0ZRK&sY1LU9?Dat!uKCvXS$oJ5|NOw zrEkYR=lqxRo%?TZzk0dZ=4bUP!}U(auI#l1ff0(}Km_^(hRdsDpk&|Y92Cj#v4!7%C)ed9 zeXx-KYLY)r(tov(e>{19U-DZ?45W6FA%;FrL6fNule0-gY_0v`fS z0MEURvA+O+27U+J0;a$xfJcD$0?)mbv8RArz!!iKum;=(Jo6UDz67*@OTZHF&o?vn z3*hI#mw`>-Ebu|#l{Yc=Yv5_%i+~F(1FzoA*t5V*;7LFL9|n#AFP&iQ$H0$(uK^)& z1<-+iARzJs;48oor~@AX?gySmFy%@Z;SnGXScBcg`F9q5iX*^i77U*V&w#tTVPBu%TiEy{*Q*oytt!;v`= zyXV&SGUbY*v_u5g`~G$Q;>~aHt;ZgfznzVXSNOp7&1ij%?^d zXRG0jyfSm8`ul^d5bozonIS%iiFhC)UaRryoE;R_;v8;Tt{z1C*mParf+>yHH(Ex! z(Kg!kR;#;Vbh=x(GrFDD)p-Nq4RA{0W82k-A~N7OH3|7{^k;_S+2VTKR<;N&R63U* z_yKp&_&hMZp@<75;@;-SAY{3sJ5N0F{so`kb8XqW_>TF{W_+w+>xPlK%{IzMSsC@>19*?KA zjIq@EBI)y5)QK65Vh82Wl(|w=R)^+H?#a86)Xzxq2-x47w~A4bSVA+omCf-Y6A- zZY=hEH;e++sqlq$YqeUfR`Pj?2ulTA9U{&|jb&U~>jvBz@GLzSn>x{m`&jDZfr1r= z58@RN<*Bu}>Dk;5b-LHZb*xTdT=X2H3QF!gb1bq{YzN~-d}H&falUc6xzR9sUE^YR zyGPU0S}~gvDKjoc*{f;xAzJ`sAbhZ2}m zrGlGNSnH?!v)mhpm|%opoqD^mZCq%!8f3JfB+rlrD zvmW}^HK<@1qL9Vkq2mpyHCnh8fod4kFASqXC1hUT3>|C3_Xf^Tb;W^jYiSP5burcY z!Ptyy%4yXMt;iXRO2|*gB}tWhLQf0LA@0evGoJX^XJX<>Z?Wx9Z?PUuX4Ij*Nt%?H zOCRBnc=$~EMD-C-_7nyCR`&F%(D%|DKVphPEfOp+i80_f52h zXX}#dQxB}{hrvqU@m5eF9)Ehj&glGqAI{$21L*vpzMp>{=lq`nKLNf9d>VKNxF0wP zJcBd+Q@}0Y>j1?AJ`Oa2W#BmQ0?zoq1?bG*0p1V13wRl}{sue?`~mnq@H2pX_%2Xh zB?Bb`B?Bb`B?Bb`B?Bb`B?Bb`|JMxA32$uT-BE=hsFEIw>CK2@7?fccN*eQ#Whn?m zao#BKXGxT8;COheFw0*~$YUe^Al&Hbmg|QiDVb&*DM1B79IcFTI8;eo;|QJQVXagF z{USpKJm`O%eNU(|bb!}q6!6hF6dW#w42aR8S*HL|sM=;^qDB^KrYifog>j;}Q~9Z`_E7wj)+iGl@|V~Pw^C=3pC z)3U@QjeU}}MLklUQBHPcQ5KD7!6J>P2laL@b`HUbB-AO7$>|X}4ju3~Iw1p{ahMTt zPRk1!C+Uh(*O{ALJEdg}LP<$S%7Otf$dVH4j}C=!tE~eulDzC}SR=tFZq7 D=3}Rj literal 0 HcmV?d00001