我正在构建一个Makefile
自动启动 docker 的程序osx
。
在启动结束时,docker 需要在 shell 上启动此命令才能配置 shell:eval "$(docker-machine env dev)"
问题是,如果我尝试在 Makefile 上运行它,这对 shell 没有影响。
事实上,如果启动:
make start
然后make status
我从 docker 收到错误。
这是我的 Makefile:
CURRENT_DIRECTORY := $(shell pwd)
start:
@sh run.sh -d
@eval $(docker-machine env dev)
start-compose:
@docker-compose up -d
clean:
@docker-compose rm --force
stop:
@docker-compose stop
shutdown:
@docker-compose stop
@docker-machine stop dev
build:
@docker-compose build
status:
@docker-compose ps
cli:
@docker-compose run --rm web bash
log:
@docker-compose logs web
logall:
@docker-compose logs
restart:
@docker-compose stop web
@docker-compose start web
restartall:
@docker-compose stop
@docker-compose start
.PHONY: clean start start-compose stop status shutdown build cli log logall restart restartall
有没有办法eval "$(docker-machine env dev)"
在 Makefile 上启动命令并且会影响 shell?
答案1
如果您没有要跟踪的依赖项,Make 可能不是合适的工具。
Make 为每个命令(或某些版本中的每个规则)启动一个 shell,如果您需要配置 shell,则需要配置每个实例。
进程不可能修改其父进程。因此,如果您想让 Make 修改执行它的 shell,那么如果不使用与 docker 相同的技巧,这是不可能的。
正如
$
Make 所解释的,要将其传递到 shell,需要对其进行转义。这是一个可行的结构(请注意,我将规则合并到一个命令中),但我再次认为 Make 不是处理此类事情的正确工具,而且我对 docker 一无所知,所以我可能会错过一些相关的东西。
start: @sh run.sh -d; \ echo $$(docker-machine env dev) > ./docker-config start-compose: @eval $$(cat ./docker-config); \ docker-compose up -d clean: @eval $$(cat ./docker-config); \ docker-compose rm --force stop: @eval $$(cat ./docker-config); \ docker-compose stop shutdown: @eval $$(cat ./docker-config); \ docker-compose stop ; \ docker-machine stop dev
答案2
如果我理解这个问题,您希望 make 使用某些环境配置 shell,以便当 make 退出时,该环境仍然存在。
该eval
命令所做的是更改当前 shell,但由于您是从 make 运行它,因此它仅更改由 make 创建的子 shell,然后在调用 `eval 的 make 目标完成时销毁该子 shell。
make 被告知要运行的每一行实际上都是在它创建的 shell 中调用的。一旦从 make 返回运行的命令,该 shell 以及您在其中所做的任何更改都会消失。
您需要做的是eval
在用于调用docker
命令的 shell 中运行命令,所有操作都在同一个子 shell 中。那是,每一个需要此环境的目标运行的命令需要eval
首先调用该命令。并且您必须在同一个 shell 中运行命令,而不是为每一行运行单独的子 shell。
最简单的方法是将命令串在一起,;
以便它首先设置环境,然后运行一些 docker 命令:
status:
eval $$(docker-machine env dev); docker-compose ps
请注意双美元符号:$
是 make 中的特殊字符,您需要将其转义,$$
以便 shell 看到$
。
这是特定于制造商的版本这个答案。因此,您还可以调用脚本、我们&&
或您喜欢的任何其他内容。
或者,如果 docker 环境不是通过 make 配置或更改的(例如,您不需要根据 make 运行时变量调整环境),而是预先确定的,则可以在已设置 docker 环境的 shell 中运行 make 。那么它的每个子shell也会有相同的环境。
您使用的 make 中有某种方法可以将多行收集到同一个子 shell 中;检查你的文档。
答案3
我解决了
@eval $$(docker-machine env dev); \
docker-compose stop; \
docker-machine stop dev
在每个 make 命令中。