4

以下测试在 CentOS 7.1 中进行。

test.service在中创建以下文件/usr/lib/systemd/system/

[Unit]
Description=Test Bash Brace Expansion
Wants=network.target
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c "a='hello world'; echo ${a}"

[Install]
WantedBy=multi-user.target

并执行systemctl daemon-reload; systemctl restart test; systemctl status test -l

没有值的输出,因为${a}不替换为 word hello world,直到它echo ${a}变为

  1. echo $a: 工作
  2. echo $${a}: 工作

$$意味着 aa bash 中进程的 pid,但是为什么可以使用$$这个技巧ExecStart来获得这个词hello world呢?

4

1 回答 1

5

大括号与参数扩展

您所做的不是大括号扩展,而是参数扩展。大括号扩展(例如${1..5}在双引号内不起作用。

你的问题用两个 Bash shell 解释

参数扩展确实在双引号内起作用,但如果替换应该发生在被调用的 shell 而不是当前的 shell 中,则$需要引用符号。

考虑这个例子:

a='bye world' ; /bin/bash -c "a='hello world'; echo ${a}"
bye world

与这个:

a='bye world' ; /bin/bash -c "a='hello world'; echo \${a}"
hello world

将解决方案应用于 systemd 服务文件以及为什么 `$$` 有效

请务必记住,您的 systemd 服务描述文件不是在 Bash 中执行的(如上例所示),因此有一些非常相似但略有不同的规则,请参阅服务单元配置文件的文档。

您的问题是,就像上面第一个示例中的交互式 Bash 一样,systemd 正在尝试扩展${a}它在其环境中没有的。正如您已经注意到的那样,$$您的解决方案是,上面的链接解释了原因:

要传递文字美元符号,请使用“$$”。

这允许在 systemd 调用的 Bash shell 中发生参数扩展。所以配置文件中的行应该是:

ExecStart=/bin/bash -c "a='hello world'; echo $${a}"
于 2015-10-13T11:41:27.817 回答