Bash中如何启动应用、读取其标准输出、执行其他操作后关闭该应用?
实现方案
你当前使用临时文件中转服务输出的方案存在临时文件残留、额外IO开销、竞态风险等问题,不需要依赖临时文件即可实现需求,以下是可直接使用的实现方式。
推荐实现(Bash 4.0+,无临时文件)
利用Bash内置的协程特性直接管理服务进程和输出管道,全程无磁盘文件操作:
#!/usr/bin/env bash set -euo pipefail # 启动服务为协程,自动建立通信管道 coproc SERVER { server 2>&1; } # 脚本异常/正常退出时自动终止服务进程 trap 'kill $SERVER_PID 2>/dev/null || true' EXIT INT TERM listen_url="" # 逐行读取服务输出,匹配到监听地址就停止读取 while IFS= read -r line <&"${SERVER[0]}"; do if [[ $line =~ (https?://[^[:space:]]+) ]]; then listen_url="${BASH_REMATCH[1]}" break fi done # 执行业务调用 run-thing --using-server="$listen_url" # 脚本执行到此处会自动触发trap清理服务进程
兼容实现(低版本Bash,无普通临时文件)
如果需要兼容3.x版本的Bash,可以用命名管道(FIFO)替代普通临时文件,不会产生残留日志文件:
#!/usr/bin/env bash set -euo pipefail # 创建临时命名管道,退出时自动清理 fifo_path=$(mktemp -u) mkfifo "$fifo_path" trap 'rm -f "$fifo_path"; kill $(jobs -p) 2>/dev/null || true' EXIT INT TERM # 后台启动服务,输出重定向到命名管道 server > "$fifo_path" 2>&1 & listen_url="" while IFS= read -r line; do if [[ $line =~ (https?://[^[:space:]]+) ]]; then listen_url="${BASH_REMATCH[1]}" break fi done < "$fifo_path" run-thing --using-server="$listen_url"
方案优势
- 无普通临时文件开销:全程通过内存管道/临时FIFO通信,不会在磁盘残留服务日志类垃圾文件
- 进程管理可靠:直接通过bash记录服务PID,trap可以精准终止服务,不会出现漏杀、错杀进程的问题
- 依赖更少:不需要调用
tail、perl等外部命令做文本匹配,用bash内置正则即可完成地址提取,环境兼容性更强 - 适配性更好:合并了服务的stderr输出流,避免部分服务将启动日志打印到错误流时提取地址失败
内容的提问来源于stack exchange,提问作者squirrel
相关产品推荐
相关产品推荐

