From 48be5115c91f5a01d89aa51641566938bec29025 Mon Sep 17 00:00:00 2001 From: zjk <1553836110@qq.com> Date: Wed, 19 Aug 2026 14:32:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9E=84=E5=BB=BA/=E9=83=A8=E7=BD=B2=EF=BC=9A?= =?UTF-8?q?=E5=88=87=E6=8D=A2=20Ubuntu=2022.04=20=E4=BA=A4=E5=8F=89?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E7=8E=AF=E5=A2=83=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=9D=BF=E5=8D=A1=E9=83=A8=E7=BD=B2=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ci/Dockerfile:基础镜像 20.04 → 22.04(板卡实测为 Orange Pi Jammy, 旧 focal 镜像保留为 h100-power-manager-ci:arm64-focal) - scripts/build-arm64-image.sh:arm64 镜像构建(支持 --force 重建) - scripts/build-arm64.sh:日常交叉编译(产物输出 bin/arm64/,与本地隔离) - scripts/deploy.sh:板卡部署(推送二进制+mission,安装 3 个 systemd 服务) - missions/h100.moos:板卡专用 mission 配置 - .gitignore:忽略 build-arm64/、webassets_gen.h 等构建产物 --- .gitignore | 10 ++ README.md | 2 +- ci/Dockerfile | 8 +- missions/h100.moos | 22 ++++ scripts/build-arm64-image.sh | 60 +++++++++ scripts/build-arm64.sh | 42 ++++++ scripts/deploy.sh | 248 +++++++++++++++++++++++++++++++++++ 7 files changed, 388 insertions(+), 4 deletions(-) create mode 100644 missions/h100.moos create mode 100755 scripts/build-arm64-image.sh create mode 100755 scripts/build-arm64.sh create mode 100755 scripts/deploy.sh diff --git a/.gitignore b/.gitignore index 078ff44..89ae626 100644 --- a/.gitignore +++ b/.gitignore @@ -258,3 +258,13 @@ reports/ # CI test binaries (built into bin/) bin/PowerMangerTests bin/udpFeeder + +# Cross-compiled aarch64 artifacts (scripts/cross-build-local.sh) +bin/arm64/ + +# Board-native build dirs (build-arm64.sh / direct on-board builds) +build-arm64/ +build-nosa-test/ + +# CMake-generated web asset table (pPowerMangerHost) +src/pPowerMangerHost/webassets_gen.h diff --git a/README.md b/README.md index fcceb6e..0f04fa9 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ CI 在 aarch64 (QEMU) 环境下运行两类测试,**不改动任何 `src/` 生 ## 构建产物(Gitea Releases,手动部署) -CI 构建的 aarch64 二进制(RK3588 / Ubuntu 20.04)会发布到 Gitea Releases,供手动下载部署: +CI 构建的 aarch64 二进制(RK3588 / Ubuntu 22.04,板卡实测为 Orange Pi 5 Plus 的 Jammy 系统)会发布到 Gitea Releases,供手动下载部署: - **版本号 Release**:推送 `v*` tag(如 `v1.0.0`)时创建,正式版 → `https://gitea2.zhaojingkui.xyz/zjk/H100PowerManger/releases/tag/v1.0.0` diff --git a/ci/Dockerfile b/ci/Dockerfile index 57c8e72..32c0b0d 100755 --- a/ci/Dockerfile +++ b/ci/Dockerfile @@ -1,15 +1,17 @@ #======================================================================= # FILE: ci/Dockerfile -# DESC: aarch64 (RK3588 / Ubuntu 20.04) build & test environment. -# - Ubuntu 20.04 arm64 base (matches the target board) +# DESC: aarch64 (RK3588 / Ubuntu 22.04) build & test environment. +# - Ubuntu 22.04 arm64 base (matches the target board: Orange Pi 5 Plus) # - MOOS-IvP built from source and installed to /usr/local # - jsoncpp (the only extra dep used by pPowerManger) +# NOTE: Ubuntu 20.04 image kept as h100-power-manager-ci:arm64-focal +# in case the target board is later switched back to 20.04. # MOOS-IvP is cloned from the internal Gitea mirror (UUV/moos-ivp) # via a BuildKit secret (github.com is unreachable from the CN # runner). PROJ/UTM are disabled to avoid github-based CPM fetches. #======================================================================= -FROM arm64v8/ubuntu:20.04 +FROM arm64v8/ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive diff --git a/missions/h100.moos b/missions/h100.moos new file mode 100644 index 0000000..3cf1cd2 --- /dev/null +++ b/missions/h100.moos @@ -0,0 +1,22 @@ +// MOOS file +// 板卡 (RK3588 / Ubuntu 20.04) 专用 mission 配置 +// 三个 systemd 服务(moosdb / pPowerManger / pPowerMangerHost)共用本文件。 +// 由 scripts/deploy.sh 推送到板卡 /root/work/h100/missions/h100.moos + +ServerHost = localhost +ServerPort = 9000 +Community = h100 + +ProcessConfig = pPowerManger +{ + AppTick = 4 + CommsTick = 4 + log_level = INFO +} + +ProcessConfig = pPowerMangerHost +{ + AppTick = 4 + CommsTick = 4 + WEB_PORT = 18080 +} diff --git a/scripts/build-arm64-image.sh b/scripts/build-arm64-image.sh new file mode 100755 index 0000000..5789fad --- /dev/null +++ b/scripts/build-arm64-image.sh @@ -0,0 +1,60 @@ +#!/bin/bash +#======================================================================= +# FILE: scripts/build-arm64-image.sh +# DESC: 一次性构建 arm64 CI 镜像(MOOS-IvP + jsoncpp + GTest)。 +# 构建产物缓存后,日常交叉编译只需 ./scripts/build-arm64.sh。 +# +# 用法: +# CI_TOKEN=xxx ./scripts/build-arm64-image.sh # 构建(已存在则跳过) +# CI_TOKEN=xxx ./scripts/build-arm64-image.sh --force # 强制重新构建 +# +# 环境变量: +# CI_TOKEN 内网 Gitea token(拉取 moos-ivp / googletest 镜像,兼容 GITEA_TOKEN) +#======================================================================= + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "${SCRIPT_DIR}")" + +IMAGE="h100-power-manager-ci:arm64" +GITEA_TOKEN="${CI_TOKEN:-${GITEA_TOKEN:-}}" +FORCE=0 +[ "${1:-}" = "--force" ] && FORCE=1 + +if [ -z "${GITEA_TOKEN}" ]; then + echo "错误: 缺少内网 Gitea token。" >&2 + echo " 请设置: CI_TOKEN=xxx ./scripts/build-arm64-image.sh" >&2 + exit 1 +fi + +if ! command -v docker >/dev/null 2>&1; then + echo "错误: 未找到 docker" >&2 + exit 1 +fi + +if ! docker info >/dev/null 2>&1; then + echo "错误: 无法连接 docker daemon(是否需要用 sudo?)" >&2 + exit 1 +fi + +if ! docker buildx version >/dev/null 2>&1; then + echo "错误: 未找到 buildx。请安装: sudo apt-get install -y docker-buildx" >&2 + exit 1 +fi + +if [ "${FORCE}" = "0" ] && docker image inspect "${IMAGE}" >/dev/null 2>&1; then + echo ">>> 已存在镜像 ${IMAGE},跳过构建(如需重建: ${0} --force)" + exit 0 +fi +if [ "${FORCE}" = "1" ]; then + echo ">>> --force: 重新构建镜像 ${IMAGE}" +fi + +CI_TOKEN="${GITEA_TOKEN}" docker buildx build \ + --platform linux/arm64 \ + --load \ + --secret id=gitea_token,env=CI_TOKEN \ + -t "${IMAGE}" -f "${PROJECT_ROOT}/ci/Dockerfile" "${PROJECT_ROOT}" + +echo ">>> 镜像构建完成: ${IMAGE}" diff --git a/scripts/build-arm64.sh b/scripts/build-arm64.sh new file mode 100755 index 0000000..7ba6c12 --- /dev/null +++ b/scripts/build-arm64.sh @@ -0,0 +1,42 @@ +#!/bin/bash +#======================================================================= +# FILE: scripts/build-arm64.sh +# DESC: 交叉编译为 RK3588 (aarch64) / Ubuntu 22.04 二进制,用法同 build.sh。 +# 在 arm64 镜像(h100-power-manager-ci:arm64)内跑 cmake + make, +# 产物输出到 bin/arm64/,与本地 x86_64 的 bin/、build/ 互不影响。 +# +# 用法: +# ./scripts/build-arm64.sh +# +# 前置(一次性,构建 arm64 镜像): +# CI_TOKEN=xxx ./scripts/build-arm64-image.sh +#======================================================================= + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "${SCRIPT_DIR}")" + +IMAGE="h100-power-manager-ci:arm64" +JOBS="${JOBS:-$(nproc)}" + +if ! docker image inspect "${IMAGE}" >/dev/null 2>&1; then + echo "错误: 本地不存在镜像 ${IMAGE}" >&2 + echo " 请先执行: CI_TOKEN=xxx ./scripts/build-arm64-image.sh" >&2 + exit 1 +fi + +mkdir -p "${PROJECT_ROOT}/build-arm64" "${PROJECT_ROOT}/bin/arm64" + +docker run --rm --platform linux/arm64 \ + -u "$(id -u):$(id -g)" \ + -v "${PROJECT_ROOT}":/src \ + -w /src/build-arm64 \ + "${IMAGE}" \ + /bin/sh -c "cmake -DCMAKE_BUILD_TYPE=Release \ + -DEXECUTABLE_OUTPUT_PATH=/src/bin/arm64 \ + -DRUNTIME_OUTPUT_DIRECTORY=/src/bin/arm64 .. && make -j${JOBS}" + +echo "" +echo ">>> 完成。产物:" +file "${PROJECT_ROOT}/bin/arm64/pPowerManger" diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100755 index 0000000..24e841b --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,248 @@ +#!/bin/bash +#======================================================================= +# FILE: scripts/deploy.sh +# DESC: 部署 pPowerManger / pPowerMangerHost(aarch64 二进制 + mission) +# 到目标板卡 (RK3588 / Ubuntu 22.04),并用三个独立 systemd 服务 +# (moosdb / pPowerManger / pPowerMangerHost)管理。 +# 只安装服务 + daemon-reload,默认不启动、不自启。 +# +# 用法: +# ./scripts/deploy.sh setup-ssh 一次性:生成 ed25519 key + ssh-copy-id +# ./scripts/deploy.sh 默认:推送二进制 + mission + 装 3 个 +# systemd 服务 + daemon-reload(不启动) +# ./scripts/deploy.sh --start 部署后按依赖顺序启动服务 +# ./scripts/deploy.sh status 板卡 3 个服务状态 +# ./scripts/deploy.sh stop 停止 3 个服务 +# ./scripts/deploy.sh help 显示帮助 +# +# 参数: +# --host 目标主机(默认 192.168.0.223) +# --user 登录用户(默认 root) +# --board-dir 板卡部署根目录(默认 /root/work/h100) +# --start 部署后立即启动服务 +# +# 板卡布局: +# /root/work/h100/bin/ aarch64 二进制 +# /root/work/h100/missions/ 板卡 mission h100.moos +# /etc/systemd/system/ moosdb.service / pPowerManger.service / +# pPowerMangerHost.service +#======================================================================= +set -uo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "${SCRIPT_DIR}")" + +HOST="192.168.0.223" +USER="root" +BOARD_DIR="/root/work/h100" +DO_START=0 + +SERVICES=(moosdb pPowerManger pPowerMangerHost) + +info() { printf '\033[1;36m[deploy]\033[0m %s\n' "$*"; } +ok() { printf '\033[1;32m[deploy]\033[0m %s\n' "$*"; } +warn() { printf '\033[1;33m[deploy]\033[0m %s\n' "$*"; } +err() { printf '\033[1;31m[deploy]\033[0m %s\n' "$*"; } + +usage() { + sed -n '2,29p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//' + exit 0 +} + +#------------------------------------------------------------------- +# 参数解析 +#------------------------------------------------------------------- +ACTION="" +while [ $# -gt 0 ]; do + case "$1" in + --host) [ $# -ge 2 ] || { err "--host 需要参数"; exit 1; }; HOST="$2"; shift 2 ;; + --user) [ $# -ge 2 ] || { err "--user 需要参数"; exit 1; }; USER="$2"; shift 2 ;; + --board-dir)[ $# -ge 2 ] || { err "--board-dir 需要参数"; exit 1; }; BOARD_DIR="$2"; shift 2 ;; + --start) DO_START=1; shift ;; + setup-ssh|status|stop|help|-h|--help) ACTION="$1"; shift ;; + "") shift ;; + *) err "未知参数: $1(见 help)"; exit 1 ;; + esac +done +[ -n "${ACTION}" ] || ACTION="deploy" + +SSH_TARGET="${USER}@${HOST}" +SSH="ssh -o BatchMode=yes -o ConnectTimeout=5" +SCP="scp -o BatchMode=yes -o ConnectTimeout=5" + +#------------------------------------------------------------------- +# 命令: setup-ssh +#------------------------------------------------------------------- +cmd_setup_ssh() { + local key="$HOME/.ssh/id_ed25519" + if [ ! -f "${key}" ]; then + info "未发现 SSH key,生成 ed25519 key ..." + mkdir -p "$HOME/.ssh" && chmod 700 "$HOME/.ssh" + ssh-keygen -t ed25519 -N '' -f "${key}" + fi + info "上传公钥到 ${SSH_TARGET}(会提示输入密码,仅此一次)..." + ssh-copy-id -o ConnectTimeout=5 "${SSH_TARGET}" + ok "免密 SSH 已配置。验证: ssh ${SSH_TARGET}" +} + +#------------------------------------------------------------------- +# 前置检查 +#------------------------------------------------------------------- +check_local() { + local missing=0 + for b in pPowerManger pPowerMangerHost; do + if [ ! -f "${PROJECT_ROOT}/bin/arm64/${b}" ]; then + err "缺少本地 aarch64 二进制: bin/arm64/${b}(先运行 ./scripts/build-arm64.sh)"; missing=1 + elif ! file "${PROJECT_ROOT}/bin/arm64/${b}" | grep -q "aarch64"; then + err "bin/arm64/${b} 不是 aarch64 二进制"; missing=1 + fi + done + if [ ! -f "${PROJECT_ROOT}/missions/h100.moos" ]; then + err "缺少板卡 mission: missions/h100.moos"; missing=1 + fi + [ "${missing}" -eq 0 ] || return 1 + ok "本地产物校验通过 (aarch64 + mission)" +} + +check_ssh() { + if ! ${SSH} "${SSH_TARGET}" 'true' 2>/dev/null; then + err "无法免密 SSH 到 ${SSH_TARGET}" + err "请先执行: ./scripts/deploy.sh setup-ssh" + return 1 + fi + ok "SSH 连接正常: ${SSH_TARGET}" +} + +#------------------------------------------------------------------- +# 生成 systemd unit(含板卡绝对路径) +#------------------------------------------------------------------- +gen_moosdb_unit() { + # MOOSDB 路径在板卡探测;探测失败给出提示 + local moosdb_bin + moosdb_bin="$(${SSH} "${SSH_TARGET}" 'command -v MOOSDB || true' 2>/dev/null)" + if [ -z "${moosdb_bin}" ]; then + moosdb_bin="$(command -v MOOSDB || true)" + warn "板卡未在 PATH 找到 MOOSDB,回退本机路径 ${moosdb_bin:-"(未找到)"}" + [ -n "${moosdb_bin}" ] || { err "MOOSDB 路径未知,无法生成 moosdb.service"; return 1; } + fi + ok "MOOSDB 路径: ${moosdb_bin}" >&2 + + cat < /etc/systemd/system/${s}.service" + ok "${s}.service 已安装" + done + + # 3. daemon-reload(不 enable,不自启) + info "systemctl daemon-reload ..." + ${SSH} "${SSH_TARGET}" "systemctl daemon-reload && systemctl reset-failed ${SERVICES[*]} 2>/dev/null || true" + ok "服务已安装但未启用自启(systemctl is-enabled 应输出 disabled)" + + # 4. 可选启动 + if [ "${DO_START}" = "1" ]; then + cmd_start + else + echo "" + info "部署完成。手动启动(或加 --start):" + echo " systemctl start moosdb pPowerManger pPowerMangerHost" + echo " 浏览器: http://${HOST}:18080" + fi +} + +#------------------------------------------------------------------- +# 命令: start / status / stop +#------------------------------------------------------------------- +cmd_start() { + info "启动服务 (moosdb -> pPowerManger -> pPowerMangerHost) ..." + ${SSH} "${SSH_TARGET}" "systemctl start moosdb && sleep 1 && \ + systemctl start pPowerManger pPowerMangerHost" || { err "启动失败"; return 1; } + ok "服务已启动" + cmd_status +} + +cmd_status() { + ${SSH} "${SSH_TARGET}" "systemctl --no-pager status moosdb pPowerManger pPowerMangerHost" || true +} + +cmd_stop() { + ${SSH} "${SSH_TARGET}" "systemctl stop pPowerMangerHost pPowerManger moosdb" && \ + ok "服务已停止" || err "停止服务失败" +} + +#------------------------------------------------------------------- +# 命令入口 +#------------------------------------------------------------------- +case "${ACTION}" in + deploy) cmd_deploy ;; + setup-ssh) cmd_setup_ssh ;; + status) cmd_status ;; + stop) cmd_stop ;; + help|-h|--help) usage ;; + *) usage ;; +esac