【发布时间】:2009-06-10 07:06:54
【问题描述】:
我想知道是否有办法在 GNU make 中实现 trap,类似于 BASH 中的内置方法?
如果用户按下CTRL-C,或者如果make 本身失败(非零退出),我想调用一个特定的目标或宏。
【问题讨论】:
-
+1 表示有趣的问题,即使你在做什么听起来是个坏主意。
标签: makefile signals gnu-make bash-trap
我想知道是否有办法在 GNU make 中实现 trap,类似于 BASH 中的内置方法?
如果用户按下CTRL-C,或者如果make 本身失败(非零退出),我想调用一个特定的目标或宏。
【问题讨论】:
标签: makefile signals gnu-make bash-trap
此时,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),以便 cmdline 覆盖并将 make 选项传递给 submake。
在陷阱中:
DELETE_ON_ERROR 不适用于目录,因此这是在 mktemp -d 之后清理的关键,例如
用有效的 CMD 替换 <DO CLEANUP HERE>。
【讨论】:
@kevinf 答案的简化版本,对于基本情况来说似乎已经足够好了:
run:
bash -c "trap 'docker-compose down' EXIT; docker-compose up --build"
(这个例子是有原因的:docker-compose up 确实说
什么时候 命令退出,所有容器都停止。
但它不会像docker run --rm 那样rm 停止容器,因此您仍然可以通过docker ps -a 看到它们。)
【讨论】:
recipe for target 'run' failed ... make: *** [run] Interrupt,并且make 目标没有运行docker-compose down 命令。 (我有这个答案中描述的确切用例。)
没有。 GNU make 的信号处理已经有很多不足之处了。在其信号处理程序中,它调用像 printf 这样的函数,这些函数在信号处理程序中调用是不安全的。我已经看到这会导致问题,例如,如果 stderr 被重定向到 stdout,.DELETE_ON_ERROR 规则并不总是运行。
例如,在 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 仍然存在。
【讨论】:
.DELETE_ON_ERROR 不起作用的例子吗?这是 make 实现中的错误吗?
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 脚本中就足够了吗?
【讨论】: