Làm thế nào để biến này thoát làm việc trong một tệp đơn vị systemd?


9

Tôi có một tệp đơn vị khá đơn giản cho dịch vụ phát hiện phụ cho một phiên bản máy chủ mà tôi đang chạy trên CoreOS. Tệp đơn vị trông như thế này:

[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

Điều này hoạt động tốt, nhưng tôi phải mất nhiều thời gian để đến giai đoạn này, bởi vì nếu tôi thay đổi etcdctldòng này:

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

Sau đó, nó không hoạt động - cuối cùng nó thiết lập một giá trị như 100.45.218.3:, không có cổng. Trên đường đi, tôi đã dành rất nhiều thời gian để chơi với các cách sử dụng khác nhau của $PORTbiến và tôi không biết tại sao cấu hình tôi giải quyết trên các công trình. Tại một thời điểm tôi đã có điều này trong kịch bản:

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

Và có nhật ký nhật ký như thế này:

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

Thực chất câu hỏi của tôi là: chuyện gì đang xảy ra ở đây vậy? Điều này đối mặt với cách tôi hiểu {}để làm việc trong các tập lệnh bash. Và tại sao tôi có thể sử dụng curlies trên COREOS_PRIVATE_IPV4biến (được xuất từ /etc/environment, nhưng không phải cho PORT?

Câu trả lời:


9

Điều này được ghi lại trong systemd.service (1) . ${PORT}được mở rộng bởi systemd. Để vượt qua $vỏ bạn cần viết $$, vì vậy $${PORT}. Dòng quan trọng là đây:

Để vượt qua ký hiệu đô la theo nghĩa đen, hãy sử dụng "$$". Các biến có giá trị không được biết tại thời điểm mở rộng được coi là các chuỗi rỗng.


Cảm ơn vì điều đó! Điều đó có ý nghĩa ngay bây giờ, tôi đã không nhận thấy rằng các biến có thể được thay thế bởi systemd khác với trong khi thực thi chính tập lệnh ...
Daniel Buckmaster

1
  1. nếu nội dung của PORT đến từ một số biến bash khác mà bạn sẽ xử lý indirect referencethì hãy thử:

    ${!PORT}
  2. Tôi giả sử bạn chắc chắn vỏ của bạn là Bash


Cảm ơn vì sự trả lời! 1. PORTxuất phát từ một dòng trong kịch bản export PORT=$(docker ...); 2. Các tàu CoreOS có bash 4.2
Daniel Buckmaster

bạn đã thử ${!PORT}trong kịch bản của bạn ??
Pat

Tôi đã làm, và nó dường như cho kết quả tương tự (một chuỗi rỗng).
Daniel Buckmaster
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.