You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止Make Recipe在前置Make命令完成前执行(Hugo构建场景)

解决Make Recipe并发执行冲突的方案

要避免Make Recipe在前一次还没跑完就被重复触发,最靠谱的办法是用文件锁机制——通过一个专属的锁文件,确保同一时间只有一个构建进程在运行,具体实现如下:

1. 基础版锁机制

修改你的Makefile规则,在执行核心逻辑前先检查锁文件:

# 定义锁文件路径,选个不会和现有文件重名的即可
LOCK_FILE := .hugo-build.lock

test:
	# 检查锁文件是否存在,存在则直接退出
	@if [ -f $(LOCK_FILE) ]; then \
		printf "Error: 上一次构建仍在运行,本次执行退出\n"; \
		exit 1; \
	fi
	# 创建锁文件,占住"唯一执行"的坑位
	@touch $(LOCK_FILE)
	# 这里替换成你的Hugo构建核心逻辑
	@printf "Start run of make recipe at $$(date)\n" > demo.txt
	@sleep 30s
	@printf "\nFinish run of make recipe at $$(date)" >> demo.txt
	# 执行完成后删除锁文件,释放坑位
	@rm -f $(LOCK_FILE)

2. 增强版:处理意外中断情况

如果构建中途意外挂掉(比如进程被强行终止),锁文件会残留导致后续构建无法执行。可以给锁文件加入进程ID,执行前先验证对应进程是否真的存活:

LOCK_FILE := .hugo-build.lock

test:
	@if [ -f $(LOCK_FILE) ]; then \
		# 读取锁文件中的进程ID,检查进程是否存活
		PID=$$(cat $(LOCK_FILE)); \
		if ps -p $$PID > /dev/null 2>&1; then \
			printf "Error: 上一次构建(进程ID: $$PID)仍在运行,本次退出\n"; \
			exit 1; \
		else \
			printf "发现残留锁文件,对应进程已终止,先清理锁文件\n"; \
			rm -f $(LOCK_FILE); \
		fi \
	fi
	# 将当前进程ID写入锁文件
	@echo $$ > $(LOCK_FILE)
	# 核心构建逻辑
	@printf "Start run of make recipe at $$(date)\n" > demo.txt
	@sleep 30s
	@printf "\nFinish run of make recipe at $$(date)" >> demo.txt
	# 执行完成后删除锁文件
	@rm -f $(LOCK_FILE)

适配Git Hook场景

因为你的构建由Git Hook触发,建议把锁文件放在仓库根目录,但不要提交到Git——将锁文件名添加到.gitignore即可,确保所有Hook触发的构建都能检测到同一个锁文件。

另外注意:你之前的测试规则末尾加了&让命令后台运行,这个必须去掉!后台运行会让Make误以为命令已执行完成,锁文件会被立即删除,锁机制就失效了。

为啥之前的作业管理/wait没用?

你尝试的作业管理或wait命令解决不了问题,是因为每次make test都是独立进程,它们的作业列表相互隔离,无法感知彼此的运行状态。而文件锁是跨进程的共享状态标识,能有效阻挡并发执行请求。

内容的提问来源于stack exchange,提问作者ryanjamurphy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:57:03