我正在用 nanobot 開發企業內部使用的 agent ,工作區是跟啟動和更新相關的程式碼,其他程式碼因隱私問題無法離開公司 launch_mec_agent.ps1: 啟動 agent 的程式碼 build-update-packages.ps1: 建立更新模組的程式碼 server.py: api server 的程式碼 ,會打包成 api_server.exe update_manager.py: 模組更新的程式碼 mec_updater.ps1: 模組更新的程式碼 (被 update_manager.py 取代) 目前面臨一個問題,api_server.exe 執行時會被 windows 鎖定而無法更新 ,已經嘗試讓 launch_mec_agent.ps1 , mec_updater.ps1 更新 api server 模組,但仍然無法更新,該怎麼處理
上午8:47
適用於 2m 31s
我先快速讀一下這幾個檔案的更新與啟動流程,確認目前是誰持有 api_server.exe、更新時怎麼切換檔案。這類 Windows exe 鎖定問題通常要改成「外部監督程式/延遲替換/版本目錄切換」其中一種,先看你現有架構比較適合哪個。
執行了 5 個指令
已執行 Get-Content -Path mec_updater.ps1
已執行 Get-Content -Path build-update-packages.ps1
已執行 Get-Content -Path launch_mec_agent.ps1
已執行 Get-Content -Path update_manager.py
已執行 Get-Content -Path server.py
我已經看到關鍵形狀了:update_manager.py 仍然是在 api_server.exe 裡執行更新邏輯,雖然有「defer api_server.exe」的概念,但真正替換必須發生在舊 api_server.exe 完全退出之後。現在我再抓 launcher 裡「套用 staged update」和「pending exe replace」那段,確認缺哪一步。
執行了 3 個指令
已執行 rg -n "pending|apply-staged|ApplyStaged|api_server.exe|_exe_pending|_pending_new_api" launch_mec_agent.ps1 update_manager.py mec_updater.ps1 server.py
已執行 rg -n "Start-Api|ApiServer|api_server" launch_mec_agent.ps1
已執行 rg -n "def _replace_directory_files|pending_new|exe_pending|_is_self_executable|MoveFile|replace" update_manager.py
這裡已經有相當多補丁痕跡,代表你碰到的是 Windows 更新器常見的「更新器不能更新自己」問題。現在最可疑的是流程順序:launcher 先處理 _exe_pending_replace,再執行 _pending_update;但第一次套用更新時 _exe_pending_replace 通常是在 apply 過程中才產生,所以要到「下一次啟動」才真的換 exe。
執行了 3 個指令
已執行 Get-Content -Path launch_mec_agent.ps1 -TotalCount 1405 | Select-Object -Skip 1340
已執行 Get-Content -Path launch_mec_agent.ps1 -TotalCount 1040 | Select-Object -Skip 860
已執行 Get-Content -Path update_manager.py -TotalCount 1120 | Select-Object -Skip 920
你現在遇到的核心不是 PowerShell 或 Python 語法問題,而是 Windows 的基本限制:正在執行中的 .exe 不能被覆蓋、刪除或替換。所以 api_server.exe 不能由自己更新自己,也不能在仍有 process 活著時被更新。
看你目前流程,最建議這樣處理:
-
更新動作必須由
api_server.exe外部的 updater 執行
也就是mec_updater.ps1、launcher、或獨立mec_updater.exe。不要讓api_server.exe --apply-staged成為主要路徑,因為它本身就在api_server\裡,會鎖住自己。 -
套用更新前,launcher 必須確實關掉所有
api_server.exe
不能只停 $ApiServerProcess,因為你的 launcher 有一段:
api_server already listening on port 47391 — reusing existing instance.這種情況下 $ApiServerProcess 是 $null,finally 裡不會 kill 到它。更新前建議用:
Get-Process -Name "api_server" -ErrorAction SilentlyContinue | Stop-Process -Force然後等待 process 真的消失,不是 sleep 固定 500ms/1000ms。
-
你現在的 deferred replace 順序有問題
launch_mec_agent.ps1目前是:- 啟動時先處理
_exe_pending_replace - 再處理
_pending_update
但
_exe_pending_replace通常是在ApplyStaged過程中才產生,所以這次啟動不會換到新 exe,會等下一次啟動才換。
建議:在 ApplyStaged 結束後、啟動 api_server 前,再執行一次 deferred exe replacement。 - 啟動時先處理
-
比較乾淨的設計
最穩的企業內部 agent 更新流程會是:api_server.exe只負責下載/Stage 更新,不負責套用自己- UI 呼叫
/api/update/restart server.py寫_restart_signallaunch_mec_agent.ps1收到 signal 後:- 關閉 nanobot / api_server / llama
- 等
api_server.exe完全退出 - 執行外部 updater 套用 staged zip
- 如有
_pending_new_api_server.exe,立刻覆蓋api_server\api_server.exe - 再啟動新版 agent
-
更穩的長期方案
如果你可以調整安裝結構,建議改成版本目錄:MEC_Agent\ current.txt versions\ 0.3.10\api_server\api_server.exe 0.3.11\api_server\api_server.exe launcher\launch_mec_agent.ps1更新時不要覆蓋正在跑的 exe,而是解壓到新版本資料夾,重啟時讓 launcher 改讀
current.txt指到新版。舊版等下次啟動或確認無 process 後再清。這是避開 Windows exe lock 最乾淨的方式。
你這份程式碼最小修改方向是:把 deferred exe replacement 抽成 function,啟動時跑一次,ApplyStaged 結束後再跑一次,且 apply 前用 process name/port 確實停止所有 api_server。 這樣不用大改架構,就能先解決 api_server.exe 被鎖住導致無法更新的問題。
上午8:50
代我核准
5.5中IDE 情境
本機作業本機
Comments...
No Comments Yet...