Make命令卡在目标阶段,如何并行运行Web服务不阻塞?
问题描述
我有一个用于两个Web服务子项目的Makefile,执行make命令时,会卡在source服务输出的“listening on port 8000”日志信息处,始终无法推进到下一个目标执行。我原本期望两个服务能够并行运行且不出现阻塞,请问是否有办法在不脱离Shell的情况下实现这种并行化?
相关代码如下:
主Makefile
.PHONY: all all: @echo "source: localhost:8000" @echo "status: localhost:5000" make -j2 sourcerun statusrun sourcerun: make -C source run statusrun: make -C status run
source子项目Makefile
# source .PHONY: run run: @echo "Starting source..." [ -d node_modules ] || $(MAKE) deps yarn run start deps: @echo "Installing dependencies..." yarn
status子项目Makefile
# status .PHONY: run run: venv ./venv/bin/python3 main.py .PHONY: venv venv: @if [ ! -d venv ]; then \ python3 -m venv venv; \ ./venv/bin/pip install -r requirements.txt; \ fi
解决方案
问题核心是你的Web服务启动命令是前台运行,会占用当前Shell进程,导致Make无法继续执行后续目标。只需将启动命令放到后台运行,就能实现并行且不阻塞的效果:
1. 修改source子项目Makefile
把yarn run start改为后台运行,可选添加日志重定向避免终端日志混乱:
# source .PHONY: run run: @echo "Starting source..." [ -d node_modules ] || $(MAKE) deps # 后台运行,将日志输出到文件,同时保留终端输出 yarn run start > source.log 2>&1 & deps: @echo "Installing dependencies..." yarn
2. 修改status子项目Makefile
同样将Python服务放到后台运行:
# status .PHONY: run run: venv # 后台运行并输出日志到文件 ./venv/bin/python3 main.py > status.log 2>&1 & .PHONY: venv venv: @if [ ! -d venv ]; then \ python3 -m venv venv; \ ./venv/bin/pip install -r requirements.txt; \ fi
3. 主Makefile优化(可选)
如果需要确认服务启动状态,或者添加停止服务的快捷目标,可以补充:
.PHONY: all stop all: @echo "source: localhost:8000" @echo "status: localhost:5000" make -j2 sourcerun statusrun # 等待2秒确保服务启动完成 @sleep 2 @echo "两个服务已在后台启动" sourcerun: make -C source run statusrun: make -C status run stop: # 根据进程名停止服务,不存在时不报错 @pkill -f "yarn run start" || true @pkill -f "python3 main.py" || true @echo "所有服务已停止"
关键说明
- 使用
&将命令放到后台运行,释放当前Shell进程,让Make可以并行执行其他目标 > source.log 2>&1是把标准输出和错误输出重定向到日志文件,避免两个服务的日志在终端混排- 如果不需要日志文件,直接用
yarn run start &和python3 main.py &即可,但终端日志会交织显示
内容的提问来源于stack exchange,提问作者sproutmaster
相关产品推荐
相关产品推荐

