Zmienne dynamiczne w plikach systemowej jednostki serwisowej

14

Czy istnieje sposób dynamicznego przypisywania zmiennych środowiskowych w pliku systemowej jednostki usługowej?

Mamy maszynę, która ma 4 procesory graficzne i chcemy rozdzielić wiele wystąpień pewnej usługi na GPU. Na przykład:

  • gpu_service @ 1: 1. usługa
  • gpu_service @ 2: 1. usługa
  • gpu_service @ 3: 1. usługa
  • gpu_service @ 4: 1. usługa
  • gpu_service @ 1: 2.service
  • gpu_service @ 2: 2.service
  • gpu_service @ 3: 2.service
  • gpu_service @ 4: 2.service
  • do znudzenia

Zatem 1: 1, 2: 1 itd. Są faktycznie% i w pliku jednostki usługowej.

Aby usługa mogła się połączyć z określonym GPU, plik wykonywalny usługi sprawdza określoną zmienną środowiskową, np .:

USE_GPU=4

Czy istnieje sposób, aby pobrać% i do pliku jednostki usługowej i uruchomić go przez jakąś funkcję (powłoki) w celu uzyskania numeru GPU, a następnie odpowiednio ustawić zmienną środowiskową USE_GPU?

Co najważniejsze, nie chcę kłopotów z pisaniem wielu /etc/systemd/system/gpu_service@x:y.service/local.confplików tylko po to, aby móc rozpędzić więcej instancji.

Kal
źródło

Odpowiedzi:

10

Jeśli jesteś ostrożny, możesz dołączyć małą sekwencję skryptów bash jako polecenie exec do pliku usługi instancji. Na przykład

ExecStart=/bin/bash -c 'v=%i; USE_GPU=$${v%:*} exec /bin/mycommand'

$$W ciągu staną jeden $w rezultacie przekazany do bash, ale co ważniejsze, będzie zatrzymać ${...}przed interpolowane przez Systemd. (Wcześniejsze wersje systemd nie dokumentowały użycia $$, więc nie wiem, czy było wtedy obsługiwane).

meuh
źródło
Skończyło się na zrobieniu czegoś takiego. :)
Kal
1
Zadzwonić, bash -caby uruchomić program z pliku jednostki? Zadzwonić exec? To jest jak używanie wózka widłowego na wózku widłowym (może z innym wózkiem widłowym na górze), ponieważ pierwszy wózek ma problemy z wózkiem widłowym.
David Tonhofer
Niestety nie można użyć programu ExecStartPre do napisania pliku env, a następnie użyć go, najwyraźniej trzeba go wcześniej napisać, aby coś takiego działało. Lub skrypt otoki do dzielenia :) Inną dziwną opcją byłoby stworzenie innej usługi do ustawienia env. plik, nie jestem pewien, jak to by działało z szablonami: stackoverflow.com/a/42841480/32453
rogerdpack
8

Nie wbudowany w sposób. Musisz zrobić te rzeczy przed rozpoczęciem usługi. Jednym ze sposobów byłoby umieszczenie go w pliku środowiska.

[Service]
# Note you need to escape percentage sign
ExecStartPre=/bin/sh -c "my_awesome_parser %%i > /run/gpu_service_%i"
EnvironmentFile=/run/gpu_service_%i
ExecStart=...
Umut
źródło
3

Wygląda na to, że rzeczywiście można ustawić zmienne środowiskowe w pliku jednostkowym systemd ...

Zgodnie z sugestiami komentujących, oto rozwiązanie:

Używanie zmiennych środowiskowych w jednostkach systemowych

Dyrektywa środowiskowa

systemd ma dyrektywę Środowisko, która ustawia zmienne środowiskowe dla wykonywanych procesów. Wymaga rozdzielonej spacjami listy przypisań zmiennych. Tę opcję można podać więcej niż jeden raz, w którym to przypadku zostaną ustawione wszystkie wymienione zmienne. Jeśli ta sama zmienna zostanie ustawiona dwukrotnie, późniejsze ustawienie zastąpi wcześniejsze ustawienie. Jeśli pusty ciąg zostanie przypisany do tej opcji, lista zmiennych środowiskowych zostanie zresetowana, wszystkie wcześniejsze przypisania nie będą miały wpływu. Dyrektywy środowiskowe są używane we wbudowanych jednostkach systemowych kontenera Linux, na przykład w etcd2 i flaneli.

W poniższym przykładzie możesz skonfigurować demona etcd2 do korzystania z szyfrowania. Wystarczy utworzyć /etc/systemd/system/etcd2.service.d/30-certificates.confdrop-in dla etcd2.service:

[Service]
# Client Env Vars
Environment=ETCD_CA_FILE=/path/to/CA.pem
Environment=ETCD_CERT_FILE=/path/to/server.crt
Environment=ETCD_KEY_FILE=/path/to/server.key
# Peer Env Vars
Environment=ETCD_PEER_CA_FILE=/path/to/CA.pem
Environment=ETCD_PEER_CERT_FILE=/path/to/peers.crt
Environment=ETCD_PEER_KEY_FILE=/path/to/peers.key

Następnie uruchom sudo systemctl daemon-reloadi sudo systemctl restart etcd2.servicezastosuj nowe środowiska do demona etcd2.

Cytowany tekst pochodzi z następującego adresu URL: https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html

CyberK
źródło
2
Chociaż teoretycznie może to odpowiedzieć na pytanie, lepiej byłoby zawrzeć tutaj istotne części odpowiedzi i podać odnośnik.
Stephen Rauch
1
Chociaż twój komentarz może teoretycznie poprawić moje przyszłe odpowiedzi w
zamianie stosów, lepiej byś umieścił
1
Witamy w Stack Exchange! Dzięki za komentarz, rozśmieszyłeś mnie. Dziękujemy również za poświęcenie czasu na edycję odpowiedzi. Staramy się budować coś, co z czasem będzie miało wartość, a łącza zawierające tylko odpowiedzi po prostu nie starzeją się zbyt dobrze.
Stephen Rauch,
Jeśli dodasz Environment=ABC=%i, ustawia to środowisko. zmienna „do całości% i”. Myślę, że możesz zrobić opakowanie, aby usunąć „rzeczy poza cytatem”, których nie chcesz, i nazywa to prawdziwym plikiem wykonywalnym. Ale jeśli robisz opakowanie, możesz nawet %ipodać go jako argument, np .:ExecStart=my_wrapper %i
rogerdpack
Pytanie dotyczyło zmiennych „dynamicznych”; po prostu dałeś nam odpowiedź na rozwiązanie statyczne.
Otheus
0

To brzydkie i niezupełnie to, o co prosiłeś, ani nie pozwala na autostart, ale dla obserwujących można zrobić coś przy użyciu środowiska systemctl :

$ sudo systemctl set-environment USE_GPU=4 # add it to the env. variables for future services
$ sudo systemctl start gpu_service@4:2.service

Próbuję wymienić wszystkie możliwe sposoby :)

rogerdpack
źródło