يحدث غالبًا أن تأتي إلى الجهاز وتجد نوعًا من البرامج النصية يعمل تحت مستخدم النظام قبل أسبوع. من أطلقها؟ أن ننظر فيها لهذا run.php؟ أو يمكنك إضافة إدخال إلى / etc / crontab ، ويتعطل البرنامج النصي هناك بسبب الخطأ "لم يتم العثور على الأمر". لماذا؟ وماذا تفعل؟
لدي إجابات لهذه الأسئلة.

متغيرات البيئة
في جميع أنظمة التشغيل الحديثة تقريبًا ، تشتمل العمليات على متغيرات البيئة. من الناحية الفنية ، فهي عبارة عن مجموعة من السلاسل المسماة. في حالة بدء تشغيل عملية فرعية ، فإنه يرث تلقائيًا نسخة من بيئة الوالد.
من بين أشياء أخرى ، هناك متغير PATH ، والذي يشير إلى مسارات البحث عن الملفات القابلة للتنفيذ ، ومتغير HOME ، الذي يشير إلى الدليل الرئيسي للمستخدم ، والمتغيرات المسؤولة عن تفضيلات لغة المستخدم ، والكثير غيرها.
هناك العديد من المراجعات التي تصف معنى هذه المتغيرات ، ولكن لا يوجد عملياً مقالات حول كيفية التحقيق في المشكلات. ملء هذه الفجوة.
من الذي بدأ العملية؟
لذلك ، وجدنا نصًا يعمل تحت مستخدم النظام قبل أسبوع. من أطلقها؟ لماذا؟ ربما نسوا عنه؟ من المحتمل أن 10 إلى 15 شخصًا يمكنهم إطلاقها ، فلن تقابل الجميع كيف تجد من كان؟ وأين يكمن هذا run.php؟
$ ps x | grep run.php 10684 ? Ss 472:25 /local/php/bin/php run.php
متغيرات البيئة العملية وميزة sudo تأتي لإنقاذ. يوجد مثل هذا المتغير PWD حيث تقوم shell بتخزين دليل العمل الحالي ؛ هذه القيمة ، في الواقع ، تخزن معلومات حول الدليل الحالي في وقت تشغيل الأمر. أيضًا ، الأداة المساعدة sudo افتراضيًا تترك المعلومات في متغير بيئة العملية حول المستخدم الذي تم تشغيله منه.
متغيرات البيئة (وأكثر من ذلك بكثير) لأي عملية تشغيل يمكن العثور عليها في / proc. فويلا:
$ cat /proc/10684/environ | tr '\0' '\n' | grep SUDO_USER SUDO_USER=alexxz $ cat /proc/10684/environ | tr '\0' '\n' | grep PWD PWD=/home/etlmaster
مهم ، لقد أطلقتها بنفسي. حسنًا ، من لم يحدث؟
بشكل عام ، باستخدام هذه الطريقة البسيطة في المواقف البسيطة ، يمكنك العثور على معلومات حول العملية ، والتي لا تتوفر عمومًا.
البرنامج النصي يعمل من سطر الأوامر ، لكنه لا يعمل من كرون
إحدى الحالات التي يتعين عليك فيها التفكير في متغيرات البيئة هي عندما يتعطل البرنامج النصي المضاف إلى / etc / crontab مع وجود خطأ. تذهب إلى الخادم عبر SSH ، وقم بتشغيل الأمر ، ويبدو أن كل شيء يعمل كما ينبغي. وعندما يبدأ تشغيله تلقائيًا ، فإنه يظهر شيئًا مثل "خلية: أمر غير موجود".
بشكل عام ، من الممارسات الجيدة كتابة المسار الكامل للأوامر القابلة للتنفيذ ، لكن هذا غير ممكن دائمًا. في مثل هذه الحالات ، يخرج المطورون كما يستطيع أي شخص. يضيف شخص ما المسار المطلوب في PATH كجزء من الفريق في crontab. أكثر من ذوي الخبرة التفاف قيادتهم في باش -L. وما زالت القنابل التي تدرسها التجربة المريرة لا تنسى أن تتدفق. كل شيء على هذا النحو: مصنوع ، يضاف إلى المراقبة والنسيان.
بعد هذه التلاعب ، تبقى الرواسب في روح مهندس حقيقي. نعم ، تم حل المشكلة. لكنني لم أفهم ما كان يجري! كيف هو نهج واحد أفضل من الآخر؟ أين يتم تخزين كل هذه الإعدادات ومن قام بتغييرها؟
دعنا نقارن متغيرات البيئة التي توجد بها العملية عندما يتم إطلاقها من التاج ومتغيرات البيئة التي لدينا في سطر الأوامر. نسجل إخراج الأمر env من التاج وبيئتنا الحالية:
$ echo "* * * * * env > ~/crontab.env" | crontab; sleep 60; echo "" | crontab; $ env > my.env
انظر ماذا يوجد في متغير PATH:
> grep ^PATH= crontab.env my.env Crontab.env: PATH=/usr/bin:/bin My.env: PATH=/local/hive/bin:/local/python/bin:/local/hadoop/bin:/local/hadoop/bin:/local/hive/bin:/local/hadoop/bin:/usr/local/bin:/usr/bin:/bin

