Bash 如何在Makefile中为until循环编写超时函数

Bash 如何在Makefile中为until循环编写超时函数,bash,makefile,Bash,Makefile,我有下面的Makefile ready: until docker-compose logs some_svc | grep "ready"; do echo -n .; sleep 1; done 我想用一个超时函数来包装它 define check_timeout timer=0 $(1); do ((timer++)); if [[ "$$timer" == 60 ]]; then

我有下面的Makefile

ready:
    until docker-compose logs some_svc | grep "ready"; do echo -n .; sleep 1; done
我想用一个超时函数来包装它

define check_timeout
    timer=0
    $(1); do
        ((timer++));
        if [[ "$$timer" == 60 ]]; then
            exit -1
        fi
        sleep 1
    done
endef

ready:
    $(call check_timeout, until docker-compose logs some_svc | grep "ready")
但我得到了以下错误:

$ make ready
timer=0
until docker-compose logs some_svc | grep "ready."; do
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [ready] Error 2

有什么想法吗?

在你的职业生涯中,你会遇到无数关于makefile的问题。许多问题可以通过问自己以下问题来解决:

这是否需要放在Makefile中,或者将此功能放在bash脚本中并从Makefile简单调用该脚本会更容易

为了提高Makefile的可读性并简化您的生活,将此功能放入bash脚本并从Makefile调用它

生成文件 在Makefile中,我们使用
timeout
命令对要调用的脚本设置时间限制。我们还通过使用in-case-of-error
|
操作符来处理错误

ready:
    timeout 60 bash until_docker.sh || exit -1
直到docker.sh 在bash脚本中,我们实现了希望调用的功能

直到docker compose记录一些| svc | grep“就绪”;做回显。;睡眠1;

您有一些问题

第一个是make总是使用
/bin/sh
来运行菜谱。无论您的个人交互式shell是bash、zsh还是csh,它都将始终使用
/bin/sh
。在许多系统上,
/bin/sh
不是bash,而是一个基本的POSIX shell,如
dash
。脚本中的许多元素都不是有效的POSIX shell脚本。因此,如果您想要完全可移植(例如,到基于Debian/Ubuntu的系统),就不能在makefile中依赖这些bash ISM

或者,您必须明确告诉make您想要bash,包括:

SHELL := /bin/bash
当然,这在任何根本没有安装bash的系统上都会失败

其次,如果希望配方位于单个逻辑行上并传递给单个shell调用,那么将脚本放入
define
块并不能免除使用反斜杠的需要。命令之间需要分号(如
exit-1
fi
等),行的末尾需要反斜杠

这应该起作用:

define check_timeout
    timer=0; \
    $(1); do \
    timer=$$(expr $$timer + 1); \
    if [ "$$timer" = 60 ]; then \
        exit -1; \
    fi; \
    sleep 1; \
    done
endef

ready:
        $(call check_timeout, until echo ready | grep "ready")

这与其说是回答,不如说是评论。