سؤال كيفية تعيين متغير البيئة في خدمة systemd؟


انا لدي نظام قوس لينكس مع systemd وقمت بإنشاء الخدمة الخاصة بي. خدمة التكوين في /etc/systemd/system/myservice.service يشبه هذا:

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

الآن أريد أن يكون لديك متغير بيئة لمجموعة /bin/myforegroundcmd. كيف يمكنني فعل ذلك؟


119
2017-08-01 19:43


الأصل




الأجوبة:


تغير الزمن وكذلك أفضل الممارسات.

ال تيار أفضل طريقة للقيام بذلك هي لتشغيل systemctl edit myserviceوالذي سيؤدي إلى إنشاء ملف تجاوز لك أو يسمح لك بتحرير ملف موجود.

في التركيبات العادية ، سيؤدي ذلك إلى إنشاء دليل /etc/systemd/system/myservice.service.d، وداخل هذا الدليل إنشاء ملف ينتهي اسمه في .conf (عادة، override.conf) ، وفي هذا الملف يمكنك إضافة أو إلغاء أي جزء من الوحدة التي يتم شحنها بواسطة التوزيع.

على سبيل المثال ، في ملف /etc/systemd/system/myservice.service.d/myenv.conf:

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

لاحظ أيضًا أنه إذا كان الدليل موجودًا وفارغًا ، فسيتم تعطيل خدمتك! إذا كنت لا تنوي وضع شيء ما في الدليل ، فتأكد من عدم وجوده.


كمرجع ، كانت الطريقة القديمة:

الطريقة الموصى بها للقيام بذلك هو إنشاء ملف /etc/sysconfig/myservice الذي يحتوي على المتغيرات الخاصة بك ، ومن ثم تحميلها EnvironmentFile.

للحصول على التفاصيل الكاملة ، انظر وثائق Fedora كيفية كتابة البرنامج النصي systemd.


144
2017-08-01 20:07



اعتقد ان sysconfig المسار خاص بـ Fedora لكن السؤال هو عن Arch Linux. إجابة paluh أكثر إثارةً أعتقد - Ludovic Kuty
/etc/sysconfig هو محدد فيدورا. كان AFAIR Arch Linux يدفع للحصول على ملفات التكوين في مكان ما محددة الحزمة بدلا من ذلك /etc بدلا من أن الموقع المحدد فيدورا. مثل /etc/myservice.conf، على الرغم من أن استخدام ملف إضافي لا يبدو الطريقة الصحيحة هنا. - Michał Górny
لا لا لا. / etc / sysconfig غير موصى به. لا يثبط ذلك ، مع / etc / default / * من ديبيان ، لأنها لا معنى لها ، والأسماء لا معنى لها ولها معنى فقط لأسباب التوافق العكسي (كل من / etc يدور حول تكوين النظام ، ليس فقط / etc / sysconfig ، و / etc / defaults هي للتجاوزات ، وليس الافتراضيات). فقط ضع التعريفات مباشرة في ملف الوحدة ، أو إذا لم يكن ذلك ممكناً ، في ملف enviornment يحتوي على موقع محدد للحزمة (كما يقترح تعليق Michał). - zbyszek
FrederickNord إنه مجرد متغير = أزواج قيمة ، مثل DJANGO_SETTINGS_MODULE=project.settings، واحد في كل سطر. - Michael Hampton♦
MichaelHampton يمكنك الرجاء إضافة رابط وثائق "أفضل طريقة الحالية"؟ - jb.


تعتمد الإجابة على ما إذا كان من المفترض أن يكون المتغير ثابتًا (بمعنى أنه ليس من المفترض أن يتم تعديله من قبل المستخدم الذي يحصل على الوحدة) أو متغير (من المفترض أن يتم تعيينه بواسطة المستخدم).

نظرًا لأن الوحدة المحلية هي وحدك ، فإن الحدود ضبابية تمامًا وسيعمل أيًا منهما. ومع ذلك ، إذا بدأت في توزيعها ، فسينتهي بها الأمر /usr/lib/systemd/system، هذا من شأنه أن يصبح مهما.

قيمة ثابتة

إذا كانت القيمة لا تحتاج إلى تغيير لكل مثيل ، فستكون الطريقة المفضلة لوضعها على أنها Environment=، مباشرة في ملف الوحدة:

[Unit]
Description=My Daemon

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

[Install]
WantedBy=multi-user.target

وتتمثل ميزة ذلك في الاحتفاظ بالمتغير في ملف واحد مع الوحدة. لذلك ، يكون من السهل نقل ملف الوحدة بين الأنظمة.

قيمة متغيرة

ومع ذلك ، فإن الحل أعلاه لا يعمل بشكل جيد عندما يفترض أن يقوم مسؤول النظام بتغيير قيمة متغير البيئة محليًا. وبشكل أكثر تحديدًا ، يجب تعيين القيمة الجديدة في كل مرة يتم فيها تحديث ملف الوحدة.

