Vraag Hoe omgevingsvariabele in systemd-service in te stellen?


ik heb een Arch Linux-systeem met systemd en ik heb mijn eigen service gemaakt. De configuratieservice op /etc/systemd/system/myservice.service het lijkt op dit:

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

Nu wil ik een omgevingsvariabele instellen voor de /bin/myforegroundcmd. Hoe doe ik dat?


119
2017-08-01 19:43


oorsprong




antwoorden:


Tijden veranderen en ook de beste werkwijzen.

De stroom de beste manier om dit te doen is om te rennen systemctl edit myservice, waarmee een override-bestand voor u wordt gemaakt of waarmee u een bestaand bestand kunt bewerken.

In normale installaties zal dit een map creëren /etc/systemd/system/myservice.service.d, en binnen die map een bestand maken waarvan de naam eindigt .conf (typisch, override.conf) en in dit bestand kunt u elk deel van de door de distributie verzonden eenheid toevoegen of vervangen.

Bijvoorbeeld in een bestand /etc/systemd/system/myservice.service.d/myenv.conf:

[Service]
Environment="SECRET=pGNqduRFkB4K9C2vijOmUDa2kPtUhArN"
Environment="ANOTHER_SECRET=JP8YLOc2bsNlrGuD6LVTq7L36obpjzxd"

Merk ook op dat als de map bestaat en leeg is, uw service zal worden uitgeschakeld! Als u niet van plan bent iets in de directory te plaatsen, zorg er dan voor dat het niet bestaat.


Ter referentie, de oude manier was:

De aanbevolen manier om dit te doen, is een bestand aan te maken /etc/sysconfig/myservice welke uw variabelen bevat, en laad ze vervolgens EnvironmentFile.

Zie Fedora's documentatie voor volledige details hoe een script te schrijven.


143
2017-08-01 20:07



Ik denk dat het sysconfig path is specifiek voor Fedora, maar de vraag gaat over Arch Linux. Het antwoord van paluh is interessanter denk ik - Ludovic Kuty
/etc/sysconfig is specifiek voor Fedora. AFAIR Arch Linux drong aan op het feit dat de configuratiebestanden eerder ergens pakketspecifiek in waren /etc in plaats van die Fedora-specifieke locatie. Net zoals /etc/myservice.conf, hoewel het gebruik van extra bestanden hier niet de goede weg lijkt. - Michał Górny
Nee nee nee. / etc / sysconfig wordt niet aanbevolen. Het is ontmoedigd, samen met / etc / default / * van debian, omdat ze zinloos zijn, en de namen zinloos zijn en alleen zinvol zijn voor achterwaartse compatibiliteitsredenen (alles van / etc gaat over de configuratie van het systeem, niet alleen / etc / sysconfig en / etc / defaults is voor overschrijvingen, niet de standaardinstellingen). Zet de definities gewoon in het bestand met de eenheid, of als het niet mogelijk is, in een milieubestand met een pakketspecifieke locatie (zoals de opmerking van Michał suggereert). - zbyszek
@FrederickNord Het zijn gewoon variabelen = waardeparen, zoals DJANGO_SETTINGS_MODULE=project.settings, een per regel. - Michael Hampton♦
@MichaelHampton Kunt u de documentatielink toevoegen voor "huidige beste manier"? - jb.


Het antwoord hangt af van de vraag of de variabele constant moet zijn (dat wil zeggen, niet verondersteld te worden gewijzigd door de gebruiker die de eenheid krijgt) of variabele (verondersteld wordt te worden ingesteld door de gebruiker).

Omdat het uw lokale apparaat is, is de grens vrij wazig en zou beide manieren werken. Echter, als je het begon te verspreiden en het erin zou belanden /usr/lib/systemd/system, dit zou belangrijk worden.

Constante waarde

Als de waarde niet per instantie hoeft te veranderen, is de voorkeursmanier om deze te plaatsen zoals Environment=, rechtstreeks in het bestand met eenheden:

[Unit]
Description=My Daemon

[Service]
Environment="FOO=bar baz"
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

Het voordeel hiervan is dat de variabele met de eenheid in één bestand wordt bewaard. Daarom is het eenheidsbestand eenvoudiger om tussen systemen te verplaatsen.

Variabele waarde

De bovenstaande oplossing werkt echter niet goed wanneer wordt verondersteld dat sysadmin de waarde van de omgevingsvariabele lokaal verandert. Meer specifiek moet de nieuwe waarde worden ingesteld elke keer dat het eenheidsbestand wordt bijgewerkt.

In dit geval moet een extra bestand worden gebruikt. Hoe - meestal afhankelijk van het distributiebeleid.

