如何在 systemd 中使用报价和美元符号

Phư*_*yễn 7 systemd

我在服务声明中使用它: ExecStartPre=/usr/bin/docker pull "$DOCKER_USERNAME/redis-replication:latest"

在systemd的日志中,当我尝试启动服务时可以看到:

Usage: docker pull [OPTIONS] NAME[:TAG]
Pull an image or a repository from the registry
-a, --all-tags=false    Download all tagged images in the repository
Run Code Online (Sandbox Code Playgroud)

看起来 systemd 没有执行正确的命令,而是执行了一些奇怪的命令。它可能是什么以及如何纠正它?

编辑:这是我的整个单元文件

[Unit]
Description=Run redis replication
After=docker.service
Requires=docker.service

[Service]
Restart=always
RestartSec=10s
EnvironmentFile=/etc/vax/credentials
EnvironmentFile=/etc/vax/centos-ip
EnvironmentFile=/etc/vax/docker-auth
EnvironmentFile=/etc/vax/cluster-prefix
ExecStartPre=-/usr/bin/docker kill redisrep
ExecStartPre=-/usr/bin/docker rm redisrep
ExecStartPre=/usr/bin/docker pull "$DOCKER_USERNAME/redis-replication:latest"
ExecStart=/usr/bin/docker run --rm --name redisrep    -v /var/data/myproject/redis:/data    -e S3_ACCESS_KEY=$S3_ACCESS_KEY    -e S3_SECRET_KEY=$S3_SECRET_KEY    -e S3_BUCKET=$S3_BUCKET    -e BACKUP_PREFIX=$BACKUP_PREFIX    -e REPLICATE_FROM_IP=$CENTOS_IP    -e REPLICATE_FROM_PORT=6379    $DOCKER_USERNAME/redis-replication:latest
ExecStop=/usr/bin/docker kill redisrep

[X-Fleet]
MachineMetadata="machineIndex=1"
Run Code Online (Sandbox Code Playgroud)

Phư*_*yễn 8

经过一番研究,我发现在 systemd 服务文件的 ExecStart 定义中使用引用是可以的。至于使用shell变量,当非空格字符连接到变量本身时,需要使用大括号来说明变量名的结尾。

在上述情况下,系统必须将$DOCKER_USERNAME/redis视为变量名称而不是$DOCKER_USERNAME。添加一个花括号然后它被正确解释。

编辑:有关 systemd 的语法的更多信息可以在这里找到:http : //www.freedesktop.org/software/systemd/man/systemd.service.html#Command%20lines

除了管道运算符之外,基本上大多数 shell 符号都可以。

  • 另外,您能否添加一个 systemd 接受的语法示例,以便通过网络搜索找到此答案的休闲读者可以清楚地了解答案? (3认同)

Pau*_*gão 5

ExecStart我只是努力在服务单元文件的键中引用并运行以下命令行:

IFS=$'\n'; f=($(ls $HOME/bk.d/DuckieTV*.backup | tail -n +2)); echo "${f[@]}"
Run Code Online (Sandbox Code Playgroud)

我将使用 systemd 引用规则来引用它,然后我将解释我在这个过程中学到的东西。它看起来很复杂,因为我们希望它遵循 POSIX shell 的引用规则,但实际上它更简单。这是ExecStart正确引用的指令

ExecStart=/bin/bash -c 'IFS=$$\'\\n\'; f=($$(ls ${HOME}/bk.d/DuckieTV*.backup | tail -n +2)); echo \"$${f[@]}\"'
Run Code Online (Sandbox Code Playgroud)

或者

ExecStart=/bin/bash -c "IFS=$$\'\\n\'; f=($$(ls ${HOME}/bk.d/DuckieTV*.backup | tail -n +2)); echo \"$${f[@]}\""
Run Code Online (Sandbox Code Playgroud)

所以,引用规则:

  1. 将要视为单个参数的字符串用单引号 ( ' ' ) 或双引号 ( " " ) 括起来。它们的待遇是一样的,无论您选择哪一个,只要收盘价与开盘价相同即可
  2. 从左到右扫描字符串,将'替换为\',将"替换为\",将$替换为$$

如果您希望 systemd 进行变量替换,则不要引用$,但 systemd 不会将$var${var}视为相同。它们都被var的环境值替换,但每种情况下的分词都会不同:使用$var ,替换var的值后,单词将在空格上分割,而使用${var}则不会出现分词。分词。实际上,systemd 将$var视为 POSIX shell 的处理方式,但将${var}视为 POSIX shell 处理"$var"的方式。