使用nohup运行脚本时,如何将特定内容同时输出到日志与终端
解决方案
一、先修正原脚本的语法错误
原脚本存在几处语法问题,必须修正才能正常运行:
- 把大写的
While改为小写while(bash 严格区分大小写) for i "${array[@]}"改为for i in "${array[@]}"(缺少循环关键字in)pid="$!"改为pid+=("$!")(数组赋值语法错误,否则只会保留最后一个进程ID)
修正后的核心片段:
pid=() for i in "${array[@]}"; do echo starting process for "$i" script_A.sh "$i" & status_bar $! # 需要在nohup运行时将该函数输出打印到终端 pid+=("$!") done
二、让特定内容同时输出到终端和日志的两种方案
方案1:修改脚本,指定特定内容写入终端
利用 /dev/tty(当前终端设备文件),让status_bar的输出同时写入日志和终端:
方式A:用tee直接分流输出
修改status_bar函数:
status_bar(){ # 同时输出到stdout(会被nohup写入日志)和终端 printf "[" | tee -a /dev/tty while kill -0 "$1" 2>/dev/null; do printf "-" | tee -a /dev/tty sleep 1 done printf "] done!\n" | tee -a /dev/tty }
之后直接运行原nohup命令即可:
nohup myscript.sh &> file.log &
方式B:提前打开终端文件描述符(更高效)
在脚本开头添加:
# 打开终端的文件描述符3,后续直接用>&3输出到终端 exec 3>/dev/tty
然后修改status_bar函数:
status_bar(){ printf "[" printf "[" >&3 while kill -0 "$1" 2>/dev/null; do printf "-" printf "-" >&3 sleep 1 done printf "] done!\n" printf "] done!\n" >&3 }
同样运行原nohup命令,此时status_bar的内容会同时出现在终端和file.log,其他日志内容仅写入file.log。
方案2:不修改脚本,通过命令行过滤输出
如果不想改动脚本,可以在运行nohup时,用tee把所有输出写入日志,同时用grep过滤出status_bar相关内容显示在终端:
nohup myscript.sh 2>&1 | tee file.log | grep -E '\[|-|\] done!' &
2>&1:把stderr合并到stdout,确保错误信息也写入日志tee file.log:将所有输出写入日志文件grep -E '\[|-|\] done!':只过滤显示status_bar输出的[、-、] done!内容,避免终端被无关日志占满
内容的提问来源于stack exchange,提问作者Ahkam
相关产品推荐
相关产品推荐