Een bijzonder interessante oplossing is om te gebruiken /etc/systemd/system/myservice.service.d directory. In tegenstelling tot andere oplossingen wordt deze map door systemd zelf ondersteund en daarom bevat deze geen distributiespecifieke paden.

In dit geval plaatst u een bestand zoals /etc/systemd/system/myservice.service.d/local.conf die de ontbrekende delen van het eenheidsbestand toevoegt:

[Service]
Environment="FOO=bar baz"

Naderhand, systemd combineert de twee bestanden bij het starten van de service (vergeet niet om systemctl daemon-reload na het veranderen van een van beide). En omdat dit pad direct door systemd wordt gebruikt, gebruik je het niet EnvironmentFile= voor deze.

Als de waarde alleen op sommige van de betrokken systemen zou moeten worden gewijzigd, kunt u beide oplossingen combineren, door een standaard rechtstreeks in het apparaat op te geven en door een lokale overschrijving in het andere bestand.


66
2018-04-23 07:48



systemctl daemon-reload is het commando om systemd te herladen - Dmitry Buzolin
EnvironmentFile= is beter wanneer de waarden geheimen zijn zoals wachtwoorden. Zien mijn antwoord voor details. - Don Kirkby


http://0pointer.de/public/systemd-man/systemd.exec.html#Environment= - je hebt twee opties (één al aangegeven door Michael):

Environment=

en

EnvironmentFile=

34
2017-10-16 13:55





Michael gaf één schone oplossing, maar ik wilde de env-variabele van het script ontvangen. Helaas is het uitvoeren van bash-commando's niet mogelijk in een systeembestand. Gelukkig kun je bash in ExecStart activeren:

http://www.dsm.fordham.edu/cgi-bin/man-cgi.pl?topic=systemd.service&ampsect=5

Merk op dat deze instelling shell-commandoregels niet direct ondersteunt. Als shell commandoregels moeten worden gebruikt, moeten ze expliciet worden doorgegeven aan een shell-implementatie van een soort.

Voorbeeld in ons geval is dan:

[Service]
ExecStart=/bin/bash -c "ENV=`script`; /bin/myforegroundcmd"

6
2017-07-23 13:31



Dit werkt niet om meerdere redenen (tenzij het een "one-shot" -service is, wat nogal zinloos is). Het lukte me om het volgende te laten werken: /bin/bash -a -c 'source /etc/sysconfig/whatever && exec whatever-program'. De -a zorgt ervoor dat de omgeving wordt geëxporteerd naar het subproces (tenzij u alle variabelen vooraf wilt invoegen whatever met export ) - Otheus
waarom het niet zal werken? Het zou altijd een volledige opdracht moeten activeren, inclusief het uitvoeren van het script, niet waar? - user1830432
Kan zijn ExecStart=/usr/bin/env ENV=script /bin/myforegroundcmd is in dit geval een iets betere oplossing. - kstep
@Otheus: prima antwoord, bespaard door de dag waarop ik een Tomcat 8 Unit-bestand moest maken. - Daniel
Er IS een manier om een ​​bash-opdracht "in" een systemd-servicebestand uit te voeren. Zie deze link: coreos.com/os/docs/latest/... - Mark Lakata


De antwoorden van Michael en Michał zijn behulpzaam en beantwoorden de oorspronkelijke vraag hoe een omgevingsvariabele voor een systemd-service in te stellen. Echter, één normaal gebruik voor omgevingsvariabelen is het configureren van gevoelige gegevens zoals wachtwoorden op een plaats die niet per ongeluk gebonden wordt aan bronbeheer met de code van uw toepassing.

Als u daarom een ​​omgevingsvariabele aan uw service wilt doorgeven, Niet doen gebruik Environment= in het configuratiebestand van de eenheid. Gebruik EnvironmentFile= en wijs het naar een ander configuratiebestand dat alleen leesbaar is voor de serviceaccount (en voor gebruikers met root-toegang).

De details van het configuratiebestand van de unit zijn zichtbaar voor elke gebruiker met deze opdracht:

systemctl show my_service

Ik heb een configuratiebestand geplaatst /etc/my_service/my_service.conf en leg daar mijn geheimen in:

MY_SECRET=correcthorsebatterystaple

Dan in mijn service-unitbestand, dat ik heb gebruikt EnvironmentFile=:

[Unit]
Description=my_service

[Service]
ExecStart=/usr/bin/python /path/to/my_service.py
EnvironmentFile=/etc/my_service/my_service.conf
User=myservice

[Install]
WantedBy=multi-user.target

Ik controleerde dat ps auxe kan die omgevingsvariabelen niet zien en andere gebruikers hebben er geen toegang toe /proc/*/environ. Controleer natuurlijk op je eigen systeem.


6
2018-05-04 00:29