英文:
How can I fix bad substitution error inside docker-compose file?
问题
如何在docker-compose文件中运行/bin/bash循环?
它显示错误的替换,并且我不确定是否还有其他需要转义的字符。
environment:
domains: (x.com,y.com)
entrypoint:
- /bin/sh
- -c
- |
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "/etc/letsencrypt/options-ssl-nginx.conf"
echo $$email
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "/etc/letsencrypt/ssl-dhparams.pem"
ls -la /etc/letsencrypt/
echo $$domains
for domain in $${domains[@]}; do
echo $$domain
done
英文:
How to run a /bin/bash for loop inside docker-compose file?
It's saying bad substitution error, and I'm not sure if there is another character to escape.
environment:
domains: (x.com,y.com)
entrypoint:
- /bin/sh
- -c
- |
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "/etc/letsencrypt/options-ssl-nginx.conf" echo $$email
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "/etc/letsencrypt/ssl-dhparams.pem"
ls -la /etc/letsencrypt/
echo $$domains
for domain in $${domains[@]}; do
echo $$domain
done
答案1
得分: 1
以下是您要翻译的内容:
未来,请包含足够的 docker-compose.yaml
部分,以便我们实际复制问题。我认为我知道问题出在哪里,但由于您的问题没有显示您正在使用的映像,所以只是一个基于经验的猜测。
您的 entrypoint
脚本正在使用 Bash 特定的功能(具体来说是数组)。尽管在许多 Linux 发行版上,/bin/sh
是指向 /bin/bash
的符号链接,但这并不是普遍适用的。在基于 Debian 的发行版,包括 Ubuntu,在 /bin/sh
中使用的是更传统的 Bourne-shell 实现,没有 Bash 中的额外功能。
如果在您的 docker-compose.yaml
中使用 fedora:38
,其中 /bin/sh
实际上是 Bash,它会运行而不会出错(尽管它不会按您的意图执行);循环的输出如下:
example_1 | (x.com,y.com)
另一方面,如果我使用 ubuntu:22.04
,我会得到您在问题中描述的错误:
example_1 | /bin/sh: 5: Bad substitution
为了使事情正常工作,我们首先需要处理逻辑错误 - 如上所示,当使用 Bash 时,脚本运行时不会出现错误,但实际上它不会将您的 domains
变量视为数组。
有两个问题:首先,Bash 数组语法使用空格而不是逗号来分隔项目;其次,在任何情况下,都不能将环境变量视为数组。但没关系,因为我们根本不需要数组变量!如果我们将 docker-compose.yaml
文件写成这样:
services:
example:
image: ubuntu:22.04
environment:
domains: "x.com y.com"
entrypoint:
- /bin/sh
- -c
- |
for domain in $domains; do
echo $domain
done
那么输出将是:
x.com
y.com
这正是我们想要的。这不需要任何特定于 Bash 的语法,这意味着无论使用哪个发行版,您都可以安全地使用 /bin/sh
。
英文:
In the future, please include enough of your docker-compose.yaml
for us to actually reproduce the problem. I think I know what the problem is, but because your question doesn't show what image you're using it's just an educated guess.
Your entrypoint
script is using Bash-specific features (specifically, arrays). While on many Linux distributions, /bin/sh
is a symlink to /bin/bash
, this isn't universally true. On Debian-derived distributions, including Ubuntu, /bin/sh
is a more traditional Bourne-shell implementation without the extra features available in Bash.
If use fedora:38
in your docker-compose.yaml
, in which /bin/sh
is actually Bash, it runs without errors (although it doesn't perform as you intend); the output of the loop is:
example_1 | (x.com,y.com)
On the other hand, if I use ubuntu:22.04
, I get the error you've described in your question:
example_1 | /bin/sh: 5: Bad substitution
To get things working, we first need to deal with logic error -- as we saw above, when using Bash, the script runs without an error, but it doesn't actually treat your domains
variable as an array.
There are two problems: first, Bash array syntax uses whitespace, rather than commas, to separate items; and second, you can't treat an environment variable as an array in any case. But that's okay, because we don't need an array variable at all! If we write the docker-compose.yaml
file like this:
services:
example:
image: ubuntu:22.04
environment:
domains: "x.com y.com"
entrypoint:
- /bin/sh
- -c
- |
for domain in $$domains; do
echo $$domain
done
Then the output is:
x.com
y.com
Which is what we want. This doesn't require any bash-specific syntax, which means you can safely use /bin/sh
regardless of what distribution you're using.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论