v0.18.9:collector 併進同一支執行檔——磁碟上不再攤出第二支 exe
leo 08-06 裁決:「不要兩支,寫成一支檔案」。
## 為什麼
v0.18.7-8 的「單一 exe」其實是**一支包著另一支**:collector.exe 被 go:embed
進 Arcrun.exe,執行時攤到 ~/.arcrun-rag/bin/ 再跑。
那正是防毒軟體眼中的 dropper 特徵 —— 封測者實撞
`Trojan:Win32/Sabsik.FL.A!ml`,檔案當場被隔離、自動刪除。
⚠️ 誠實界定:`!ml` 結尾=**機器學習判定**,Sabsik 是最常見的通用誤判家族,
主因是「未簽章+下載次數少」,**不是**特別指向 dropper 行為。
所以本次改動**不保證**解除誤判——真正的解是上架 MS Store(微軟簽章)。
但「執行時把第二支 PE 寫到磁碟再執行」本來就該拿掉,這是對的方向且順手變小。
## 怎麼做
- `collector/` 39 個檔 `package main` → `package collector`,`main()` → 匯出的 `Run(args) int`
- 新增 `collector/cmd/collector/`(薄殼 CLI,讓單獨跑 collector 這條路仍可用)
- App 直接 import 該套件;`main()` 第一件事就判 `--collector`,是的話走 `collector.Run` 不碰 GUI
- `supervisor` 加 `ArgPrefix`,App 把 `BinPath` 指向 `os.Executable()` 自己
- 刪掉 `bundled_collector_{windows,other}.go`(embed + 攤檔那套)
- 三支打包腳本不再編/複製第二支;版本注入同時打到兩個 package
- build-win.sh 的機械閘改成**直接問它**:`--collector --version` 回得出版本才放行
(舊閘是比大小,只能證明「有 embed」,證明不了「分派是對的」)
## 驗(真機實跑)
· `.app/Contents/MacOS/` 只有 **一個** 執行檔(原本兩個)
· 跑起來兩個行程是**同一個 exe**:
…/MacOS/arcrun-app
…/MacOS/arcrun-app --collector direct --config …
· `~/.arcrun-rag/bin` **不存在**(沒有任何東西被攤出來)
· 端到端:丟檔進看守資料夾 → collector.log `"status":"ingested","http_status":200`
· `lsappinfo` 仍是 `type="UIElement"`、`Version="0.18.9"`
· collector 39 檔測試全過;app 測試過;go vet 全綠;mac + windows 交叉編譯皆過
· 單檔 26MB → 22MB(不再夾帶第二份完整程式)
This commit is contained in:
+17
-18
@@ -13,7 +13,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -22,32 +21,31 @@ import (
|
||||
|
||||
var sup *supervisor.Supervisor
|
||||
|
||||
// collectorBinPath 找同綑的 collector 執行檔。
|
||||
// collectorBinPath 回傳「要跑哪一支執行檔當同步引擎」——答案是**我們自己**。
|
||||
//
|
||||
// 兩種同綑方式,依平台:
|
||||
// - Windows:collector **embed 在 Arcrun.exe 裡**,第一次執行攤到 ~/.arcrun-rag/bin/
|
||||
// (leo 08-06:「解開還是 2 個檔 ⇒ 應該只有 1 個檔案」)。見 bundled_collector_windows.go。
|
||||
// - macOS:放在 .app 的 Contents/MacOS/ 同層(使用者只看到一個可拖曳的 Arcrun.app)。
|
||||
// 🔴 2026-08-06 leo 裁決:「不要兩支,寫成一支檔案」。
|
||||
//
|
||||
// 內嵌攤開失敗時**退回找同層**——舊版打包出來的資料夾仍然能跑,不會因為換機制而全壞。
|
||||
// 先前兩代做法都有病:
|
||||
// ① zip 裡放兩支 exe 同層 ⇒ 使用者少拿一支就永遠不同步(leo 封測回報②)
|
||||
// ② 內嵌 collector.exe、執行時攤到磁碟再跑 ⇒ **Windows Defender 眼中的 dropper**
|
||||
// (封測者實撞:檔案「包含病毒或潛在的垃圾軟體」當場被刪)
|
||||
// 現在:collector 已改成可被引用的套件(arcrun-rag/collector.Run),
|
||||
// App 直接把它編進同一個執行檔,靠 `--collector` 參數換身分。
|
||||
// ⇒ **磁碟上永遠只有一個 exe,沒有任何東西被攤出來。**
|
||||
func collectorBinPath() string {
|
||||
if p := bundledCollectorPath(); p != "" {
|
||||
return p
|
||||
}
|
||||
name := "arcrun-collector"
|
||||
if runtime.GOOS == "windows" {
|
||||
name += ".exe"
|
||||
}
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return name
|
||||
return ""
|
||||
}
|
||||
if p, err := filepath.EvalSymlinks(exe); err == nil {
|
||||
exe = p
|
||||
}
|
||||
return filepath.Join(filepath.Dir(exe), name)
|
||||
return exe
|
||||
}
|
||||
|
||||
// collectorArgPrefix 是「把自己當 collector 跑」的參數(見 main.go 開頭的分派)。
|
||||
func collectorArgPrefix() []string { return []string{collectorModeFlag} }
|
||||
|
||||
// startSupervisor 在 App 啟動時拉起 collector;沒有 config 就先不啟動
|
||||
// (使用者還沒連知識庫,啟動只會一直失敗刷 log)。
|
||||
func startSupervisor() {
|
||||
@@ -56,8 +54,8 @@ func startSupervisor() {
|
||||
// 🔴 t195:這裡以前只 Stat(config) 就靜默 return,出問題完全查不到。
|
||||
// leo 實撞:App 活著、collector 從沒啟動、畫面卻顯示「正在整理知識卡」。
|
||||
// ⇒ 每個 return 點都要留下痕跡(寫進 collector.log 旁邊的 app.log)。
|
||||
if _, err := os.Stat(bin); err != nil {
|
||||
appLog("啟動同步引擎失敗:找不到 %s(%v)", bin, err)
|
||||
if bin == "" {
|
||||
appLog("啟動同步引擎失敗:取不到自己的執行檔路徑")
|
||||
return
|
||||
}
|
||||
if _, err := os.Stat(cfg); err != nil {
|
||||
@@ -65,6 +63,7 @@ func startSupervisor() {
|
||||
return
|
||||
}
|
||||
sup = supervisor.New(bin, cfg)
|
||||
sup.ArgPrefix = collectorArgPrefix() // 同一支執行檔,換身分跑
|
||||
sup.Start()
|
||||
appLog("同步引擎已啟動:%s", bin)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user