Systemd hizmetinde ortam değişkeni nasıl ayarlanır?


162

Sistemli bir Arch Linux sistemim var ve kendi hizmetimi oluşturdum. Adresindeki yapılandırma hizmeti /etc/systemd/system/myservice.serviceşöyle görünür:

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

Şimdi için bir ortam değişkeni ayarlamak istiyorum /bin/myforegroundcmd. Bunu nasıl yaparım?

Yanıtlar:


197

Zaman değişir ve en iyi uygulamaları yaparsınız.

Geçerli Bunu yapmanın en iyi yolu çalıştırmaktır systemctl edit myservicesizin için bir iptal dosyası yaratacak olan veya mevcut bir düzenleyelim.

Normal kurulumlarda bu bir dizin oluşturur /etc/systemd/system/myservice.service.dve bu dizinin içinde adı biten .conf(genellikle, override.conf) bir dosya oluşturur ve bu dosyaya dağıtım tarafından gönderilen birimin herhangi bir bölümüne ekleyebilir veya geçersiz kılabilirsiniz.

Örneğin, bir dosyada /etc/systemd/system/myservice.service.d/myenv.conf:

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

Ayrıca, dizin varsa ve boşsa, hizmetinizin devre dışı bırakılacağını unutmayın. Dizine bir şey koymak niyetinde değilseniz, mevcut olmadığından emin olun.


Başvuru için eski yol şuydu:

Bunu yapmanın önerilen yolu/etc/sysconfig/myservice , değişkenlerinizi içeren bir dosya oluşturmak ve sonra bunları yüklemektir EnvironmentFile.

Ayrıntıların tamamı için, Fedora’nın bir sistem komut dosyası yazma konusundaki belgelerine bakın .


4
Sanırım sysconfigyol Fedora'ya özgü ama soru Arch Linux ile ilgili. Paluh tarafından verilen cevap daha ilginç olduğunu düşünüyorum
Ludovic Kuty

1
/etc/sysconfigFedora özgüdür. AFAIR Arch Linux, yapılandırma dosyalarının Fedora'ya özgü bir yerde değil, pakete özgü bir yerde /etcolmasını sağlamaya çalışıyordu. Gibi /etc/myservice.conf, ekstra dosya kullanarak burada doğru yol görünmüyor olsa da.
Michał Górny

5
Hayır hayır hayır. / etc / sysconfig önerilmez. Debian'dan / etc / default / * ile birlikte caydırılır, çünkü anlamsızdırlar ve isimler anlamsızdır ve yalnızca geriye dönük uyumluluk nedenleriyle mantıklıdırlar (tüm / etc sadece / etc / değil sistemin konfigürasyonuyla ilgilidir. sysconfig ve / etc / defaults, varsayılanlar yerine geçersiz kılmalar içindir). Tanımları doğrudan birim dosyasına veya mümkün değilse, pakete özel bir konuma sahip bir ortam dosyasına (Michał'in önerdiği gibi) koyun.
zbyszek

1
@FrederickNord Değişken = DJANGO_SETTINGS_MODULE=project.settingsher satırda bir tane gibi değer çiftleri .
Michael Hampton,

1
@MichaelHampton Lütfen "geçerli en iyi yol" için dokümantasyon bağlantısını ekleyebilir misiniz?
jb.

77

Bu sorunun cevabı, değişkenin sabit olması (yani, üniteyi alan kullanıcı tarafından değiştirilmemesi gereken) veya değişken (kullanıcı tarafından ayarlanması gereken) olup olmamasına bağlıdır.

Yerel biriminiz olduğundan, sınır oldukça bulanık ve her iki şekilde de işe yarar. Ancak, dağıtmaya başlarsanız ve sonuçta ortaya çıkarsa /usr/lib/systemd/system, bu önemli hale gelecektir.

Sabit değer

Değerin örnek başına değişmesi gerekmiyorsa, tercih edilen yol Environment=, değeri doğrudan birim dosyasına koymaktır:

[Unit]
Description=My Daemon

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

[Install]
WantedBy=multi-user.target

Bunun avantajı, değişkenin ünite ile tek bir dosyada tutulmasıdır. Bu nedenle, birim dosyası sistemler arasında hareket etmek daha kolaydır.

Değişken değer

Bununla birlikte, yukarıdaki çözüm, sysadmin'in ortam değişkeninin değerini yerel olarak değiştirmesi gerektiği zaman işe yaramaz. Daha spesifik olarak, yeni değer, birim dosyası her güncellendiğinde ayarlanmalıdır.

