如何让Makefile等待脚本中的后台进程执行完成?
问题背景
现有如下Makefile内容:
MAKEFLAGS += -s SHELL := /bin/bash all: $(MAKE) step1 $(MAKE) -j 2 step2 step3 $(MAKE) step4 step1: $(MAKE) step1_execute step1_execute: echo "Running step 1..." ./createFileWithTime.sh output/step1_output echo "step1 completed." step2: $(MAKE) step2_execute step2_execute: echo "Running step 2..." ./createFileWithTime.sh output/step2_output echo "step2 completed." step3: $(MAKE) step3_execute step3_execute: echo "Running step 3..." ./createFileWithTime.sh output/step3_output echo "step3 completed." step4: $(MAKE) step4_execute step4_execute: echo "Running step 4..." ./createFileWithTime.sh output/step4_output echo "step4 completed."
配套的createFileWithTime.sh脚本内容如下:
#!/bin/bash if [ -z "$1" ]; then echo "Usage: $0 <filename>" exit 1 fi file_path="$1" dir_name=$(dirname "$file_path") if [ ! -d "$dir_name" ]; then mkdir -p "$dir_name" fi current_date=$(date +"%Y-%m-%d %H:%M:%S.%N") echo "$current_date" > "$file_path" sleep 3 & echo "File '$file_path' created with current date and time: $current_date"
问题在于脚本里用后台方式执行sleep 3,导致Makefile不等脚本的所有进程跑完就继续执行后续步骤。比如跑make all时,输出文件的生成没有预期的3秒延迟。
要求:不能修改脚本本身,必须保留<step_name>和<step_name>_execute的组合目标结构,也不能指定依赖,怎么让Makefile等脚本里的所有命令(包括后台启动的进程)执行完再继续?
解决方案
核心是让Makefile在执行脚本后,等待脚本启动的所有后台子进程完成。可以把脚本执行和wait命令放在同一个子shell里,这样wait会等子shell内的所有后台进程结束,Makefile才会继续往下走。
修改后的Makefile如下:
MAKEFLAGS += -s SHELL := /bin/bash all: $(MAKE) step1 $(MAKE) -j 2 step2 step3 $(MAKE) step4 step1: $(MAKE) step1_execute step1_execute: echo "Running step 1..." (./createFileWithTime.sh output/step1_output; wait) echo "step1 completed." step2: $(MAKE) step2_execute step2_execute: echo "Running step 2..." (./createFileWithTime.sh output/step2_output; wait) echo "step2 completed." step3: $(MAKE) step3_execute step3_execute: echo "Running step 3..." (./createFileWithTime.sh output/step3_output; wait) echo "step3 completed." step4: $(MAKE) step4_execute step4_execute: echo "Running step 4..." (./createFileWithTime.sh output/step4_output; wait) echo "step4 completed."
原理说明
- 括号
()会启动一个新的bash子shell,脚本在这个子shell里运行,它启动的后台sleep进程属于这个子shell的子进程。 - 子shell里的
wait命令会默认等待所有后台子进程执行完毕,之后子shell才会退出。 - 这样Makefile会等整个子shell执行完成(包括后台
sleep的3秒),再执行后续的提示语句和其他步骤。
内容的提问来源于stack exchange,提问作者Heimish
相关产品推荐
相关产品推荐

