@@ -1,271 +0,0 @@
#!/bin/bash
#=======================================================================
# FILE: scripts/deploy.sh
# DESC: 部署 mission + 7 个 systemd 服务(moosdb / pPowerManger /
# pPowerMangerHost / pCCU / pCanBridge / pMotor / pELoad)到目标
# 板卡 (RK3588 / Ubuntu 22.04)。只安装服务 + daemon-reload,
# 默认不启动、不自启。
#
# 注意:二进制由 ./scripts/build-board.sh 在板卡原生编译并部署到
# /root/work/h100/bin/(交叉编译已移除),本脚本不再推送二进制。
#
# 用法:
# ./scripts/deploy.sh setup-ssh 一次性:生成 ed25519 key + ssh-copy-id
# ./scripts/deploy.sh 默认:推送 mission + 装 7 个
# systemd 服务 + daemon-reload(不启动)
# ./scripts/deploy.sh --start 部署后按依赖顺序启动服务
# ./scripts/deploy.sh status 板卡各服务状态
# ./scripts/deploy.sh stop 停止各服务
# ./scripts/deploy.sh help 显示帮助
#
# 参数:
# --host <ip> 目标主机(默认 192.168.0.223)
# --user <user> 登录用户(默认 root)
# --board-dir <dir> 板卡部署根目录(默认 /root/work/h100)
# --start 部署后立即启动服务
# --ccu-host <ip> 覆盖 mission 中 pPowerManger 的 CCU 地址 (ccuhost)
# --ccu-port <n> 覆盖 mission 中 pPowerManger 的 CCU 端口 (ccuport)
#
# 板卡布局:
# /root/work/h100/bin/ 二进制(由 build-board.sh 板卡编译产出)
# /root/work/h100/missions/ 板卡 mission h100.moos
# /root/work/h100/data/ 数据库存储目录 (power_data.db 等)
# /etc/systemd/system/ moosdb.service / pPowerManger.service /
# pPowerMangerHost.service / pCCU.service /
# pCanBridge.service / pMotor.service /
# pELoad.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
CCU_HOST = ""
CCU_PORT = ""
SERVICES = ( moosdb pPowerManger pPowerMangerHost pCCU pCanBridge pMotor pELoad)
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,35p' " ${ 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 ; ;
--ccu-host) [ $# -ge 2 ] || { err "--ccu-host 需要参数" ; exit 1; } ; CCU_HOST = " $2 " ; shift 2 ; ;
--ccu-port) [ $# -ge 2 ] || { err "--ccu-port 需要参数" ; exit 1; } ; CCU_PORT = " $2 " ; shift 2 ; ;
setup-ssh| status| stop| help| -h| --help) ACTION = " $1 " ; shift ; ;
"" ) shift ; ;
*) err " 未知参数: $1 (见 help) " ; exit 1 ; ;
esac
done
[ -n " ${ ACTION } " ] || ACTION = "deploy"
case " ${ CCU_PORT } " in
"" | *[ !0-9] *) [ -z " ${ CCU_PORT } " ] || { err " --ccu-port 必须是数字端口: ${ CCU_PORT } " ; exit 1; } ; ;
esac
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_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 <<EOF
[Unit]
Description=MOOSDB for H100 Power Manager
After=network.target
[Service]
Type=simple
ExecStart=${moosdb_bin} --moos_no_colour ${BOARD_DIR}/missions/h100.moos
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
}
gen_app_unit( ) {
local app = " $1 " deps = ""
[ " ${ app } " = "moosdb" ] || deps = "After=moosdb.service\nRequires=moosdb.service"
cat <<EOF
[Unit]
Description=${app} for H100 Power Manager
$(printf '%b' "${deps}")
[Service]
Type=simple
WorkingDirectory=${BOARD_DIR}/bin
ExecStart=${BOARD_DIR}/bin/${app} --alias=${app} ${BOARD_DIR}/missions/h100.moos
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
}
#-------------------------------------------------------------------
# mission 中插入/替换 "key = value"(键已存在则替换,否则插到第一个
# 顶层 '}' 之前,即 pPowerManger 配置块末尾)
#-------------------------------------------------------------------
upsert_moos_param( ) {
local f = " $1 " key = " $2 " val = " $3 "
if grep -qE " ^[[:space:]]* ${ key } [[:space:]]*= " " ${ f } " ; then
sed -i -E " s|^([[:space:]]*) ${ key } [[:space:]]*=.*|\1 ${ key } = ${ val } | " " ${ f } "
else
awk -v kv = " ${ key } = ${ val } " \
'!d && /^[[:space:]]*}[[:space:]]*$/ { print kv; d=1 } { print }' \
" ${ f } " > " ${ f } .tmp " && mv " ${ f } .tmp " " ${ f } "
fi
}
#-------------------------------------------------------------------
# 命令: deploy
#-------------------------------------------------------------------
cmd_deploy( ) {
check_ssh || return 1
[ -f " ${ PROJECT_ROOT } /missions/h100.moos " ] || { err "缺少板卡 mission: missions/h100.moos" ; return 1; }
# 1. 创建板卡目录 + 推送 mission
info " 创建板卡目录 ${ BOARD_DIR } /{bin,missions,data} ... "
${ SSH } " ${ SSH_TARGET } " " mkdir -p ${ BOARD_DIR } /bin ${ BOARD_DIR } /missions ${ BOARD_DIR } /data " || { err "创建目录失败" ; return 1; }
info "推送 mission h100.moos ..."
local mission_src = " ${ PROJECT_ROOT } /missions/h100.moos "
local mission_push = " ${ mission_src } " tmp_moos = ""
if [ -n " ${ CCU_HOST } " ] || [ -n " ${ CCU_PORT } " ] ; then
tmp_moos = " $( mktemp) "
cp " ${ mission_src } " " ${ tmp_moos } "
[ -n " ${ CCU_HOST } " ] && upsert_moos_param " ${ tmp_moos } " ccuhost " ${ CCU_HOST } "
[ -n " ${ CCU_PORT } " ] && upsert_moos_param " ${ tmp_moos } " ccuport " ${ CCU_PORT } "
mission_push = " ${ tmp_moos } "
info " CCU 地址覆盖: ccuhost= ${ CCU_HOST :- <保持原值> } ccuport= ${ CCU_PORT :- <保持原值> } "
fi
${ SCP } -q " ${ mission_push } " \
" ${ SSH_TARGET } : ${ BOARD_DIR } /missions/ " || { err "推送 mission 失败" ; [ -n " ${ tmp_moos } " ] && rm -f " ${ tmp_moos } " ; return 1; }
[ -n " ${ tmp_moos } " ] && rm -f " ${ tmp_moos } "
ok "mission 已推送(二进制由 build-board.sh 在板卡编译部署)"
# 2. 生成并安装 4 个 systemd unit
local unit
for s in " ${ SERVICES [@] } " ; do
info " 生成 ${ s } .service ... "
if [ " ${ s } " = "moosdb" ] ; then
unit = " $( gen_moosdb_unit) " || return 1
else
unit = " $( gen_app_unit " ${ s } " ) "
fi
printf '%s\n' " ${ unit } " | ${ SSH } " ${ SSH_TARGET } " " 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 pCCU pCanBridge pMotor pELoad"
echo " 浏览器: http:// ${ HOST } :18080 (上位机模拟) "
echo " http:// ${ HOST } :8090 (pPowerManger) "
echo " http:// ${ HOST } :8080 (pCCU) "
echo " http:// ${ HOST } :18082 (pELoad) "
fi
}
#-------------------------------------------------------------------
# 命令: start / status / stop
#-------------------------------------------------------------------
cmd_start( ) {
info "启动服务 (moosdb -> pPowerManger / pPowerMangerHost / pCCU / pCanBridge / pMotor / pELoad) ..."
${ SSH } " ${ SSH_TARGET } " "systemctl start moosdb && sleep 1 && \
systemctl start pPowerManger pPowerMangerHost pCCU pCanBridge pMotor pELoad" || { err "启动失败" ; return 1; }
ok "服务已启动"
cmd_status
}
cmd_status( ) {
${ SSH } " ${ SSH_TARGET } " " systemctl --no-pager status ${ SERVICES [*] } " || true
}
cmd_stop( ) {
${ SSH } " ${ SSH_TARGET } " "systemctl stop pELoad pMotor pCanBridge pPowerMangerHost pPowerManger pCCU 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