Files

300 lines
9.7 KiB
Bash
Raw Permalink Normal View History

2026-06-22 15:35:18 +08:00
#!/bin/bash
echo "$0"
cd "$(dirname "$(readlink -f "$0")")"
script_name=$(basename "$0")
script_dir=`pwd`
script_path=${script_dir}/${script_name}
NewLOG_FILE=/home/root/poweroad.log
POWEROAD_DEVICE=`printenv POWEROAD_DEVICE || echo ems`
## app_start.sh 需要独立运行摆脱父进程时放开
# # 检查是否已经通过 setsid 运行
# if [ -z "$SETSID_RAN" ]; then
# export SETSID_RAN=1
# echo "set to run setsid shell!"| tee -a "${NewLOG_FILE}"
# # 使用 setsid 启动一个新的会话
# setsid ${script_path} "$@" > /dev/null 2>&1 < /dev/null &
# exit $?
# fi
echo "this is run shell ${script_name} !"
# check platform
# hostname echo $HOSTNAME
if [[ $HOSTNAME =~ imx8 ]] || [[ $HOSTNAME =~ imx93evk ]]; then # imx8mpevk
APP_DIR=/home/poweroad/${POWEROAD_DEVICE}
APP_BIN_DIR=${APP_DIR}/bin
APP_LIB_DIR=/usr/poweroadlib
else # ubuntu-vm
APP_DIR=./
APP_BIN_DIR=${APP_DIR}/x86_bin
APP_LIB_DIR=${APP_DIR}/../lib/x86
source ./envsetup_EMSx86.sh
fi
echo "APP_DIR: ${APP_DIR}"
## 修改程序日志默认等级(程序启动时默认为Info(4),可在此次做启动前先设等级,即刻生效)
####### preset log level: Trace(6): [Defaut: Info(4)] [0-Off, 1-C, 2-E, 3-W, 4-I, 5-D, 6-T]
#echo 6 > /tmp/prlog/level/manage
#echo 6 > /tmp/prlog/level/logic
#echo 6 > /tmp/prlog/level/tcpcomm
#echo 6 > /tmp/prlog/level/pushcloud
#TC_XML=${APP_DIR}/config/cloud/factory_config/TerminalConfig.xml
#if [ -f ${TC_XML} ];then
# cp -rf ${TC_XML} /usr/poweroad/factory_config/
# sync
#fi
#杀死原有进程
kill_old_process() {
local process_name=$1
#
local pids=$(pgrep -f "$process_name")
echo "pids=$(pgrep -f "app_start.sh")"
echo "old process: $pids"
if [ -z "$pids" ];then
return
fi
local self_pid=$$
echo "self_pid: $self_pid"
for pid in $pids; do
if [ "$pid" -eq "$self_pid" ]; then
continue
fi
kill -15 "$pid"
echo "kill $pid"
sleep 2s
if kill -0 "$pid" > /dev/null 2>&1; then
echo "force kill $pid"
kill -9 "$pid"
fi
done
sleep 1
}
# 根据进程名杀死并重启进程
restart_process() {
local process_name=$1
local process_path=$2
# 杀死现有进程
pkill -f "$process_name" 2>/dev/null
sleep 1
# 启动新进程
$process_path &
echo "$(date '+%Y-%m-%d %H:%M:%S')] - Restarted $process_name" >> "${NewLOG_FILE}"
}
# 监控进程是否存在,不存在时重新拉起
# 支持传入多个监控目标路径
monitor_process() {
# 1. 参数检查:未传参数时提示并返回(用return而非exit,避免退出整个脚本)
if [ $# -eq 0 ]; then
echo "错误:未传入需要监控的程序路径!"
return 1 # 返回非0表示参数错误
fi
while true; do
# 2. 遍历所有传入的程序路径,为每个程序启动独立的监控子进程
for process_path in "$@"; do
# 检查路径是否存在
if [ ! -e "$process_path" ]; then
local warn_msg="$(date '+%Y-%m-%d %H:%M:%S')] - 警告:路径 $process_path 不存在,跳过监控!"
echo "$warn_msg" >> "${NewLOG_FILE}"
echo "$warn_msg"
continue
fi
# 检查是否可执行,不可执行则尝试添加执行权限
if [ ! -x "$process_path" ]; then
local chmod_msg="$(date '+%Y-%m-%d %H:%M:%S')] - 警告:路径 $process_path 不可执行,尝试添加执行权限..."
echo "$chmod_msg" >> "${NewLOG_FILE}"
echo "$chmod_msg"
# 给目标路径添加执行权限
chmod +x "$process_path" 2>/dev/null
# 再次检查,仍不可执行则跳过
if [ ! -x "$process_path" ]; then
local fail_msg="$(date '+%Y-%m-%d %H:%M:%S')] - 错误:路径 $process_path 添加执行权限失败,跳过监控!"
echo "$fail_msg" >> "${NewLOG_FILE}"
echo "$fail_msg"
continue
fi
fi
# 提取程序名(从路径中截取最后一个/后的部分)
local process_name=$(basename "$process_path")
# 检查进程是否存在(-f 匹配完整命令行,避免同名冲突)
echo "monitor process: $process_name (path: $process_path)"
if ! pgrep -f "$process_path" > /dev/null; then
# 记录日志并重启进程
local log_msg="$(date '+%Y-%m-%d %H:%M:%S')] - Process $process_name ($process_path) is not running, restarting..."
echo "$log_msg" >> "${NewLOG_FILE}"
echo "$log_msg" # 控制台也输出,便于调试
# 启动程序(后台运行,避免阻塞监控循环)
nohup "$process_path" > /dev/null 2>&1 &
fi
sleep 5
# local start_msg="$(date '+%Y-%m-%d %H:%M:%S')] - 已启动对 $process_name ($process_path) 的监控,监控进程PID: $!"
# echo "$start_msg" >> "${NewLOG_FILE}"
# echo "$start_msg"
done
sleep 10 # 每10秒检查一次(如需1分钟,改为 sleep 60)
done
# 等待所有后台监控进程(防止脚本退出后监控进程终止)
wait
}
if [ -z "`echo ${LD_LIBRARY_PATH}|grep poweroadlib`" ];then
export LD_LIBRARY_PATH=${APP_LIB_DIR}/:${LD_LIBRARY_PATH}
fi
if [ -z "`echo ${QT_PLUGIN_PATH}|grep poweroadlib`" ];then
export QT_PLUGIN_PATH=${APP_LIB_DIR}/:${QT_PLUGIN_PATH}
fi
#### 共享内存区,云升级需要保留状态,不可使用 ipcrm -a 清空
echo 'check ipcrm ...'
# 旧版本(V2200之前)升级到V2200及以上,需要增加ipcrm -a指令,首次升级运行时会自动移除
#ipcrm -a; ipcrm -a; ipcs| tee -a "${NewLOG_FILE}" # 去掉注释后只调用一次,就会被本脚本屏蔽掉
#创建量道产品sn 存储文件
touch /usr/poweroad/.productsn
# 自动移除处理
if sed -n "/^[[:space:]]*ipcrm -a*/ {p; q}" ${script_path} | grep -q .; then
sleep 1
sed -i "/^[[:space:]]*ipcrm -a/ s/^/# /" ${script_path} && sync
# 旧版本进版升级必然存在ConnectedSubTerminals.xml,新版本无从文件,不需要执行
if [ -f ${APP_DIR}/config/cloud/cloud_config/ConnectedSubTerminals.xml ];then
# 旧版本升新2200时,必须同时开启这个,其他2200以上,如需要才打开
sync; echo 'reboot -f' | tee -a "${NewLOG_FILE}"; reboot -f
echo "$(date '+%Y-%m-%d %H:%M:%S')] #ipcrm -a" | tee -a "${NewLOG_FILE}"
fi
fi
# 自动取消重启动作,下次生效,当次依赖ipcrm -a标记
if sed -n "/^[[:space:]]*sync; echo 'reboot -f'*/ {p; q}" ${script_path} | grep -q .; then
sed -i "/^[[:space:]]*sync; echo 'reboot -f'/ s/^/# /" ${script_path} && sync
echo "$(date '+%Y-%m-%d %H:%M:%S')] #sync; echo 'reboot -f'" | tee -a "${NewLOG_FILE}"
fi
## 旧版本兼容处理,如果版本号低于LIB: build version @ Jul 30 2025 v3.2.0.1的就执行期望的命令
# strings libruntime_environ.so |grep 'LIB: build version @'|head -n1
BaseV2200="v3.2.0.1"
NewCurrent=`strings /usr/poweroadlib/libruntime_environ.so |grep 'LIB: build version @'|head -n1|awk '{print $NF}'`
v2200Base=`echo "${BaseV2200}" | awk -F'[^0-9]+' '{printf "%2d%02d%02d%02d\n", $2, $3, $4, $5}'`
vCurrent=`echo ${NewCurrent} | awk -F'[^0-9]+' '{printf "%2d%02d%02d%02d\n", $2, $3, $4, $5}'`
if [ $vCurrent -lt $v2200Base ]; then
cmd="echo hello,poweroad." #"ipcs; ipcrm -a; ipcrm -a; ipcs"
echo "$(date '+%Y-%m-%d %H:%M:%S')] eval $cmd" | tee -a ${NewLOG_FILE}
eval $cmd
fi
#保证脚本的唯一性,避免脚本多个地方在执行
kill_old_process "app_start.sh"
if [ -f ./bin/DEBUG ];then
# 先启动 upgrade 进程
${APP_BIN_DIR}/upgrade &
sleep 3 # 等待 3 秒
# 现在启动 manage 和其他进程
${APP_BIN_DIR}/manage &
sleep 1
${APP_BIN_DIR}/logic &
sleep 1
if [[ $HOSTNAME =~ imx8 ]]; then # imx8mpevk
${APP_BIN_DIR}/hmi &
fi
${APP_BIN_DIR}/tcpcomm &
${APP_BIN_DIR}/uartcomm &
${APP_BIN_DIR}/cloud_interact &
${APP_BIN_DIR}/cloud_router &
sleep 1
${APP_BIN_DIR}/pushcloud &
${APP_BIN_DIR}/dataBase &
else
# 先启动 upgrade 进程
${APP_BIN_DIR}/upgrade &
# 重启 upgrade
#restart_process "upgrade" "${APP_BIN_DIR}/upgrade"
sleep 3 # 等待 3 秒
# 现在启动 manage 和其他进程
${APP_BIN_DIR}/manage &
# restart_process "manage" "${APP_BIN_DIR}/manage"
echo "monitor upgrade..."
# 记录启动的进程ID
pid=$!
# 等待一段时间,检查进程是否还在运行
sleep 10
# 设置日志文件路径
LOG_DIR=/var/poweroad
LOG_FILE=${LOG_DIR}/upgrade.log
MAX_SIZE=10485760 # 10 MB
# 检查日志文件是否存在
if [ ! -f "${LOG_FILE}" ]; then
touch "${LOG_FILE}"
chmod 644 "${LOG_FILE}"
fi
# 检查日志文件大小
LOG_SIZE=$(stat -c %s "${LOG_FILE}")
# 如果日志文件大小超过最大值,则删除最旧的一条记录
if [ ${LOG_SIZE} -gt ${MAX_SIZE} ]; then
# 读取日志文件内容
readarray -t lines < "${LOG_FILE}"
# 删除最旧的一条记录
# 只保留从第二行开始的内容
remaining_lines="${lines[@]:1}"
printf "%s\n" "${remaining_lines[@]}" > "${LOG_FILE}"
fi
# 检查进程是否还存在
if ps -p $pid > /dev/null; then
echo "$(date '+%Y-%m-%d %H:%M:%S')] The manage program works fine" >> "${LOG_FILE}"
echo "" >> ${LOG_FILE} # 添加一个空行
else
echo "$(date '+%Y-%m-%d %H:%M:%S')] The manage program exited abnormally" >> "${LOG_FILE}"
echo "" >> ${LOG_FILE} # 添加一个空行
sync
# 定义常量
UPGRADE_STATUS_FILE="/var/poweroad/upgrade_status.txt"
# 检查文件是否存在
if [ -f "$UPGRADE_STATUS_FILE" ]; then
# 文件存在,写入 "rollback"
echo "rollback" > "$UPGRADE_STATUS_FILE"
fi
fi
# 清理
wait $pid
fi
# oneshot service, keep alive here
echo "enter looong sleep..."
while true;do
monitor_process "${APP_BIN_DIR}/upgrade" "${APP_BIN_DIR}/manage"
# kill_old_process "app_start.sh"
sleep 10
done