我的 Makefile 应该并且确实/tmp/file
使用以下命令在 docker 容器中创建一个文件make test
:
test:
(cd subdirectory && docker-compose exec webserver bash -c "\
MYTEXT=hello && \
echo 'this is $$MYTEXT world' > /tmp/file && \
cat /tmp/file
")
但这并没有按预期工作。/tmp/file
有内容:
this is world
但我希望它是
this is hello world
如何将 MYTEXT 传递给下一个命令 ( echo
)?
答案1
make
调用sh
(默认情况下,除非您更改SHELL
make
变量)来解释代码(sh
每行一次调用,除非您\
在每行末尾使用)。
在这里,您希望将$$MYTEXT
so$MYTEXT
嵌入到sh
代码中,但您也希望它$MYTEXT
不被 that 扩展sh
,而是在代码中传递bash
,因此必须使用\
双引号内部或使用单引号来防止扩展双引号。无论如何,由于您想要bash
扩展该$MYTEXT
,因此您不希望$MYTEXT
在bash
代码中使用单引号。
所以:
test:
(cd subdirectory && \
docker-compose exec webserver bash -c '\
MYTEXT=hello && \
echo "this is $$MYTEXT world" > /tmp/file && \
cat /tmp/file \
'\
)
如果你运行strace -s999 -fe execve make
,你会看到(这里用docker-compose exec webserver bash
替换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
无论如何,子 shell(...)
在这里都不是必需的,因为cd
它只会更改运行该调用的一个进程的工作目录sh
,而不会影响稍后通过make
运行其他命令运行的任何其他 shell 的工作目录。
答案2
获取脚本并使其在 make 之外运行。
- 运行它
shellcheck
- 测试一下
你会发现引号有问题。