Systemctl 没有在 bash 中完美执行的 运行 命令(反引号)

Systemctl doesn't run command which is perfectly executed in bash (back quote)

问题是执行命令的结果没有正确传递到 systemctl 服务中,而在 bash 中执行这样的命令是正确的。

这是我的服务:

[Unit]
Description=Java jar which listens to Redis
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStartPre=-/usr/bin/docker stop java_redis
ExecStartPre=-/usr/bin/docker rm java_redis
ExecStart=/usr/bin/docker run --name java_redis --rm java_redis:latest --redis_host `docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge`
ExecStop=/usr/bin/docker stop -t 2 java_redis

[Install]
WantedBy=multi-user.target

如果我在bash中运行执行以下命令没有错误:

/usr/bin/docker run --name java_redis --rm java_redis:latest --redis_host `docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge`

当我在 journal 中搜索时,我发现参数没有正确传递:

Oct 08 21:04:55 mscphisprk00034 docker[1328378]: No argument is allowed: network
Oct 08 21:04:55 mscphisprk00034 docker[1328378]: org.kohsuke.args4j.CmdLineException: No argument is allowed: network
Oct 08 21:04:55 mscphisprk00034 docker[1328378]:         at org.kohsuke.args4j.CmdLineParser.parseArgument(CmdLineParser.java:509)

你能告诉我如何在 systemctl 服务中获取该参数吗?

我需要传递一个参数,它是以下命令的结果:

docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge

阅读 ExecStart= leads me to Command Lines 的文档,其中指定仅支持简单的参数解析,解决此问题的一种方法是将整个命令行包装在 shell:

ExecStart=/bin/sh -c '/usr/bin/docker run --name java_redis --rm java_redis:latest --redis_host "$(/usr/bin/docker network inspect --format="{{range .IPAM.Config}}{{.Gateway}}{{end}}" bridge)"'

请注意我如何将内部单引号更改为双引号以避免解析器混淆。

为了更好的衡量,与您对 docker 的引用保持一致是有意义的,要么将其写为完整路径,要么不写。只是避免混淆这两个引用,例如使用 /usr/bin/docker 或使用 docker.

通常也最好使用 $(...) 而不是老式的 `…`:

ExecStart=/bin/sh -c '/usr/bin/docker run ... --redis_host $(/usr/bin/docker network ...)'

并记得引用扩展以避免它经历分词和路径名扩展:

ExecStart=/bin/sh -c '/usr/bin/docker run ... --redis_host "$(/usr/bin/docker network ...)"'