Makefile 如何捕获GNU make中的错误和中断?
我想知道是否有一种方法可以在GNUMakefile 如何捕获GNU make中的错误和中断?,makefile,signals,gnu-make,bash-trap,Makefile,Signals,Gnu Make,Bash Trap,我想知道是否有一种方法可以在GNUmake中实现trap,类似于BASH中内置的方法 如果用户按CTRL-C键,或者如果make本身失败(非零退出),我想调用特定的目标或宏。否。据我所知,没有此类功能。make生成返回代码。就我现在所记得的,它返回0表示成功,返回2表示失败(请查看文档)。因此,例如,将make封装在shell脚本中就足够了吗?否。gnumake的信号处理已经有很多需要改进的地方。在信号处理程序中,它调用像printf这样的函数,这些函数在信号处理程序中调用是不安全的。我发现这会
make
中实现trap
,类似于BASH
中内置的方法
如果用户按CTRL-C键,或者如果make本身失败(非零退出),我想调用特定的目标或宏。否。据我所知,没有此类功能。make生成返回代码。就我现在所记得的,它返回0表示成功,返回2表示失败(请查看文档)。因此,例如,将make封装在shell脚本中就足够了吗?否。gnumake的信号处理已经有很多需要改进的地方。在信号处理程序中,它调用像
printf
这样的函数,这些函数在信号处理程序中调用是不安全的。我发现这会导致问题,例如。如果stderr
被重定向到stdout
,则在出错时删除规则并不总是运行
例如,在CentOS 7.4机箱上:
创建以下Makefile
:
.DELETE_ON_ERROR:
foo:
touch $@
sleep 10
在vim
中打开它,然后运行:make
当它睡觉时,按Ctrl-C
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”退出时未正常清理的操作,这通常是一个令人满意的解决方案。此时,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"
.PHONY:内部目标外部目标
外部目标:
bash-c“trap”trap-SIGINT SIGTERM ERR;;退出1“SIGINT SIGTERM ERR;$(MAKE)内部目标”
内部目标:
echo“在这里做事”
它捕获中断、终止和任何非零退出代码
请注意$(MAKE)
以便将cmdline覆盖和MAKE选项传递给submake
关于陷阱:
- 清除陷阱处理程序(带-)
- 清理
- 退出状态为非零,因此生成自动化工具会报告失败的生成
例如,DELETE_ON_错误不适用于目录,因此这是在mktemp-d
之后进行清理的关键
将
替换为有效的CMD。一个简化版本的@kevinf的答案,对于基本情况来说似乎已经足够好了:
run:
bash -c "trap 'docker-compose down' EXIT; docker-compose up --build"
(这个例子有一个原因:docker compose up
确实说
什么时候
命令退出,所有容器停止
但是它不会rm
停止的容器,如docker run--rm
,因此您仍然可以使用docker ps-a
)查看它们,以了解有趣的问题,尽管您所做的听起来是个坏主意。我可以这样做,但如果可能,请尽量避免,它是独立的,我正试图保持这种方式。你有没有一些例子说明.DELETE\u ON\u ERROR
不起作用?这是make实现中的错误吗?@HakanBaba添加了详细信息。除了echo中的嵌套引号(当然是非法的)之外,这似乎不起作用,至少对于我想要实现的目标来说是这样的。一个人应该如何使用它?假设我的makefile只有一个具有睡眠和触摸的目标,如@andrewdotn示例(忽略.DELETE_ON_错误),您将如何修改它以使用此解决方法?请参阅编辑。echo“在这里做事”将是睡眠/触摸。在这里执行清理类似于,您按下ctrl-cI时仍然看到目标“运行”的方法失败。。。make:**[run]Interrupt
当我尝试此操作时,make目标不会运行docker compose down
命令。(我有这个答案中描述的确切的用例。)这确实适用于我这个确切的用例,即确保向上运行后向下运行。