Comment cette variable d'échappement fonctionne-t-elle dans un fichier d'unité systemd?


9

J'ai un fichier unitaire assez simple pour un service d'accompagnement de découverte pour une instance de serveur que j'exécute sur CoreOS. Le fichier d'unité ressemble à ceci:

[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

Cela fonctionne bien, mais il m'a fallu beaucoup de temps pour arriver à ce stade, car si je change la etcdctlligne en ceci:

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

Ensuite, cela ne fonctionne pas - il finit par définir une valeur comme 100.45.218.3:, sans port. En cours de route, j'ai passé beaucoup de temps à jouer avec différentes utilisations de la $PORTvariable, et je ne sais pas pourquoi la configuration sur laquelle j'ai opté fonctionne. À un moment donné, j'avais ceci dans le script:

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

Et obtenu des journaux de journal comme celui-ci:

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

Essentiellement, ma question est: que se passe-t-il ici? Cela va à l'encontre de ma compréhension {}du travail dans les scripts bash. Et pourquoi puis-je utiliser des curlies sur la COREOS_PRIVATE_IPV4variable (qui est exportée depuis /etc/environment, mais pas pour PORT?

Réponses:


9

Ceci est documenté dans systemd.service (1) . ${PORT}est développé par systemd. Pour passer l' $au shell vous devez écrire $$, donc $${PORT}. La ligne importante est la suivante:

Pour passer un signe dollar littéral, utilisez "$$". Les variables dont la valeur n'est pas connue au moment de l'expansion sont traitées comme des chaînes vides.


Merci pour ça! Cela a du sens maintenant, je n'ai pas remarqué que les variables pouvaient être remplacées par systemd différemment de lors de l'exécution du script lui-même ...
Daniel Buckmaster

1
  1. si le contenu de PORT provient d'une autre variable bash avec laquelle vous auriez affaire, indirect referenceveuillez essayer:

    ${!PORT}
  2. Je suppose que vous êtes sûr que votre coquille est Bash


Merci pour la réponse! 1. PORTprovient d'une ligne du script export PORT=$(docker ...); 2. CoreOS est livré avec bash 4.2
Daniel Buckmaster

avez-vous essayé ${!PORT}dans votre script ??
Pat

Je l'ai fait, et cela semble donner le même résultat (une chaîne vide).
Daniel Buckmaster
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.