Verwendung von Anführungszeichen und Dollarzeichen mit systemd

7

Ich verwende dies in einer Service-Deklaration: ExecStartPre=/usr/bin/docker pull "$DOCKER_USERNAME/redis-replication:latest"

Im Protokoll von systemd kann ich Folgendes sehen, wenn ich versuche, den Dienst zu starten:

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

Es sieht so aus, als hätte systemd nicht den richtigen Befehl ausgeführt, sondern einen seltsamen. Was könnte es sein und wie kann man das korrigieren?

Bearbeitet : Hier ist meine gesamte Einheitendatei

[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"
Phương Nguyễn
quelle
Veröffentlichen Sie die gesamte Einheitendatei.
Michael Hampton
Ich denke nicht, dass Sie dort Anführungszeichen verwenden sollten.
Michael Hampton
1
Ich habe die Anführungszeichen entfernt und der Fehler ist immer noch der gleiche. Beachten Sie nur, dass der Fehler behoben ist, wenn ich $ DOCKER_USERNAME in $ {DOCKER_USERNAME} ändere
Der Unterstrich ist also wahrscheinlich das Problem.
Michael Hampton
Gibt es grundlegende Richtlinien zur Verwendung von Umgebungsvariablen in der systemd-Servicedatei? Ich bin bis jetzt auf ziemlich viel Versuch und Irrtum.

Antworten:

8

Nach einigen Recherchen stellte ich fest, dass es in Ordnung ist, ein Zitat in der ExecStart-Definition einer systemd-Servicedatei zu verwenden. Bei der Verwendung von Shell-Variablen müssen geschweifte Klammern verwendet werden, um zu verdeutlichen, wo der Variablenname endet, wenn Nicht-Leerzeichen mit der Variablen selbst verbunden sind.

In dem obigen Fall muss das System $DOCKER_USERNAME/redisstattdessen als Variablennamen behandelt haben $DOCKER_USERNAME. Fügen Sie geschweifte Klammern hinzu, dann wird es richtig interpretiert.

Bearbeiten : Weitere Informationen darüber, welche Syntax mit systemd in Ordnung ist, finden Sie hier: http://www.freedesktop.org/software/systemd/man/systemd.service.html#Command%20lines

Grundsätzlich ist die meiste Shell-Notation in Ordnung, mit Ausnahme der Rohrbetreiber.

Phương Nguyễn
quelle
Sollte dies nicht mit systemd gemeldet werden? Sie verwenden anscheinend eine Shell-ähnliche Variablensyntax, weichen jedoch geringfügig von der Syntax ab, was sehr wahrscheinlich unbeabsichtigt ist.
Pavel Šimerda
3
Würden Sie bitte auch ein Beispiel für die von systemd akzeptierte Syntax hinzufügen, damit die Antwort für Gelegenheitsleser klar ist, die diese Antwort über eine Websuche finden?
Pavel Šimerda
Vielen Dank, ich habe den Link hinzugefügt, über den ein Leser mehr über die Syntax der systemd-Dienstdatei lesen kann. Obwohl es bei dieser Frage speziell um Anführungszeichen und Dollarzeichen geht und ich denke, meine Antwort hat sie bereits geklärt.
Phương Nguyễn
2

Ich habe gerade versucht, die folgende Befehlszeile im ExecStartSchlüssel einer Serviceeinheitendatei zu zitieren und auszuführen :

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

Ich zitiere es mit systemd-Zitierregeln und erkläre dann, was ich dabei gelernt habe. Es erscheint kompliziert, weil wir erwarten, dass es den Anführungsregeln von POSIX-Shells entspricht, aber tatsächlich ist es noch einfacher. Hier ist die ExecStartRichtlinie, richtig zitiert

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

oder

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

Also, die Zitierregeln:

  1. Schließen Sie die Zeichenfolge, die als einfaches Argument behandelt werden soll, entweder in einfache Anführungszeichen ( '' ) oder in doppelte Anführungszeichen ( "" ) ein. Sie werden gleich behandelt, egal für welche Sie sich entscheiden, solange das Schlusszitat mit dem Eröffnungszitat übereinstimmt
  2. Scannen Sie die Zeichenfolge von links nach rechts und ersetzen Sie ' durch \' , " durch \" und $ durch $$

Wenn systemd eine Variablensubstitution durchführen soll, zitieren Sie $ nicht , aber systemd behandelt $ var und $ {var} nicht als gleich. Sie werden beide durch den Umgebungswert von var ersetzt , aber die Wortaufteilung ist in jedem Fall unterschiedlich: Bei $ var werden die Wörter nach dem Ersetzen des Werts von var in Leerzeichen aufgeteilt, während es bei $ {var} keine gibt Wortteilung. Tatsächlich behandelt systemd $ var wie eine POSIX-Shell, aber $ {var} wie eine POSIX-Shell "$ var" .

Paulo Marcel Coelho Aragão
quelle