#!/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