这个变量转义在systemd单位文件中如何工作?


9

对于CoreOS上运行的服务器实例,我有一个非常简单的单位文件,可用于发现伙伴服务。单位文件如下所示:

[Unit]
Description=Discovery for frontend server (instance %i)
BindsTo=frontend@%i.service
After=frontend@%i.service

[Service]
EnvironmentFile=/etc/environment
ExecStart=/usr/bin/bash -c ' \
    while true; do \
        export PORT=$(docker port frontend%i 80 | sed s/.*://); \
        etcdctl set /services/frontend/%i "${COREOS_PRIVATE_IPV4}:$PORT" --ttl 60; \
        sleep 45; \
    done'
ExecStop=/usr/bin/etcdctl rm /services/frontend/%i

[X-Fleet]
MachineOf=frontend@%i.service

效果很好,但是花了我很多时间才能进入此阶段,因为如果我将其更改为etcdctl

etcdctl set /services/frontend/%i "${COREOS_PRIVATE_IPV4}:${PORT}" --ttl 60; \

然后它不起作用-最终设置了一个像这样的值100.45.218.3:,没有端口。在此过程中,我花费了大量时间来使用$PORT变量的不同用途,而且我不知道为什么我选择的配置有效。有一点我在脚本中有这个:

echo hi $PORT; \
echo "hi $PORT"; \
echo hi ${PORT}; \
echo "hi ${PORT}"; \

并得到了这样的日志日志:

Aug 17 01:05:07 core-01 bash[53694]: hi 32769
Aug 17 01:05:07 core-01 bash[53694]: hi 32769
Aug 17 01:05:07 core-01 bash[53694]: hi
Aug 17 01:05:07 core-01 bash[53694]: hi

本质上,我的问题是:这是怎么回事?这与我了解如何{}在bash脚本中工作有关。为什么我可以在COREOS_PRIVATE_IPV4变量上使用curlies(该变量是从导出的/etc/environment,而不是为导出的PORT

Answers:


9

这记录在systemd.service(1)中${PORT}由systemd扩展。要通过$你需要写的外壳$$,所以$${PORT}。重要的一行是这样的:

要传递文字美元符号,请使用“ $$”。其值在扩展时未知的变量被视为空字符串。


感谢那!现在这很有意义,我没有注意到变量可以由systemd代替脚本本身的执行过程来替换...
Daniel Buckmaster 2015年

1
  1. 如果PORT的内容来自其他bash变量,您将要处理该变量,indirect reference请尝试:

    ${!PORT}
  2. 我假设您确定您的外壳是Bash


感谢您的回复!1. PORT来自脚本中的一行export PORT=$(docker ...); 2. CoreOS附带bash 4.2
Daniel Buckmaster

您是否尝试${!PORT}过使用脚本?
2015年

我做了,它似乎给出了相同的结果(一个空字符串)。
丹尼尔·巴克马斯特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.