Envie o comando para o shell via Makefile

1

Estou criando um Makefile para automatizar o início da janela de encaixe em osx .

No final do início, o docker requer o lançamento desse comando no shell para configurar o shell: eval "$(docker-machine env dev)"

O problema é que, se eu tentar executá-lo no Makefile, isso não terá efeito no shell.
Na verdade, se o lançamento: make start e, em seguida, make status recebo erro do docker.

Este é o meu 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

Existe uma maneira de lançar o comando eval "$(docker-machine env dev)" no Makefile e isso afetará o shell?

    
por Lughino 15.03.2016 / 12:30

3 respostas

6

  1. Se você não tem dependências para acompanhar, o Make provavelmente não é a ferramenta certa.

  2. Make lança um shell por comando (ou por regra em algumas versões), se você precisar configurar o shell, precisará configurar cada instância.

  3. Não é possível que um processo modifique seu pai. Portanto, se você quiser que o Make modifique o shell no qual ele foi executado, isso não será possível sem usar o mesmo tipo de truque do docker.

  4. Como $ é interpretado por Make, para que ele seja passado para o shell, ele precisa ser escapado.

  5. Aqui está uma estrutura que pode ser viável (note que eu combine as regras em um comando), mas novamente eu não acho que o Make é a ferramenta certa para esse tipo de coisa e eu não sei nada sobre o docker, então eu posso sentir falta algo relevante.

    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
    
por 15.03.2016 / 13:02
2

Se eu entendi a pergunta, você quer fazer para configurar um shell com algum ambiente de tal forma que quando faz saídas, esse ambiente persiste.

O que o comando eval está fazendo é alterar o shell atual, mas como você o executa do make, ele altera apenas a subshell criada pelo make, que é então destruída quando o destino do make que invoca 'eval é concluído.

Toda linha make é instruída a executar, na verdade, é invocada em um shell criado por ela. Uma vez que o comando é executado a partir do make retorna, esse shell é removido, junto com quaisquer alterações feitas nele.

O que você precisa fazer é executar o comando eval em um shell que é usado para invocar o comando docker , todos no mesmo subshell. Ou seja, o comando every que um alvo executa que precisa deste ambiente precisa invocar o comando eval primeiro. E você tem que executar os comandos no mesmo shell, em vez de um subshell separado para cada linha.

A maneira mais fácil de fazer isso é agrupar seus comandos com ; para que primeiro defina o ambiente e, em seguida, execute algum comando do docker:

status:
    eval $$(docker-machine env dev); docker-compose ps

Observe o cifrão duplo: $ é um caractere especial no make, e você precisa escapar como $$ para que o shell veja $ .

Esta é uma versão específica da esta resposta . Então, você também pode invocar um script, ou && ou qualquer outra coisa que você goste.

Ou, se o ambiente do docker não estiver configurado ou alterado por make (por exemplo, você não precisa ajustar o ambiente com base em variáveis de tempo de execução), mas estiver predeterminado, execute o make em um shell que já possui conjunto de ambiente de janela de encaixe. Então cada uma de suas subshells também terá o mesmo ambiente.

Existe alguma maneira na marca que você está usando para coletar várias linhas na mesma sub-camada; verifique sua documentação.

    
por 15.03.2016 / 13:26
0

eu resolvi com

@eval $$(docker-machine env dev); \
docker-compose stop; \
docker-machine stop dev

em cada comando make.

    
por 15.03.2016 / 14:57