この変数エスケープはsystemdユニットファイルでどのように機能しますか?


9

CoreOSで実行しているサーバーインスタンスの検出サイドキックサービス用のかなり単純なユニットファイルがあります。ユニットファイルは次のようになります。

[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

これは問題なく動作しますが、この段階に到達するには年齢がかかりました。etcdctl行を次のように変更すると、

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

次に、それは機能しません- 100.45.218.3:ポートのないのような値を設定することになります。途中で、$PORT変数のさまざまな使用法を試すのに多くの時間を費やしましたが、なぜ私が解決した構成が機能するのかわかりません。ある時点で、私はこれをスクリプトに含めました:

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

そして、このようなジャーナルログを得ました:

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

基本的に私の質問は:ここで何が起こっているのですか?これは、私{}がbashスクリプトで作業することを理解する方法に直面します。そして、なぜ私は上、中括弧を使用することができますCOREOS_PRIVATE_IPV4からエクスポートされた(変数/etc/environmentではなく、ためにPORT

回答:


9

これはsystemd.service(1)に文書化されています。${PORT}systemdによって拡張されます。を$シェルに渡すには$$、次のように記述する必要があります$${PORT}。重要な行はこれです:

文字通りのドル記号を渡すには、「$$」を使用します。展開時に値が不明な変数は、空の文字列として扱われます。


それをありがとう!これは理にかなっています。スクリプト自体の実行中とは異なり、systemdによって変数が置き換えられることに気づきませんでした...
Daniel Buckmaster

1
  1. PORTのコンテンツが他のbash変数からのものである場合は、indirect reference次に処理してみてください。

    ${!PORT}
  2. 私はあなたがあなたの殻がバッシュであると確信していると思います


ご返信ありがとうございます!1. PORTスクリプトの行からexport PORT=$(docker ...); 取得2. CoreOSにはbash 4.2が同梱
Daniel Buckmaster 2015

${!PORT}スクリプトで試しましたか?
パット

私はそうしました、そしてそれは同じ結果(空の文字列)を与えるようです。
Daniel Buckmaster 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.