web-dev-qa-db-ja.com

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

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}。重要な行はこれです:

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

9
Uwe Geuder
  1. pORTのコンテンツが他のbash変数からのものである場合は、indirect referenceその後、お試しください:

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

1
Pat