如何在bash脚本内判断自身是否通过nohup运行及重启相关问题
如何在Bash脚本内验证是否通过nohup运行并实现安全自动重启
判断脚本是否由nohup启动
nohup的核心行为是忽略SIGHUP信号,以及默认将标准输入重定向到/dev/null、标准输出/错误重定向到nohup.out。结合这两个特性,可以在脚本内做精准判断:
- 检查SIGHUP信号处理:nohup启动的进程会默认忽略SIGHUP,用
trap -p SIGHUP查看当前信号规则,若输出包含'' SIGHUP则表示SIGHUP被忽略。 - 检查标准输入是否为终端:nohup会把stdin重定向到/dev/null,用
[[ -t 0 ]]判断,返回false(退出码非0)则说明stdin不是终端。
封装成判断函数的代码:
is_nohup() { # 同时满足SIGHUP被忽略、stdin非终端两个条件 trap -p SIGHUP | grep -q "'' SIGHUP" && ! [[ -t 0 ]] }
注意:如果你的脚本自身手动设置了
trap '' SIGHUP或重定向了stdin,需要根据自身逻辑调整判断条件。
为什么你之前的方法无效
jobs -l是当前shell的内置命令,脚本运行在独立子shell中,无法访问父shell的作业列表,因此不可用。/proc/[PID]/fd和ps aux只能看到IO重定向或进程状态,但无法区分是nohup触发的重定向还是用户手动执行的,无法精准判断是否由nohup启动。
实现安全的自动重启(避免重复nohup)
不要在脚本内嵌套调用nohup,而是在脚本开头先判断当前环境是否符合nohup运行条件:若不符合,就用nohup重启自己并退出;若符合,直接执行业务逻辑。
示例完整脚本:
#!/bin/bash # 判断是否处于nohup环境 is_nohup() { trap -p SIGHUP | grep -q "'' SIGHUP" && ! [[ -t 0 ]] } # 非nohup启动时自动重启 if ! is_nohup; then echo "当前未通过nohup启动,将自动切换到nohup模式..." nohup "$0" "$@" > ./script_run.log 2>&1 & exit 0 fi # ------------------- 业务逻辑区域 ------------------- echo "脚本以nohup模式启动,PID: $$" while true; do echo "业务运行中... $(date)" sleep 30 # 若需在运行中重启,直接用exec替换当前进程(无需再次调用nohup) # if [ 触发重启的条件 ]; then # exec "$0" "$@" # fi done
关键细节
- 用
exec "$0" "$@"替代直接调用脚本,可避免进程嵌套,保持PID链清晰。 - 运行中重启时无需再次调用nohup,因为当前已经处于nohup环境中。
- 可自行调整输出日志的路径,不必局限于默认的
nohup.out。
内容的提问来源于stack exchange,提问作者Ardavan Sh
相关产品推荐
相关产品推荐