في هذه الحالة ، سيتم استخدام ملف إضافي. كيف - عادة ما يعتمد على سياسة التوزيع.

حل واحد للاهتمام بشكل خاص هو استخدام /etc/systemd/system/myservice.service.d دليل. بخلاف الحلول الأخرى ، يتم دعم هذا الدليل بواسطة systemd نفسه ، وبالتالي لا يحتوي على مسارات خاصة بالتوزيع.

في هذه الحالة ، يمكنك وضع ملف مثل /etc/systemd/system/myservice.service.d/local.conf يضيف الأجزاء المفقودة من ملف الوحدة:

[Service]
Environment="FOO=bar baz"

بعد ذلك ، يدمج systemd الملفين عند بدء الخدمة (تذكر إلى systemctl daemon-reload بعد تغيير أي منهما). وبما أن هذا المسار يستخدم مباشرة من قبل systemd ، فإنك لا تستخدمه EnvironmentFile= لهذا.

إذا كان من المفترض أن يتم تغيير القيمة فقط على بعض الأنظمة المتأثرة ، فيمكنك الجمع بين كلا الحلين ، مع توفير الإعداد الافتراضي مباشرة في الوحدة والتجاوز المحلي في الملف الآخر.


67
2018-04-23 07:48



systemctl daemon-reload هو الأمر لإعادة تحميل systemd - Dmitry Buzolin
EnvironmentFile= أفضل عندما تكون القيم أسرار مثل كلمات المرور. نرى إجابتي للتفاصيل. - Don Kirkby


http://0pointer.de/public/systemd-man/systemd.exec.html#Environment= - لديك خياران (أحدهما أشار إليه مايكل):

Environment=

و

EnvironmentFile=

34
2017-10-16 13:55





أعطى مايكل حلاً نظيفًا واحدًا ، لكني أردت الحصول على تحديث للمتغير env من النص البرمجي. للأسف تنفيذ أوامر bash غير ممكن في ملف الوحدة systemd. لحسن الحظ يمكنك تشغيل bash داخل ExecStart:

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

لاحظ أن هذا الإعداد لا يدعم مباشرة أسطر الأوامر shell. في حالة استخدام خطوط أوامر shell ، يجب أن يتم تمريرها بشكل صريح إلى تطبيق shell من نوع ما.

مثال في حالتنا هو:

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

6
2017-07-23 13:31



لن يعمل هذا لأسباب متعددة (ما لم تكن خدمة "ذات لقطة واحدة" ، والتي لا معنى لها). تمكنت من الحصول على ما يلي للعمل: /bin/bash -a -c 'source /etc/sysconfig/whatever && exec whatever-program'. ال -a يضمن أن البيئة يتم تصديرها إلى العملية الفرعية (إلا إذا كنت تريد بادئة كل المتغيرات في whatever مع export ) - Otheus
لماذا لن يعمل؟ ينبغي أن تؤدي إلى أمر كامل دائمًا يتضمن تنفيذ النص البرمجي ، أليس كذلك؟ - user1830432
يمكن ExecStart=/usr/bin/env ENV=script /bin/myforegroundcmd هو حل أفضل قليلا في هذه الحالة. - kstep
Otheus: إجابة رائعة ، تم حفظها باليوم عندما اضطررت لإنشاء ملف وحدة Tomcat 8. - Daniel
هناك طريقة لتنفيذ أمر bash "في" ملف خدمة systemd. انظر هذا الرابط: coreos.com/os/docs/latest/... - Mark Lakata


الإجابات من قبل ميخائيل و اللاعب Michał مفيدة والإجابة على السؤال الأصلي حول كيفية تعيين متغير بيئة لخدمة systemd. ومع ذلك ، واحد الاستخدام الشائع لمتغيرات البيئة هي تكوين البيانات الحساسة مثل كلمات المرور في مكان لا يلتزم بطريق الخطأ بالتحكم في المصدر مع رمز التطبيق الخاص بك.

إذا كان هذا هو سبب رغبتك في تمرير متغير بيئة إلى خدمتك ، لا استعمال Environment= في ملف تكوين الوحدة. استعمال EnvironmentFile= وأشره إلى ملف تكوين آخر يمكن قراءته فقط بواسطة حساب الخدمة (والمستخدمين الذين لديهم حق الوصول إلى الجذر).

تفاصيل ملف تكوين الوحدة مرئية لأي مستخدم لديه هذا الأمر:

systemctl show my_service

أضع ملف التكوين في /etc/my_service/my_service.conf وأضع أسراري هناك:

MY_SECRET=correcthorsebatterystaple

ثم في ملف وحدة الخدمة الخاصة بي ، اعتدت 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 auxe لا يمكن رؤية متغيرات البيئة هذه ، ولا يستطيع المستخدمون الآخرون الوصول إليها /proc/*/environ. تحقق على نظامك الخاص ، بالطبع.


6
2018-05-04 00:29