在Makefile中导出环境变量时出现问题

时间:2019-08-26 10:34:29

标签: docker makefile docker-compose

我想在Makefile中导出环境变量。在这种情况下,是要获取用于通过docker调试的IP

Makefile

start:
    export XDEBUG_REMOTE_HOST=$$(/sbin/ip route|awk '/kernel.*metric/ { print $$9 }') \
    ; docker-compose up -d

从答案更新:

version: '3.5'

services:
  php:
      build:
        context: .
        dockerfile: docker/php/Dockerfile
      environment:
        - XDEBUG_CONFIG="idekey=docker"
        - XDEBUG_REMOTE_HOST=${XDEBUG_REMOTE_HOST}

输出:

$ make start
export XDEBUG_REMOTE_HOST=$(/sbin/ip route|awk '/kernel.*metric/ { print $9 }') \
; docker-compose up -d
Starting service_php           ... done

$ docker-compose exec php bash
WARNING: The XDEBUG_REMOTE_HOST variable is not set. Defaulting to a blank string.

2 个答案:

答案 0 :(得分:2)

您需要确保变量分配和docker命令在同一shell中运行。琐碎地,将它们放在相同的规则中:

start:
    XDEBUG_REMOTE_HOST=$$(/sbin/ip route|awk '/kernel.*metric/ { print $$9 }') \
    docker-compose up -d

我拿出@是因为这可能只是个坏主意,尤其是在您需要了解此处发生的情况时。如果您不想查看make -s的运行状况,则可以使用Makefile

export的目的是将变量公开给子流程,但这不是必需的。取而代之的是,我们使用Shell的常规名称

variable=value anothervar=anothervalue command

语法,用于在单个命令的持续时间内设置变量的值。

如果docker-compose的内部要求对该变量进行export编辑,那么您当然也可以这样做:

start:
    export XDEBUG_REMOTE_HOST=$$(/sbin/ip route|awk '/kernel.*metric/ { print $$9 }') \
    ; docker-compose up -d

请注意,命令列表第一行末尾的反斜杠如何将两个命令合并到一条逻辑行上,因此它们被传递到同一shell实例,并且需要;命令分隔符终止第一个命令。 (我把分号放在行首,以提醒读​​者这是所有命令行。)

专门针对docker-compose,从命令行设置变量的惯用方式是使用特定的命名选项;

start:
    docker-compose up -e XDEBUG_REMOTE_HOST=$$(/sbin/ip route|awk '/kernel.*metric/ { print $$9 }') -d

还有其他解决方法,例如GNU Make .ONESHELL指令,但这很简单明了,可移植到任何Make。

答案 1 :(得分:0)

如果您假设在首次调用make时该路由存在,则可以分配一个make变量而不是一个shell变量,如下所示:

export XDRH_MAKE_VAR:=$(shell /sbin/ip route|awk '/kernel.*metric/ { print $$9 }')

start:
    @echo XDHR_MAKE_VAR=$(XDRH_MAKE_VAR)
    XDEBUG_REMOTE_HOST=$(XDRH_MAKE_VAR) docker-compose up -d

XDRH_FILE:
    echo $(XDRH_MAKE_VAR) > $@

someother_target:
    XDEBUG_REMOTE_HOST=$(XDRH_MAKE_VAR) some_other_command
    command_that_uses_it_as_param $(XDRH_MAKE_VAR)

NOTE_does_not_work:
    XDEBUG_REMOTE_HOST=$(XDRH_MAKE_VAR) echo $$XDEBUG_REMOTE_HOST

最后一个不起作用,因为bash shell在分配$XDEBUG_REMOTE_HOST之前会先展开bash> make start XDRH_FILE bash> XDEBUG_REMOTE_HOST=`cat XDRH_FILE` bash> docker-compose exec php bash (请参见here)。另外,该变量是在make解析时设置的,因此,如果您的任何规则影响路由,那么该变量都不会反映在其值中。

如果您以后想要访问Shell中的值,则需要执行以下操作:

import numpy as np
import cv2
import sys
import time

# name of source video and paths
video = '07-21-19-R44/C0023_1min'
input_vidpath = 'D:/Building/' + video + '.mp4'
output_vidpath = 'D:/Building/' + video + '-with3ROI.mp4'

# set ROI coordinates extrapolated from last video frame as well as fixed parameters for analysis (radius)
x1 = 1188 # in pixels
y1 = 1204 # in pixels
x2 = 952
y2 = 836
x3 = 1000
y3 = 1440
radius = 75

# set parameters for output video as identical to input
fps = 25.0

## import video
cap = cv2.VideoCapture(input_vidpath)
if cap.isOpened() == False:
    sys.exit('Video file cannot be read! Please check input_vidpath to ensure it is correctly pointing to the video file')

## Video writer class to output video
# (make sure the frame size matches size of array 'final')
# (frame shape is given as height,width , so the output needs to be re-ordered to match VideoWriter arguments)
o_height = cap.read()[1].shape[0]
o_width = cap.read()[1].shape[1]
output_framesize = (o_width,o_height) # VideoCapture.read() returns [0] boolean of operation outcome and [1] frame matrix
# mp4 codec tag (0x7634706d)
out = cv2.VideoWriter(filename = output_vidpath, fourcc = 0x7634706d, fps = fps, frameSize = output_framesize, isColor = True) # isColor: is VideoWriter expecting a colour or greyscale video

## apply ROI frame by frame and thread them back into output video
start = time.time()
f = -1
last = 0
mask = np.zeros((o_height,o_width), np.uint8)
mask = cv2.circle(mask,(x1,y1),radius,255,thickness=-1) #image, row and column coord of centre of circle, radius, color (black), thickness
mask = cv2.circle(mask,(x2,y2),radius,255,thickness=-1)
mask = cv2.circle(mask,(x3,y3),radius,255,thickness=-1)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read() #'return' value (T/F) and frame

    this = cap.get(1) # get 'CV_CAP_PROP_POS_FRAMES'
    if ret == True:

        # Apply mask to area of interest
        frame[mask ==  0] = 0

        out.write(frame)

        f += 1
        if f%1000==0:
            print(f)

    if last == this:
        break

    last = this

## When everything done, release the capture
cap.release()
out.release()
cv2.destroyAllWindows()
cv2.waitKey(1)

## End time and duration
end = time.time()
duration = end - start
print("--- %s seconds ---" %duration)
相关问题