Wie funktioniert das Entkommen dieser Variablen in einer systemd-Einheitendatei?

9

Ich habe eine ziemlich einfache Unit-Datei für einen Discovery-Sidekick-Dienst für eine Serverinstanz, die ich unter CoreOS ausführe. Die Einheitendatei sieht folgendermaßen aus:

[Unit]
Description=Discovery for frontend server (instance %i)
BindsTo=frontend@%i.service
After=frontend@%i.service

[Service]
EnvironmentFile=/etc/environment
ExecStart=/usr/bin/bash -c ' \
    while true; do \
        export PORT=$(docker port frontend%i 80 | sed s/.*://); \
        etcdctl set /services/frontend/%i "${COREOS_PRIVATE_IPV4}:$PORT" --ttl 60; \
        sleep 45; \
    done'
ExecStop=/usr/bin/etcdctl rm /services/frontend/%i

[X-Fleet]
MachineOf=frontend@%i.service

Das funktioniert gut, aber ich habe ewig gebraucht, um zu diesem Stadium zu gelangen, denn wenn ich die etcdctlZeile dahingehend ändere :

etcdctl set /services/frontend/%i "${COREOS_PRIVATE_IPV4}:${PORT}" --ttl 60; \

Dann funktioniert es nicht - am Ende wird ein Wert wie 100.45.218.3:ohne Port festgelegt. Unterwegs habe ich viel Zeit damit verbracht, mit verschiedenen Verwendungszwecken der $PORTVariablen zu spielen, und ich habe keine Ahnung, warum die Konfiguration, für die ich mich entschieden habe, funktioniert. An einem Punkt hatte ich dies im Skript:

echo hi $PORT; \
echo "hi $PORT"; \
echo hi ${PORT}; \
echo "hi ${PORT}"; \

Und habe Tagebuchprotokolle wie diese bekommen:

Aug 17 01:05:07 core-01 bash[53694]: hi 32769
Aug 17 01:05:07 core-01 bash[53694]: hi 32769
Aug 17 01:05:07 core-01 bash[53694]: hi
Aug 17 01:05:07 core-01 bash[53694]: hi

Im Wesentlichen ist meine Frage: Was ist hier los? Dies steht {}im Widerspruch zu meinem Verständnis , in Bash-Skripten zu arbeiten. Und warum kann ich Curlies für die COREOS_PRIVATE_IPV4Variable verwenden (die exportiert wird /etc/environment, aber nicht für PORT?

Daniel Buckmaster
quelle

Antworten:

9

Dies ist in systemd.service (1) dokumentiert . ${PORT}wird um systemd erweitert. Zum Bestehen der $an die Shell Sie schreiben müssen $$, so $${PORT}. Die wichtige Zeile lautet:

Verwenden Sie "$$", um ein wörtliches Dollarzeichen zu übergeben. Variablen, deren Wert zur Erweiterungszeit nicht bekannt ist, werden als leere Zeichenfolgen behandelt.

Uwe Geuder
quelle
Dank dafür! Das macht jetzt Sinn, ich habe nicht bemerkt, dass Variablen durch systemd anders ersetzt werden können als während der Ausführung des Skripts selbst ...
Daniel Buckmaster
1
  1. Wenn der Inhalt von PORT von einer anderen Bash-Variablen stammt, mit der Sie sich befassen würden, indirect referenceversuchen Sie bitte:

    ${!PORT}
  2. Ich nehme an, Sie sind sicher, dass Ihre Shell Bash ist

Klopfen
quelle
Danke für die Antwort! 1. PORTkommt aus einer Zeile im Skript export PORT=$(docker ...); 2. CoreOS wird mit Bash 4.2 ausgeliefert
Daniel Buckmaster
Hast du es ${!PORT}in deinem Skript versucht ?
Pat
Ich habe es getan, und es scheint das gleiche Ergebnis zu liefern (eine leere Zeichenfolge).
Daniel Buckmaster