0

My Makefile should and does create a file /tmp/file in the docker container using make test:

test:   
    (cd subdirectory && docker-compose exec webserver bash -c "\
        MYTEXT=hello && \
        echo 'this is $$MYTEXT world' > /tmp/file && \
        cat /tmp/file
    ")

But this doesn't work as expected. /tmp/file has content:

this is  world

But I would expect it to be

this is hello world

How to pass MYTEXT to the next command (echo)?

7
  • The single quote in your command will mean that at best you will get 'this is $MYTEXT world' in your file. The ( and ) add nothing except load to your system. Is the webserver container running, i.e. does docker exec webserver /bin/true succeed or give an error?
    – icarus
    Dec 16 '20 at 20:07
  • @icarus Yes, the container is running. How should the echo command be written instead?
    – WeSee
    Dec 16 '20 at 20:10
  • 2
    cd subdirectory && docker exec webserver bash -c 'MYTEXT=hello; echo "this is $$MYTEXT world" >/tmp/file' works for me. Note using docker rather than docker-compose and swapping the single and double quotes and removal of the ().
    – icarus
    Dec 16 '20 at 22:19
  • 1
    What have you done to debug this?  (Obvious steps include running it without Docker, running it without the redirection (so the message appears on your terminal(?)), eliminating the variable and just doing echo "hello world", eliminating the parentheses, doing the command in the terminal (outside of make), and doing everything in one line.) Do you get any output on your terminal? … … … … … … … … … … … … … … Please do not respond in comments; edit your question to make it clearer and more complete. Dec 17 '20 at 7:12
  • @G-ManSays'ReinstateMonica' modified question to make it clearer.
    – WeSee
    Dec 18 '20 at 9:19
3

make calls sh (by default, unless you change the SHELL make variable) to interpret the code (one sh invocation per line, unless you use \ at the end of each line).

Here, you want $$MYTEXT so $MYTEXT be embedded in the sh code, but you also want that $MYTEXT not to be expanded by that sh, but be passed in the bash code, so that expansion must be prevented either with \ inside the double-quotes, or use single-quotes instead of double-quotes. In any case, since you want bash to expand that $MYTEXT, you don't want $MYTEXT in the bash code to be in single-quotes.

So:

test:   
    (cd subdirectory && \
      docker-compose exec webserver bash -c '\
        MYTEXT=hello && \
        echo "this is $$MYTEXT world" > /tmp/file && \
        cat /tmp/file \
      '\
    )

If you run strace -s999 -fe execve make, you'll see (here with docker-compose exec webserver bash replaced with bash):

[pid 22370] execve("/bin/sh", ["/bin/sh", "-c", "(cd subdirectory && \\\n  exec bash -c '\\\n    MYTEXT=hello && \\\n    echo \"this is $MYTEXT world\" > /tmp/file && \\\n    cat /tmp/file \\\n  '\\\n)"], 0x555ce503e620 /* 52 vars */) = 0
strace: Process 22371 attached
[pid 22371] execve("/bin/bash", ["bash", "-c", "\\\n    MYTEXT=hello && \\\n    echo \"this is $MYTEXT world\" > /tmp/file && \\\n    cat /tmp/file \\\n  "], 0x563430f3e8f8 /* 52 vars */) = 0
[pid 22371] execve("/bin/cat", ["cat", "/tmp/file"], 0x55e9509edc10 /* 52 vars */) = 0
this is hello world

In any case, the subshell (...) is not necessary here as cd will only change the working directory of that one process running that one sh invocation, without affecting the working directory of any other shell run later on by make to run other commands.

0

Take the script and get it working outside of make.

  • run it through shellcheck
  • test it

You will find a problem with quotes.

2
  • Sorry, but it's inside the Makefile that makes things harder because make has specific rules for variable subsititution.
    – WeSee
    Dec 21 '20 at 11:41
  • Yes. And this is exactly why I say "Take the script and get it working outside of make". Trying to fix two types of error at the same time is to complex: complexity(a) × complexity(b) Dec 21 '20 at 11:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.