300 lines
9.7 KiB
Bash
300 lines
9.7 KiB
Bash
|
|
#!/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
|
||
|
|
|