#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
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
Есть идеи?
Ответ №1:
У вас есть несколько проблем.
Первый заключается в том, что make всегда использует /bin/sh
для запуска рецептов. Не имеет значения, является ли ваша личная интерактивная оболочка bash, zsh или csh, она всегда будет использоваться /bin/sh
. Во многих системах /bin/sh
это не bash, а базовая оболочка POSIX dash
. Многие элементы вашего скрипта не являются допустимыми сценариями оболочки POSIX. Поэтому, если вы хотите быть переносимым (например, для систем на базе Debian / Ubuntu), вы не можете полагаться на эти bash-измы в вашем makefile.
Либо это, либо вы должны конкретно указать make, что вы хотите bash, с:
SHELL := /bin/bash
Конечно, это приведет к сбою в любой системе, которая вообще не устанавливает bash.
Во-вторых, то, что вы помещаете скрипт в 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")
Ответ №2:
В вашей карьере вы столкнетесь с бесконечными проблемами с Makefile. Многие из них можно решить, задав себе вопрос:
Должно ли это быть в Makefile, или мне было бы проще поместить эту функциональность в скрипт bash и просто вызвать этот скрипт из моего Makefile?
Чтобы улучшить читаемость ваших Make-файлов и упростить вашу жизнь, поместите эту функциональность в скрипт bash и вызовите его из вашего Makefile.
Makefile
В Makefile мы используем timeout
команду, чтобы установить ограничение по времени для скрипта, который мы хотим вызвать. Мы также обрабатываем ошибку, используя оператор in case of error ||
.
ready:
timeout 60 bash until_docker.sh || exit -1
until_docker.sh
В скрипте bash мы реализовали функциональность, которую хотим вызвать
until docker-compose logs some_svc | grep "ready"; do echo -n .; sleep 1;
Комментарии:
1. Это скорее комментарий, чем ответ.