12

I'm using this in a service declaration:

ExecStartPre=/usr/bin/docker pull "$DOCKER_USERNAME/redis-replication:latest"

In the log of systemd, I can see this when I try to start the service:

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

It looks like systemd didn't execute the proper command but some weird one. What could it be and how to correct that?

Edited: Here's my entire unit file

[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"
7
  • Post the entire unit file. Commented Dec 21, 2014 at 17:05
  • I don't think you should be using quotation marks there. Commented Dec 22, 2014 at 2:52
  • 1
    I removed the quotation marks and the error is still the same. Just notice that the error is resolved if I change $DOCKER_USERNAME to ${DOCKER_USERNAME} Commented Dec 22, 2014 at 3:17
  • The underscore is probably the issue, then. Commented Dec 22, 2014 at 3:20
  • Is there a basic guidelines on how to use environment variable in systemd service file? I'm on quite some trial and error so far. Commented Dec 22, 2014 at 3:24

2 Answers 2

10

After some research around, I found that it's ok to use quote in ExecStart definition of a systemd service file. As for using shell variable, it's necessary to use curly braces to clarify where the variable name end when non-space characters is connected to the variable itself.

In the above case, the system must have treat $DOCKER_USERNAME/redis as the variable name instead of $DOCKER_USERNAME. Add a curly braces then it is interpreted correctly.

Edit: More information about what syntax is ok with systemd can be found here: http://www.freedesktop.org/software/systemd/man/systemd.service.html#Command%20lines

Basically most shell notation is ok, with the except of pipe operators.

3
  • Shouldn't this be reported with systemd? They're apparently using shell-like variable syntax but they divert from the syntax slightly, which is very likely unintentional. Commented Dec 23, 2014 at 12:01
  • 3
    Also would you please add an example of the syntax accepted by systemd so the answer is clear to casual readers that find this answer by a web search? Commented Dec 23, 2014 at 15:58
  • Thanks, I added the link where a reader could read more on systemd service file syntax. Though this question is specifically about quote and dollarsign and I think my answer already cleared it. Commented Dec 23, 2014 at 16:53
8

I've just struggled to quote and run the following command line in the ExecStart key of a service unit file:

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

I'll quote it using systemd quoting rules, and then I'll explain what I learned in the process. It appears complicated because we expect it to follow the quoting rules of POSIX shells, but in fact it's even simpler. Here's the ExecStart directive, properly quoted

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

or

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

So, the quoting rules:

  1. Enclose the string to be treated as a single argument either in single quotes (' ') or double quotes (" "). They are treated the same, it doesn't matter which one you choose, as long as the closing quote is the same as the opening quote.
  2. Scan the string from left to right, replacing ' with ', " with ", $ with $$ and % (a unit file specifier) with %%.

If you want systemd to do variable substitution, then don't quote $, but systemd doesn't treat $var and ${var} as the same. They are both replaced by the environment value of var, but word splitting will be different in each case: with $var, after replacing the value of var, the words will be split on whitespace, whereas with ${var} there will be no word splitting. Effectively, systemd treats $var as a POSIX shell would do, but it treats ${var} as a POSIX shell would treat "$var".

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.