ماما ميا! لذلك هناك تحت التاج الحد الأدنى للغاية! بالطبع ، تحتاج إلى تحميل متغيرات البيئة العادية.
لنرى كيف ستكون البيئة إذا أضفنا bash -l:
$ echo "* * * * * bash -l env > ~/crontab.env" | crontab; sleep 60; echo "" | crontab; alexxz@bi1.mlan:~> grep ^PATH= crontab.env my.env Crontab.env: PATH=/local/hive/bin:/local/python/bin:/local/hadoop/bin:/local/hadoop/bin:/local/hadoop/bin:/local/hive/bin:/usr/local/bin:/usr/bin:/bin My.env: PATH=/local/hive/bin:/local/python/bin:/local/hadoop/bin:/local/hadoop/bin:/local/hive/bin:/local/hadoop/bin:/usr/local/bin:/usr/bin:/bin
الفرق ليس ملحوظًا. يتم عرض جميع المسارات. بعضها بترتيب مختلف ، يتكرر بعضها ، لكن هذا أفضل بكثير مما كان عليه. ما تبقى من المتغيرات هي أيضا ضبطها بشكل جيد. هناك بالطبع اختلاف بسيط في الإعدادات المحلية ، في المتغيرات من SSH ، لكن هذا لم يعد يؤثر بشكل كبير على تشغيل البرنامج النصي.
أصبح من الواضح الآن سبب الحاجة إلى bash -l في إدخالات crontab. وبالطبع ، لا تنسى قطيع.
تصحيح تهيئة البرامج النصية لتسجيل الدخول
يبدو أن المشكلة يجب حلها ، كل شيء من التاج يعمل. ولكن كيف يتم تكرار بعض المسارات في متغير PATH؟ لذلك هناك نوع من الفوضى في إعداد الخادم. دعنا نحاول معرفة ذلك.
نفتح بعض الناس لتهيئة البيئة ، ونقرأ أي نصوص وبأي ترتيب يتم تنفيذه ، بحماس نبدأ في الجري في أعينهم - وبعد بضع دقائق يأتي الشعور باليأس. بعض الدفق اللانهائي من الشروط حول بعض الحالات الخاصة للبنيات والمحطات وإعدادات اللون المهمة بشكل لا يصدق للأمر ls. ألم ، يأس ، كراهية! نحن مهتمون ببا واحد متغير PATH!
في الواقع ، كل شيء أبسط إلى حد ما. اجتماع
env -i bash -x -l -c 'echo 123' > login.log 2>&1
ماذا يفعل هذا الفريق؟ ينشئ عملية bash جديدة مع بيئة مبدئية ، يشير إلى أنه من الضروري تشغيل البرامج النصية للتهيئة وتأمين كل شيء بالتفصيل في ملف login.log. الآن لدينا الفرصة لا لتنفيذ جميع النصوص في أذهاننا ، ولكن ببساطة لقراءة ماذا وأين ومتى تم تنفيذه ومن أين جاء هذا الإعداد أو تلك البيئة.
لن أحلل بالتفصيل كيفية قراءة السجل الناتج. كل شيء تافه تقريبا هناك. أذكر فقط أن ضربة واحدة جاءت من / etc / profile واثنين من /etc/bash.bashrc. نعم ، في مكان ما كانوا أذكياء للغاية عند إعداد الحزم في pappet. حسنًا ، لا شيء ، لا يزعجني العمل.
ولكن الآن أنا أعرف ويمكن!
ملاحظة: في الحالات الصعبة للغاية ، ولكي نفهم كل شيء على الإطلاق ، يمكنك لف الأمر بحزم:
strace -f env -i bash -x -l -c 'echo 123' > login.log 2>&1