- 并发安全:PowerManger 新增 m_stateMutex,保护 m_pmCurrentState / m_currentDisBreakerState / m_CcuColCmd / faultCode,并封装 addFaultCode/clearFaultCodes/getFaultCodes 访问器 - SystemData 新增跨线程读访问器(getDynVoltageLink/getPowerBusStatus/ getDcdcStatus/getDeviceCommonStatus 等)及配电故障码集合加锁访问 - upmsg buildMsg / httpserver pushSystemData / LowerCommManager 均改为 持锁快照,避免 listen 线程与 comm 线程撕裂读写 - 修复析构顺序:先删 httpServer 再删其他对象,避免 use-after-free - 修复 ccuState reserved2 越界读(协议预留 2 字节,结构体仅声明 1), 修正 coutMsg 中 SOC 门限/功率限制字段打印 - udpComm::sendDisSysCmd 不再吞掉异常,返回 sendMsg 实际结果并记录 ERROR, 新增 SendDisSysCmdFailsWithoutSocket 单测 - 新增 fullFeeder 全类型 UDP 集成仿真器与 fetch-data/clean-data 脚本, .gitignore 补充 SQLite 运行期文件与 fullFeeder 二进制
126 lines
5.0 KiB
Bash
Executable File
126 lines
5.0 KiB
Bash
Executable File
#!/bin/bash
|
||
#=======================================================================
|
||
# FILE: scripts/fetch-data.sh
|
||
# DESC: 从目标板卡 (RK3588 / Ubuntu 22.04) 下载数据库与日志到本地。
|
||
# 默认抓取板卡运行目录 /root/work/h100/data/ 下的:
|
||
# power_data.db (+ -wal/-shm) 主机功率数据库
|
||
# feedback_data.db 反馈落盘数据库
|
||
# pPowerManger.log 主机运行日志
|
||
# 可选 --journal 一并导出三个 systemd 服务的 journal 日志。
|
||
#
|
||
# 用法:
|
||
# ./scripts/fetch-data.sh # 下载 db + 日志到本地 data/board-<时间>/
|
||
# ./scripts/fetch-data.sh --journal # 额外导出 systemd journal
|
||
# ./scripts/fetch-data.sh --out-dir /tmp/xx # 指定本地保存目录
|
||
#
|
||
# 参数:
|
||
# --host <ip> 目标主机(默认 192.168.0.223)
|
||
# --user <user> 登录用户(默认 root)
|
||
# --board-dir <dir> 板卡部署根目录(默认 /root/work/h100)
|
||
# --out-dir <dir> 本地保存目录(默认 data/board-<时间>)
|
||
# --journal 额外导出 3 个服务的 systemd journal 日志
|
||
# -h, --help 显示帮助
|
||
#
|
||
# 前置: 板卡已配免密 SSH(见 scripts/deploy.sh setup-ssh)。
|
||
#=======================================================================
|
||
|
||
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"
|
||
OUT_DIR=""
|
||
DO_JOURNAL=0
|
||
|
||
SERVICES=(moosdb pPowerManger pPowerMangerHost)
|
||
|
||
# 板卡 data 目录下需要下载的文件(含 SQLite WAL/SHM 以保证数据完整)
|
||
DATA_FILES=(power_data.db power_data.db-wal power_data.db-shm feedback_data.db pPowerManger.log)
|
||
|
||
info() { printf '\033[1;36m[fetch-data]\033[0m %s\n' "$*"; }
|
||
ok() { printf '\033[1;32m[fetch-data]\033[0m %s\n' "$*"; }
|
||
warn() { printf '\033[1;33m[fetch-data]\033[0m %s\n' "$*"; }
|
||
err() { printf '\033[1;31m[fetch-data]\033[0m %s\n' "$*"; }
|
||
|
||
usage() {
|
||
sed -n '2,26p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
|
||
exit 0
|
||
}
|
||
|
||
#-------------------------------------------------------------------
|
||
# 参数解析
|
||
#-------------------------------------------------------------------
|
||
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 ;;
|
||
--out-dir) [ $# -ge 2 ] || { err "--out-dir 需要参数"; exit 1; }; OUT_DIR="$2"; shift 2 ;;
|
||
--journal) DO_JOURNAL=1; shift ;;
|
||
-h|--help) usage ;;
|
||
*) err "未知参数: $1(见 --help)"; exit 1 ;;
|
||
esac
|
||
done
|
||
|
||
SSH_TARGET="${USER}@${HOST}"
|
||
SSH="ssh -o BatchMode=yes -o ConnectTimeout=5"
|
||
SCP="scp -o BatchMode=yes -o ConnectTimeout=5"
|
||
|
||
#-------------------------------------------------------------------
|
||
# 1. 前置检查
|
||
#-------------------------------------------------------------------
|
||
if ! ${SSH} "${SSH_TARGET}" 'true' 2>/dev/null; then
|
||
err "无法免密 SSH 到 ${SSH_TARGET}"
|
||
err "请先执行: ./scripts/deploy.sh setup-ssh"
|
||
exit 1
|
||
fi
|
||
ok "SSH 连接正常: ${SSH_TARGET}"
|
||
|
||
if [ -z "${OUT_DIR}" ]; then
|
||
OUT_DIR="${PROJECT_ROOT}/data/board-$(date +%Y%m%d-%H%M%S)"
|
||
fi
|
||
mkdir -p "${OUT_DIR}" || { err "无法创建本地目录 ${OUT_DIR}"; exit 1; }
|
||
info "本地保存目录: ${OUT_DIR}"
|
||
|
||
#-------------------------------------------------------------------
|
||
# 2. 下载 data 目录下的数据库与日志
|
||
#-------------------------------------------------------------------
|
||
BOARD_DATA="${BOARD_DIR}/data"
|
||
missing=0
|
||
for f in "${DATA_FILES[@]}"; do
|
||
if ${SSH} "${SSH_TARGET}" "[ -f ${BOARD_DATA}/${f} ]" 2>/dev/null; then
|
||
info "下载 ${f} ..."
|
||
${SCP} -q "${SSH_TARGET}:${BOARD_DATA}/${f}" "${OUT_DIR}/" \
|
||
|| { err "下载 ${f} 失败"; exit 1; }
|
||
ok "${f}"
|
||
else
|
||
warn "板卡上不存在: ${BOARD_DATA}/${f}(跳过)"
|
||
missing=$((missing+1))
|
||
fi
|
||
done
|
||
[ "${missing}" -eq "${#DATA_FILES[@]}" ] && { err "板卡 data 目录下没有任何可下载文件"; exit 1; }
|
||
|
||
#-------------------------------------------------------------------
|
||
# 3. 可选: 导出 systemd journal
|
||
#-------------------------------------------------------------------
|
||
if [ "${DO_JOURNAL}" = "1" ]; then
|
||
for s in "${SERVICES[@]}"; do
|
||
info "导出 journal: ${s} ..."
|
||
${SSH} "${SSH_TARGET}" "journalctl --no-pager -u ${s} 2>/dev/null" > "${OUT_DIR}/${s}.journal.log" \
|
||
|| { warn "导出 ${s} journal 失败(可能无记录)"; }
|
||
ok "${s}.journal.log"
|
||
done
|
||
fi
|
||
|
||
#-------------------------------------------------------------------
|
||
# 4. 完成
|
||
#-------------------------------------------------------------------
|
||
echo ""
|
||
ok "下载完成。本地文件:"
|
||
ls -lah "${OUT_DIR}" | sed 's/^/ /'
|
||
echo ""
|
||
info "查看数据库可用: sqlite3 ${OUT_DIR}/power_data.db .tables"
|