如何让just工具在首次发现错误时立即终止执行?
我搞不懂just工具的错误处理逻辑。按官方文档说明,通常命令返回非零退出状态时,执行会停止,但在CI工作流里,我们碰到just返回退出码1却继续执行的情况,导致工作流出错却显示成功。我复现了这个问题,写了如下Justfile:
run: for path in *; do \ if [ ${path} != "err" ]; then \ just ok ; \ else \ just err; \ fi ; \ done ok: echo "ok" err: cat blabla
当目录里有err、ok、ok2和Justfile文件时,执行just run会发现,触发err任务后虽然报错,但还是会继续执行后面的ok任务。请问怎么配置才能让just在首次出错时立刻终止?
原因分析
你遇到的问题是因为run任务里的循环是单个Shell命令,just只会检查整个Shell命令的最终退出码,而不会在循环内部的子命令(just err)失败时直接终止整个循环。也就是说,just err返回非零后,Shell循环本身并没有被中断,所以会继续执行后续迭代。
解决方案
有两种常用方法可以实现首次错误即终止:
方法1:在Shell循环中启用 errexit 选项
修改run任务,在循环开头添加set -e,让Shell在任何命令返回非零退出码时立即退出:
run: set -e; \ for path in *; do \ if [ ${path} != "err" ]; then \ just ok ; \ else \ just err; \ fi ; \ done
set -e会让Shell脚本在遇到第一个非零退出码的命令时立刻终止,这样just err失败后,整个循环和run任务都会停止。
方法2:手动检查子命令的退出码并中断循环
如果不想全局启用set -e,可以在调用just err后手动检查退出码,一旦失败就用exit终止整个Shell命令:
run: for path in *; do \ if [ ${path} != "err" ]; then \ just ok ; \ else \ just err; \ exit 1; # 直接退出整个Shell命令 fi ; \ done
这种方式更灵活,可以根据需要控制何时终止执行。
额外说明
需要注意的是,just的默认错误终止逻辑是针对单个任务内的顶级命令,如果任务是由多个Shell命令组成(比如用;分隔的序列),just会在第一个失败的顶级命令处终止。但你的情况是循环在一个Shell命令内部,所以需要用Shell本身的错误控制机制来实现中断。
内容的提问来源于stack exchange,提问作者wookie_on_earth

