Makefile执行常驻命令阻塞 如何并行启动多服务后运行客户端
问题根因
原有Makefile无法按预期运行有两个核心原因:
- Make默认串行执行依赖目标,会等前一个目标的命令完全执行退出后才会运行下一个目标,而Envoy、Go服务都是常驻前台的进程,启动后不会主动退出,执行到
envoy目标时就会永久卡住,根本不会走到后续服务启动逻辑。 - 所有服务都以前台模式运行,Make会阻塞等待当前命令的进程生命周期结束,不具备并行运行的基础。
修改方案
需要做三处调整:
- 把所有常驻服务进程放到后台运行,不阻塞Make的执行流,同时把服务日志重定向到独立文件,避免输出混乱
- 开启Make的并行执行能力,让Envoy和3台Go服务可以同时启动,不需要串行等待
- 增加服务就绪等待逻辑,确保所有服务启动完成后再拉起客户端,避免客户端提前启动连接失败
修改后的完整Makefile如下:
LOG_DIR := ./logs .PHONY: envoy server1 server2 server3 loadbalancer stop # 初始化日志目录 $(LOG_DIR): mkdir -p $(LOG_DIR) # 后台启动Envoy,日志输出到logs目录 envoy: | $(LOG_DIR) envoy -c envoy.yaml > $(LOG_DIR)/envoy.log 2>&1 & # 后台启动3台Go服务,日志分别输出到对应文件 server1: | $(LOG_DIR) go run ./server1/main.go > $(LOG_DIR)/server1.log 2>&1 & server2: | $(LOG_DIR) go run ./server2/main.go > $(LOG_DIR)/server2.log 2>&1 & server3: | $(LOG_DIR) go run ./server3/main.go > $(LOG_DIR)/server3.log 2>&1 & # 所有服务依赖拉起后,等待就绪再启动客户端 loadbalancer: envoy server1 server2 server3 @echo "服务启动中,等待初始化完成..." @sleep 3 # 可根据服务实际启动速度调整等待时长,也可替换为端口探活逻辑 go run ./client/main.go # 辅助目标:一键停止所有后台启动的服务,避免残留进程占用端口 stop: pkill -f "envoy -c envoy.yaml" || true pkill -f "go run ./server1/main.go" || true pkill -f "go run ./server2/main.go" || true pkill -f "go run ./server3/main.go" || true
使用方式
启动完整流程时执行带并行参数的make命令,指定最多并行4个任务(刚好匹配4个需要同时启动的服务):
make -j4 loadbalancer
需要停止所有后台服务时执行:
make stop
补充说明
- 命令末尾的
&是Shell后台运行语法,会把进程放到后台执行,Make不需要等待进程退出就会继续推进后续流程 2>&1是把标准错误输出重定向到标准输出,统一写入日志文件,方便排查问题- 如果你不想用固定sleep等待,可以把sleep替换成端口探活逻辑,比如循环检测对应服务的监听端口是否可用,确认全部就绪后再启动客户端,可靠性更高
- 所有服务的日志都存在
./logs目录下,出问题可以直接查看对应文件定位原因
内容的提问来源于stack exchange,提问作者Chris G.
相关产品推荐
相关产品推荐

