Pertanyaan Bagaimana mengatur variabel lingkungan dalam layanan sistem?


Saya punya Sistem Linux Arch dengan systemd dan saya telah membuat layanan saya sendiri. Layanan konfigurasi di /etc/systemd/system/myservice.service terlihat seperti ini:

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

Sekarang saya ingin memiliki variabel lingkungan yang ditetapkan untuk /bin/myforegroundcmd. Bagaimana aku melakukan itu?


119
2017-08-01 19:43






Jawaban:


Perubahan waktu dan begitu juga praktik terbaik.

Itu arus Cara terbaik untuk melakukan ini adalah dengan berlari systemctl edit myservice, yang akan membuat file pengganti untuk Anda atau membiarkan Anda mengedit yang sudah ada.

Dalam instalasi normal ini akan membuat direktori /etc/systemd/system/myservice.service.d, dan di dalam direktori itu buat file yang namanya diakhiri .conf (khas, override.conf), dan dalam file ini Anda dapat menambah atau mengganti bagian apa pun dari unit yang dikirimkan oleh distribusi.

Misalnya, dalam file /etc/systemd/system/myservice.service.d/myenv.conf:

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

Perhatikan juga bahwa jika direktori ada dan kosong, layanan Anda akan dinonaktifkan! Jika Anda tidak ingin memasukkan sesuatu ke dalam direktori, pastikan tidak ada.


Untuk referensi, cara lama adalah:

Cara yang disarankan untuk melakukan ini adalah membuat file /etc/sysconfig/myservice yang berisi variabel Anda, dan kemudian memuatnya dengan EnvironmentFile.

Untuk rincian lengkap, lihat dokumentasi Fedora di bagaimana cara menulis skrip systemd.


143
2017-08-01 20:07



Saya kira itu sysconfig path khusus untuk Fedora tetapi pertanyaannya adalah tentang Arch Linux. Jawabannya menurut paluh lebih menarik menurut saya - Ludovic Kuty
/etc/sysconfig adalah khusus Fedora. AFAIR Arch Linux mendorong untuk memiliki file-file konfigurasi di suatu tempat paket-spesifik bukan di /etc daripada lokasi khusus Fedora. Seperti /etc/myservice.conf, meskipun menggunakan file ekstra sepertinya tidak benar di sini. - Michał Górny
Tidak tidak Tidak. / etc / sysconfig tidak direkomendasikan. Tidak disarankan, bersama dengan / etc / default / * dari debian, karena mereka tidak berguna, dan nama-nama tidak berarti dan hanya masuk akal untuk alasan kompatibilitas mundur (semua / etc adalah tentang konfigurasi sistem, bukan hanya / etc / sysconfig, dan / etc / defaults untuk mengganti, bukan default). Hanya menempatkan definisi langsung di file unit, atau jika tidak mungkin, dalam file lingkungan yang memiliki lokasi khusus paket (seperti komentar Michał menyarankan). - zbyszek
@FrederickNord Ini hanya variabel = pasangan nilai, seperti DJANGO_SETTINGS_MODULE=project.settings, satu per baris. - Michael Hampton♦
@MichaelHampton Bisakah Anda menambahkan tautan dokumentasi untuk "cara terbaik saat ini"? - jb.


Jawabannya tergantung pada apakah variabel seharusnya konstan (yaitu, tidak seharusnya dimodifikasi oleh pengguna mendapatkan unit) atau variabel (seharusnya diatur oleh pengguna).

Karena ini adalah unit lokal Anda, batasnya cukup buram dan cara mana pun akan berfungsi. Namun, jika Anda mulai mendistribusikannya dan itu akan berakhir /usr/lib/systemd/system, ini akan menjadi penting.

Nilai konstan

Jika nilai tidak perlu berubah per instance, cara yang disukai adalah menempatkannya sebagai Environment=, langsung di file unit:

[Unit]
Description=My Daemon

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

[Install]
WantedBy=multi-user.target

Keuntungannya adalah bahwa variabel disimpan dalam satu file dengan unit. Oleh karena itu, file unit lebih mudah dipindahkan antar sistem.

Nilai variabel

Namun, solusi di atas tidak berfungsi dengan baik ketika sysadmin seharusnya mengubah nilai variabel lingkungan secara lokal. Lebih khusus lagi, nilai baru perlu diatur setiap kali file unit diperbarui.

Untuk kasus ini, file ekstra akan digunakan. Bagaimana - biasanya tergantung pada kebijakan distribusi.

