web-dev-qa-db-ja.com

Makefileを介してシェルにコマンドを送信する

MakefileでのDockerの起動を自動化するためにosxを構築しています。

開始の最後に、Dockerはシェルを構成するためにシェルでこのコマンドを起動する必要があります:eval "$(docker-machine env dev)"

問題は、Makefileで実行しようとしても、シェルには影響がないことです。
実際、打ち上げの場合:
_make start_次に_make status_ dockerからエラーが発生します。

これは私のメイクファイルです:

_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
_

Makefileでeval "$(docker-machine env dev)"コマンドを起動する方法はありますか?それはシェルに影響しますか?

4
Lughino
  1. 追跡する依存関係がない場合、Makeはおそらく適切なツールではありません。

  2. Makeはコマンドごとに(または一部のバージョンではルールごとに)1つのシェルを起動します。シェルを構成する必要がある場合は、各インスタンスを構成する必要があります。

  3. プロセスがその親を変更することはできません。そのため、Makeが実行されたシェルを変更したい場合は、Dockerと同じ種類のトリックを使用しないと不可能です。

  4. なので $はMakeによって解釈され、シェルに渡されるようにエスケープする必要があります。

  5. これは機能する可能性のある構造です(ルールを1つのコマンドに結合していることに注意してください)が、ここでもMakeがそのようなものに適したツールであるとは思いません。

    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
    
10
AProgrammer

質問を理解したら、シェルをいくつかの環境で構成して、exitを実行してもその環境が持続するようにする必要があります。

evalコマンドが実行していることは、現在のシェルを変更することですが、makeから実行しているため、makeによって作成されたサブシェルのみが変更され、 `evalを呼び出すmakeターゲットが完了すると破棄されます。

Makeが実行するように指示されたすべての行は、実際にそれが作成するシェルで呼び出されます。 makeから実行されたコマンドが戻ると、そのシェルは、シェルで行った変更とともに失われます。

必要なことは、evalコマンドを呼び出すために使用されるシェルでdockerコマンドをすべて同じサブシェルで実行することです。つまり、この環境を必要とするターゲットが実行するeveryコマンドは、最初にevalコマンドを呼び出す必要があります。また、コマンドをすべての行で個別のサブシェルではなく、同じシェルで実行する必要があります。

これを行う最も簡単な方法は、;を使用してコマンドを文字列化し、最初に環境を設定してから、いくつかのdockerコマンドを実行することです。

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

二重ドル記号に注意してください:$はmakeの特殊文字なので、シェルが$$を認識できるように、$としてエスケープする必要があります。

これは この答え のmake固有のバージョンです。したがって、スクリプト、または&&など、好きなものを呼び出すこともできます。

または、makeによってdocker環境が構成または変更されていない場合(たとえば、makeランタイム変数に基づいて環境を微調整する必要はない)が事前に決定されている場合は、すでにdocker環境が設定されているシェルでmakeを実行します。 。次に、そのサブシェルのそれぞれも同じ環境になります。

Makeを使用して複数の行を同じサブシェルに収集する方法がいくつかあります。ドキュメントを確認してください。

2
user156990

私は解決しました

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

各makeコマンドで。

0
Lughino