// Command bj-component-install — root-установщик компонентов bj (независимые обновления). // // bj-server работает без прав root: он скачивает подписанный манифест релиза и выбранные файлы в // каталог подготовки и просит root-воркер (bj-keymedia-worker, действие component-install) вызвать // этот инструмент. Проверка и установка — release.InstallStaged: подпись манифеста ключом из // /etc/bj/update.pub (принадлежит root), sha256 файлов, только известные компоненты, без отката, // копия прежнего файла, перезапуск служб (ядро последним), записи в /var/lib/bj/.bj/components.json. // Вывод — JSON для bj-server. // // bj-component-install <каталог подготовки> // bj-component-install -root /tmp/песочница -pub test.pub -no-restart <каталог> (проверка на копии) package main import ( "encoding/json" "flag" "fmt" "os" "git.zetit.ru/zuevav/Bridge-and-Join-s/internal/release" ) func main() { fs := flag.NewFlagSet("bj-component-install", flag.ExitOnError) root := fs.String("root", "", "корень установки (для проверки в песочнице; по умолчанию /)") pubPath := fs.String("pub", "/etc/bj/update.pub", "открытый ключ подписи релизов (base64 Ed25519), файл root") noRestart := fs.Bool("no-restart", false, "не перезапускать службы") _ = fs.Parse(os.Args[1:]) var res release.InstallResult if pub, err := release.LoadPublicKey(*pubPath); err != nil { res.Error = fmt.Sprintf("открытый ключ обновлений (%s): %v", *pubPath, err) } else { res = release.InstallStaged(fs.Arg(0), release.InstallOptions{Root: *root, PubKey: pub, Restart: !*noRestart}) } b, _ := json.Marshal(res) fmt.Println(string(b)) if !res.OK { os.Exit(1) } }