远程执行Bash脚本时Case分支2无法正常退出问题
问题分析与解决方案
你的脚本选项2在远程SSH执行后无法退出的核心原因是:你在选项2中启动了多个持续运行的后台进程(DConfigAgent &、TM ... &等),而SSH远程执行命令时,会等待所有属于当前会话的子进程(包括后台进程)完全结束后才会关闭连接。虽然脚本已经执行完最后一条echo语句,但那些后台服务还在运行,导致SSH会话一直处于等待状态,看起来像是脚本没有退出。
而选项1和3没有这个问题,是因为选项1没有启动长期运行的后台任务,选项3直接执行exit且无残留子进程,脚本结束后SSH就正常退出了。
具体修复步骤
你需要修改选项2中启动后台进程的逻辑,让它们完全脱离当前SSH会话,避免SSH持续等待。以下是调整后的完整代码片段:
2) e_sid="$ORACLE_SID" e_name=$(echo "$HOME" | cut -d "/" -f4) x=12000000 # 简化变量赋值,用引号包裹避免空格或特殊字符干扰 export GENEVA_FIXEDDATE="${yr}${mt}${dt} ${x}" # 优化kill逻辑:用xargs避免空值报错,无需后台执行 ps -fu "$e_name" | egrep 'TM|DConfigAgent' | tr -s " " | cut -d " " -f2 | xargs kill -9 2>/dev/null cd "$HOME/bin" dconfigadmin -L platform.cfg ## custom application # 启动DConfigAgent并彻底脱离SSH会话 nohup DConfigAgent >/dev/null 2>&1 & disown sleep 1 # 启动TM服务并彻底脱离SSH会话 nohup TM -u admin -p password -s "$e_sid" >/dev/null 2>&1 & disown sleep 2 # 简化日志处理,移除临时文件操作 last_log_dir=$(ls -lrt "$HOME/log" | awk 'END{print $NF}') last_tm_log=$(ls -lrt "$HOME/log/$last_log_dir" | awk '/^TM/{print $9}' | tail -1) tail -100 "$HOME/log/$last_log_dir/$last_tm_log" echo "execution ends here ...... I can see till this echo statement being printed" # 手动添加exit明确标记脚本正常结束(可选但更稳妥) exit 0 ;;
关键修改点说明
移除不必要的后台任务:
kill -9 $process_id &完全没必要放后台,kill命令执行极快,后台运行反而多一个子进程占用会话。改用xargs还能避免当process_id为空时执行kill -9报错。让后台进程彻底脱离会话:用
nohup ... >/dev/null 2>&1 & disown组合:nohup让进程忽略挂起信号(SIGHUP),即使SSH会话关闭也能继续运行>/dev/null 2>&1将标准输出和错误输出重定向到空设备,避免进程占用SSH的输出流disown将进程从当前shell的作业列表中移除,让SSH不再等待它结束
简化日志处理逻辑:用awk替代临时文件
aaa.txt,减少不必要的文件操作,同时避免临时文件残留问题。手动添加exit(可选):虽然脚本执行到
;;后会自动退出,但手动添加exit 0可以明确标记脚本正常结束,避免潜在的隐式问题。
通过这些修改,你的脚本选项2执行完后会立即退出,SSH会话也会正常关闭,而启动的后台服务会继续稳定运行。
内容的提问来源于stack exchange,提问作者PKB11290
相关产品推荐
相关产品推荐