Bu durumda, fazladan bir dosya kullanılacaktır. Nasıl - genellikle dağıtım politikasına bağlıdır.

Özellikle ilginç bir çözüm /etc/systemd/system/myservice.service.ddizin kullanmaktır . Diğer çözümlerden farklı olarak, bu dizin systemd tarafından desteklenir ve bu nedenle dağıtıma özgü yollar bulunmaz.

Bu durumda, /etc/systemd/system/myservice.service.d/local.confbirim dosyasının eksik parçalarını ekleyen bir dosya yerleştirirsiniz :

[Service]
Environment="FOO=bar baz"

Daha sonra, systemd hizmeti başlatırken iki dosyayı birleştirir ( systemctl daemon-reloadikisini de değiştirdikten sonra hatırlayın ). Ve bu yol doğrudan sistem tarafından kullanıldığından, bunun için kullanmazsınız EnvironmentFile=.

Değerin yalnızca bazı etkilenen sistemlerde değiştirilmesi gerekiyorsa, her iki çözümü birleştirerek, doğrudan ünitede bir varsayılan değer ve diğer dosyada yerel bir geçersiz kılma sağlayabilirsiniz.


systemctl daemon-reloadsystemd yeniden yükleme
emridir

EnvironmentFile=değerler şifreler gibi sırlar olduğunda daha iyidir. Ayrıntılar için cevabımı gör .
Don Kirkby,


17

Michael ve Michał tarafından verilen cevaplar yardımcıdır ve bir sistem hizmeti için ortam değişkeninin nasıl ayarlanacağı konusundaki orijinal soruya cevap verir. Bununla birlikte, ortam değişkenleri için yaygın bir kullanım , şifreniz gibi hassas verileri, uygulamanızın koduyla kaynak denetimine yanlışlıkla adanmayacak bir yerde yapılandırmaktır.

Eğer hizmetine bir ortam değişkeni geçmek istiyorum bu yüzden Eğer yok kullanmak Environment=birim yapılandırma dosyasında. Kullanın EnvironmentFile=ve yalnızca hizmet hesabı (ve kök erişimi olan kullanıcılar) tarafından okunabilen başka bir yapılandırma dosyasına yönlendirin.

Ünite konfigürasyon dosyasının detayları, bu komutu kullanan herhangi bir kullanıcı tarafından görülebilir:

systemctl show my_service

Bir yapılandırma dosyası /etc/my_service/my_service.confkoydum ve sırlarımı buraya koydum:

MY_SECRET=correcthorsebatterystaple

Sonra servis birimi dosyamda kullandım 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

ps auxeBu ortam değişkenlerini göremediğini ve diğer kullanıcıların erişemediğini kontrol ettim /proc/*/environ. Elbette kendi sisteminizi kontrol edin.


8

Michael bir temiz çözüm verdi, ancak komut dosyasından env değişkenini güncellemek istedim. Ne yazık ki, bash komutlarını çalıştırmak systemd birim dosyasında mümkün değildir. Neyse ki ExecStart içinde bash'i tetikleyebilirsiniz:

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

Bu ayarın doğrudan kabuk komut satırlarını desteklemediğini unutmayın. Eğer kabuk komut satırları kullanılacaksa, açıkça bir tür kabuk uygulamasına geçirilmeleri gerekir.

Bizim durumumuzda örnek o zaman:

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

7
Bu pek çok nedenden dolayı işe yaramaz (“tek seferlik” bir servis olmadığı sürece, bu anlamsızdır). İşe aşağıdaki başardı: /bin/bash -a -c 'source /etc/sysconfig/whatever && exec whatever-program'. -a(Eğer tüm değişkenleri önek istemedikçe olmasını sağlar çevre alt süreç ihraç edilmektedir whateverile export)
Otheus

neden işe yaramıyor? Her zaman betiği çalıştırmayı içeren komutun tamamını tetiklemeli değil mi?
user1830432,

Belki ExecStart=/usr/bin/env ENV=script /bin/myforegroundcmdbu durumda biraz daha iyi bir çözümdür.
kstep

@Otheus: Bir Tomcat 8 Unit dosyası oluşturmak zorunda kaldığım günden tasarruf sağlayan mükemmel cevap.
Daniel,

1
Bir systemd hizmet dosyasında "içinde" bir bash komutu yürütmenin bir yolu vardır. Bu bağlantıya bakınız: coreos.com/os/docs/latest/…
Mark Lakata
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.