Como esta variável escapando funciona em um arquivo unitário systemd?

6

Eu tenho um arquivo de unidade bastante simples para um serviço de sidekick de descoberta para uma instância do servidor que estou executando no CoreOS. O arquivo da unidade é assim:

[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

Isso funciona bem, mas eu levei séculos para chegar a este estágio, porque se eu mudar a linha etcdctl para isso:

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

Então não funciona - acaba definindo um valor como 100.45.218.3: , sem porta. Ao longo do caminho, passei muito tempo brincando com diferentes usos da variável $PORT , e não tenho ideia de por que a configuração que eu defini funciona. Em um ponto eu tive isso no script:

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

E recebi registros de diário assim:

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

Essencialmente, minha pergunta é: o que está acontecendo aqui? Isso mostra como eu entendo {} para trabalhar em scripts bash. E por que posso usar curlies na variável COREOS_PRIVATE_IPV4 (que é exportada de /etc/environment , mas não para PORT ?

    
por Daniel Buckmaster 17.08.2015 / 03:28

2 respostas

6

Isso está documentado em systemd.service (1) . ${PORT} é expandido pelo systemd. Para passar o $ para o shell, você precisa escrever $$ , então $${PORT} . A linha importante é esta:

To pass a literal dollar sign, use "$$". Variables whose value is not known at expansion time are treated as empty strings.

    
por 26.08.2015 / 07:33
1
  1. se o conteúdo do PORT vier de alguma outra variável bash você estaria lidando com um indirect reference , por favor tente:

    ${!PORT}
    
  2. Eu suponho que você tenha certeza de que seu shell é Bash

por 17.08.2015 / 13:49