Salah satu solusi yang sangat menarik adalah menggunakan /etc/systemd/system/myservice.service.d direktori. Tidak seperti solusi lain, direktori ini didukung oleh sistem itu sendiri dan karena itu tidak memiliki jalur khusus distribusi.

Dalam hal ini, Anda menempatkan file seperti /etc/systemd/system/myservice.service.d/local.conf yang menambahkan bagian yang hilang dari file unit:

[Service]
Environment="FOO=bar baz"

Setelah itu, sistemd menggabungkan dua file ketika memulai layanan (ingat untuk systemctl daemon-reload setelah mengubah salah satu dari mereka). Dan karena jalur ini digunakan secara langsung oleh systemd, Anda tidak menggunakan EnvironmentFile= untuk ini.

Jika nilai seharusnya diubah hanya pada beberapa sistem yang terpengaruh, Anda dapat menggabungkan kedua solusi, menyediakan default langsung di unit dan penggantian lokal di file lain.


66
2018-04-23 07:48



systemctl daemon-reload adalah perintah untuk memuat ulang sistemd - Dmitry Buzolin
EnvironmentFile= lebih baik ketika nilai-nilai adalah rahasia seperti kata sandi. Lihat Jawabanku untuk detailnya. - Don Kirkby


http://0pointer.de/public/systemd-man/systemd.exec.html#Environment= - Anda memiliki dua opsi (yang telah ditunjuk oleh Michael):

Environment=

dan

EnvironmentFile=

34
2017-10-16 13:55





Michael memberikan satu solusi yang bersih tetapi saya ingin memperbarui variabel env dari skrip. Sayangnya mengeksekusi perintah bash tidak dimungkinkan dalam file unit sistem. Untungnya Anda dapat memicu bash di dalam ExecStart:

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

Perhatikan bahwa pengaturan ini tidak secara langsung mendukung baris perintah shell. Jika baris perintah shell harus digunakan, mereka harus diteruskan secara eksplisit ke implementasi shell dari beberapa jenis.

Contoh dalam kasus kami adalah:

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

6
2017-07-23 13:31



Ini tidak akan berhasil karena berbagai alasan (kecuali itu adalah layanan "satu-shot", yang agak tidak berguna). Saya berhasil mendapatkan yang berikut untuk bekerja: /bin/bash -a -c 'source /etc/sysconfig/whatever && exec whatever-program'. Itu -a memastikan lingkungan diekspor ke sub-proses (kecuali Anda ingin awalan semua variabel di whatever dengan export ) - Otheus
mengapa itu tidak berhasil? Itu harus selalu memicu seluruh perintah yang termasuk mengeksekusi skrip, bukan? - user1830432
Mungkin ExecStart=/usr/bin/env ENV=script /bin/myforegroundcmd adalah solusi yang sedikit lebih baik dalam hal ini. - kstep
@Otheus: Jawaban yang bagus, disimpan pada hari ketika saya harus membuat file Tomcat 8 Unit. - Daniel
ADA cara untuk menjalankan perintah bash "dalam" file layanan sistem. Lihat tautan ini: coreos.com/os/docs/latest/… - Mark Lakata


Jawabannya oleh Michael dan Michał membantu dan menjawab pertanyaan asli tentang cara mengatur variabel lingkungan untuk layanan sistem. Namun, satu penggunaan umum untuk variabel lingkungan adalah mengonfigurasi data sensitif seperti kata sandi di tempat yang tidak akan secara tidak sengaja berkomitmen terhadap kontrol sumber dengan kode aplikasi Anda.

Jika itu sebabnya Anda ingin menyampaikan variabel lingkungan ke layanan Anda, tidak menggunakan Environment= dalam file konfigurasi unit. Menggunakan EnvironmentFile= dan arahkan ke file konfigurasi lain yang hanya dapat dibaca oleh akun layanan (dan pengguna dengan akses root).

Detail file konfigurasi unit dapat dilihat oleh semua pengguna dengan perintah ini:

systemctl show my_service

Saya meletakkan file konfigurasi di /etc/my_service/my_service.conf dan menyimpan rahasia saya di sana:

MY_SECRET=correcthorsebatterystaple

Kemudian di file unit layanan saya, saya gunakan 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

Saya memeriksanya ps auxe tidak dapat melihat variabel lingkungan tersebut, dan pengguna lain tidak memiliki akses ke /proc/*/environ. Periksa sistem Anda sendiri, tentu saja.


6
2018-05-04 00:29