我想知道是否有一种方法可以trap
在 GNU中实现make
,类似于内置的BASH
?
如果用户按下CTRL-C
,或者如果make
它本身失败(非零退出),我想调用一个特定的目标或宏。
目前,GNU make 还没有原生支持。
但是有一个可靠的解决方法:
.PHONY: internal-target external-target
external-target:
bash -c "trap 'trap - SIGINT SIGTERM ERR; <DO CLEANUP HERE>; exit 1' SIGINT SIGTERM ERR; $(MAKE) internal-target"
internal-target:
echo "doing stuff here"
这会捕获中断、终止和任何非零退出代码。
注意$(MAKE)
so cmdline 覆盖和 make 选项被传递给 submake。
陷阱上:
DELETE_ON_ERROR 不适用于目录,因此这是清理之后的关键mktemp -d
,例如
替换<DO CLEANUP HERE>
为有效的 CMD。
@kevinf 的答案的简化版本,对于基本情况来说似乎已经足够好了:
run:
bash -c "trap 'docker-compose down' EXIT; docker-compose up --build"
(这个例子是有原因的:docker-compose up
确实说
当命令退出时,所有容器都将停止。
但它不像rm
停止的容器那样docker run --rm
,所以你仍然可以看到它们docker ps -a
。)
不。GNU make 的信号处理已经有很多不足之处了。从它的信号处理程序中,它调用那些在信号处理程序printf
中不能安全调用的函数。我已经看到这会导致问题,例如,.DELETE_ON_ERROR
如果stderr
重定向到stdout
.
例如,在 CentOS 7.4 机器上:
创建以下内容Makefile
:
.DELETE_ON_ERROR:
foo:
touch $@
sleep 10
打开它vim
并运行:make
,
Vim/制作打印
Press ENTER or type command to continue
touch foo
sleep 10
^C
shell returned 130
Interrupt: Press ENTER or type command to continue
Make被发送了一个中断信号,但foo
仍然存在。
Make 不支持它,但是使用 BASH 技巧你可以完成类似的事情。
default: complete
complete: do_mount
echo "Do something here..."
do_mount:
mkdir -p "$(MOUNTPOINT)"
( while ps -p $$PPID >/dev/null ; do \
sleep 1 ; \
done ; \
unmount "$(MOUNTPOINT)" \
) &
mount "$(MOUNTSOURCE)" "$(MOUNTPOINT)" -o bind
“卸载”将在“制作”完成后运行。如果您尝试清理在构建期间可能发生但在“make”退出时未正常清理的操作,这通常是一个令人满意的解决方案。
没有。据我所知,没有这样的功能。
make 产生返回码。据我现在记得,它返回 0 表示成功,2 表示失败(请查看文档)。因此,例如,将 make 包装在 shell 脚本中就足够了吗?