كيفية استخدام Eval في Linux Bash Scripts
نشرت: 2022-08-22 من بين جميع أوامر Bash ، من المحتمل أن يكون eval
القديم الضعيف هو الأسوأ سمعة. مبرر ، أم مجرد صحافة سيئة؟ نناقش استخدام ومخاطر أوامر Linux الأقل شهرة.
نحن بحاجة إلى التحدث عن Eval
عند استخدامها بلا eval
، يمكن أن يؤدي التقييم إلى سلوك غير متوقع وحتى انعدام الأمن في النظام. من أصواتها ، ربما لا ينبغي لنا استخدامها ، أليس كذلك؟ كذلك ليس تماما.
يمكنك أن تقول شيئًا مشابهًا عن السيارات. في الأيدي الخطأ ، هم سلاح فتاك. يستخدمها الناس في غارات مداهمات وكعربات هروب. هل يجب أن نتوقف جميعًا عن استخدام السيارات؟ لا بالطبع لأ. ولكن يجب استخدامها بشكل صحيح ، ومن قبل الأشخاص الذين يعرفون كيفية قيادتها.
الصفة المعتادة المطبقة على eval
هي “شر”. لكن الأمر كله يتعلق بكيفية استخدامه. يقوم الأمر eval
بتجميع القيم من متغير واحد أو أكثر. يقوم بإنشاء سلسلة أوامر. ثم ينفذ هذا الأمر. هذا يجعله مفيدًا عندما تحتاج إلى التعامل مع المواقف التي يتم فيها اشتقاق محتوى الأمر ديناميكيًا أثناء تنفيذ البرنامج النصي الخاص بك.
تظهر المشكلات عندما تتم كتابة نص لاستخدام eval
على سلسلة تم استلامها من مكان ما خارج البرنامج النصي. يمكن كتابته من قبل المستخدم ، أو إرسالها من خلال واجهة برمجة التطبيقات ، أو وضع علامة عليها في طلب HTTPS ، أو في أي مكان آخر خارج البرنامج النصي.
إذا لم يتم اشتقاق السلسلة التي سيعمل عليها التقييم محليًا eval
، فهناك خطر من أن السلسلة قد تحتوي على تعليمات ضارة مضمنة أو مدخلات أخرى سيئة التكوين. من الواضح أنك لا ترغب في أن يقوم eval
بتنفيذ أوامر ضارة. حتى تكون آمنًا ، لا تستخدم eval
مع سلاسل مُنشأة خارجيًا أو مع مدخلات المستخدم.
الخطوات الأولى مع EVAL
الأمر eval
هو أمر Bash shell مضمن. إذا كان Bash موجودًا ، فسيكون eval
موجودًا.
تقوم eval
بتسلسل معلماتها في سلسلة واحدة. سيستخدم مساحة واحدة لفصل العناصر المتسلسلة. يقوم بتقييم الوسيطات ثم يمرر السلسلة بأكملها إلى shell لتنفيذه.
لنقم بإنشاء متغير يسمى wordcount
.
wordcount = "wc -w raw-notes.md"
يحتوي متغير السلسلة على أمر لعد الكلمات في ملف يسمى "raw-notes.md."
يمكننا استخدام eval
لتنفيذ هذا الأمر عن طريق تمرير قيمة المتغير إليه.
eval " $wordcount "
يتم تنفيذ الأمر في الصدفة الحالية ، وليس في مجموعة فرعية. يمكننا بسهولة إظهار هذا. لدينا ملف نصي قصير يسمى "variables.txt". يحتوي على هذين السطرين.
أولًا = كيف الثاني = المهوس
سنستخدم cat
لإرسال هذه الخطوط إلى نافذة المحطة. ثم سنستخدم eval
لتقييم أمر cat
بحيث يتم العمل وفقًا للتعليمات الموجودة داخل الملف النصي. هذا سيحدد المتغيرات بالنسبة لنا.
متغيرات القط. txt EVAL "$ (متغيرات القط. txt)" صدى $ الأولى $ الثانية
باستخدام echo
لطباعة قيم المتغيرات ، يمكننا أن نرى أن الأمر eval
يعمل في الغلاف الحالي ، وليس في المجموعة الفرعية.
لا يمكن لعملية في المجموعة الفرعية أن تغير بيئة الغلاف للوالد. نظرًا لأن EVAL تعمل في الصدفة الحالية ، فإن المتغيرات التي تم تعيينها بواسطة eval
يمكن استخدامها من الصدفة التي أطلقت الأمر eval
.
لاحظ أنه إذا كنت تستخدم eval
في نص برمجي ، فإن الصدفة التي سيتم تغييرها بواسطة eval
هي المجموعة الفرعية التي يعمل بها البرنامج النصي ، وليس الصدفة التي قامت بتشغيله.
ذات صلة: كيفية استخدام أوامر Linux cat و tac
استخدام المتغيرات في سلسلة الأوامر
يمكننا تضمين متغيرات أخرى في سلاسل الأوامر. سنضع متغيرين يحتويان على أعداد صحيحة.
العدد 1 = 10 عدد 2 = 7
سننشئ متغيرًا يحمل أمر expr
والذي سيعيد مجموع رقمين. هذا يعني أننا بحاجة إلى الوصول إلى قيم متغيرين من المتغيرات الصحيحة في الأمر. لاحظ backticks حول عبارة expr
.
add = "` expr $ num1 + $ num2` "
سننشئ أمرًا آخر لتظهر لنا نتيجة بيان expr
.
عرض = "صدى"
لاحظ أننا لا نحتاج إلى تضمين مسافة في نهاية سلسلة echo
، ولا في بداية سلسلة expr
. إن eval
يهتم بذلك.
ولتنفيذ الأمر بالكامل نستخدم:
تقييم $ show $ add
يتم استبدال القيم المتغيرة داخل سلسلة expr
في السلسلة بواسطة eval
قبل أن يتم تمريرها إلى shell ليتم تنفيذها.
ذات صلة: كيفية العمل مع المتغيرات في Bash
الوصول إلى المتغيرات داخل المتغيرات
يمكنك إسناد قيمة إلى متغير ، ثم إسناد اسم ذلك المتغير إلى متغير آخر. باستخدام eval
، يمكنك الوصول إلى القيمة المحفوظة في المتغير الأول ، من اسمه وهو القيمة المخزنة في المتغير الثاني. مثال سيساعدك على فك ذلك.
انسخ هذا النص إلى محرر ، واحفظه كملف يسمى “assign.sh”.
#! / بن / باش العنوان = "How-To Geek" صفحة الويب = العنوان أمر = "صدى" Eval $ command \ $ {$ webpage}
نحتاج إلى جعله قابلاً للتنفيذ باستخدام الأمر chmod
.
chmod + x assign.sh
ستحتاج إلى القيام بذلك لأي نصوص نصية تنسخها من هذه المقالة. فقط استخدم اسم البرنامج النصي المناسب في كل حالة.
عندما نقوم بتشغيل البرنامج النصي الخاص بنا ، نرى النص من title
المتغير على الرغم من أن الأمر eval
يستخدم webpage
المتغيرة.
./assign.sh
تتسبب علامة الدولار " $
" والأقواس الكبيرة " {}
" في قيام Eval بإلقاء نظرة على القيمة الموجودة داخل المتغير الذي تم تخزين اسمه في متغير webpage
.
استخدام المتغيرات التي تم إنشاؤها ديناميكيًا
يمكننا استخدام eval
لإنشاء المتغيرات ديناميكيًا. يسمى هذا البرنامج النصي "loop.sh."
#! / بن / باش المجموع = 0 التسمية = "اكتملت التكرار. الإجمالي:" لـ n في {1..10} فعل التقييم x $ n = $ n صدى "حلقة" $ x $ n ((إجمالي + = $ x دولار أمريكي)) فعله صدى $ x1 $ x2 $ x3 $ x4 $ x5 $ x6 $ x7 $ x8 $ x9 $ x10 صدى $ label $ المجموع
يقوم بإنشاء متغير يسمى total
والذي يحتوي على مجموع قيم المتغيرات التي نقوم بإنشائها. ثم يقوم بإنشاء متغير سلسلة يسمى label
. هذه سلسلة نصية بسيطة.
سنقوم بالتكرار 10 مرات وإنشاء 10 متغيرات تسمى x1
حتى x10
. توفر تعليمة eval
في جسم الحلقة "x" وتأخذ قيمة عداد الحلقة $n
لإنشاء اسم المتغير. في الوقت نفسه ، يضبط المتغير الجديد على قيمة عداد الحلقة $n
.
يقوم بطباعة المتغير الجديد إلى نافذة المحطة ثم يزيد المتغير total
بقيمة المتغير الجديد.
خارج الحلقة ، تتم طباعة المتغيرات العشرة الجديدة مرة أخرى ، وكلها في سطر واحد. لاحظ أنه يمكننا الإشارة إلى المتغيرات بأسمائها الحقيقية أيضًا ، دون استخدام نسخة محسوبة أو مشتقة من أسمائها.
أخيرًا ، نطبع قيمة المتغير total
.
./loop.sh
ذات صلة: التمهيدي: Bash Loops: for و while و until
باستخدام EVAL مع المصفوفات
تخيل سيناريو حيث يكون لديك برنامج نصي يعمل لفترة طويلة ويقوم ببعض المعالجة نيابة عنك. يكتب في ملف سجل باسم تم إنشاؤه من طابع زمني. من حين لآخر ، سيبدأ ملف سجل جديد. عند انتهاء البرنامج النصي ، إذا لم تكن هناك أخطاء ، فإنه يحذف ملفات السجل التي قام بإنشائها.
أنت لا تريده ببساطة rm *.log
، فأنت تريده فقط حذف ملفات السجل التي أنشأها. هذا البرنامج النصي يحاكي تلك الوظيفة. هذا هو "clear-logs.sh."
#! / بن / باش تعلن -ملفات السجل عدد الملفات = 0 rm_string = "صدى" وظيفة create_logfile () { ((++ filecount)) اسم الملف = $ (التاريخ + "٪ Y-٪ m-٪ d_٪ H-٪ M-٪ S"). سجل logfiles [$ filecount] = $ filename echo $ filecount "تم إنشاؤه" $ {logfiles [$ filecount]} } # نص النص. بعض المعالجة تتم هنا # بشكل دوري ينشئ ملف السجل. سنقوم بمحاكاة ذلك create_logfile النوم 3 create_logfile النوم 3 create_logfile النوم 3 create_logfile # هل هناك أي ملفات لإزالتها؟ لـ ((ملف = 1 ؛ ملف <= $ filecount ؛ ملف ++)) فعل # إزالة ملف السجل Eval $ rm_string $ {logfiles [$ file]} "تم حذفه ..." ملفات السجل [$ file] = "" فعله
يعلن البرنامج النصي عن مصفوفة تسمى logfiles
. سيحتوي هذا على أسماء ملفات السجل التي تم إنشاؤها بواسطة البرنامج النصي. تعلن عن متغير يسمى filecount
. سيحتوي هذا على عدد ملفات السجل التي تم إنشاؤها.
كما تعلن عن سلسلة تسمى rm_string
. في نص برمجي في العالم الحقيقي ، قد يحتوي هذا على الأمر rm
، لكننا نستخدم echo
حتى نتمكن من إظهار المبدأ بطريقة غير مدمرة.
الوظيفة create_logfile()
هي المكان الذي يتم فيه تسمية كل ملف سجل ، ومكان فتحه. نحن نقوم فقط بإنشاء اسم الملف ، ونتظاهر بأنه تم إنشاؤه في نظام الملفات.
تعمل الدالة على زيادة متغير filecount
. قيمته الأولية هي صفر ، لذلك يتم تخزين اسم الملف الأول الذي أنشأناه في الموضع الأول في المصفوفة. يتم ذلك عن قصد ، كما نرى لاحقًا.
يتم إنشاء اسم الملف باستخدام الأمر date
وامتداد ".log". يتم تخزين الاسم في المصفوفة في الموضع المشار إليه بواسطة filecount
. تتم طباعة الاسم على نافذة المحطة. في نص برمجي حقيقي ، يمكنك أيضًا إنشاء الملف الفعلي.
يتم محاكاة نص البرنامج النصي باستخدام الأمر sleep
. يقوم بإنشاء ملف السجل الأول ، وينتظر ثلاث ثوانٍ ، ثم يقوم بإنشاء ملف آخر. يقوم بإنشاء أربعة ملفات سجل ، متباعدة بحيث تختلف الطوابع الزمنية في أسماء الملفات الخاصة بهم.
أخيرًا ، هناك حلقة تحذف ملفات السجل. يتم تعيين ملف عداد الحلقة على واحد. يتم احتسابها بما يصل إلى قيمة عدد filecount
، والتي تحتوي على عدد الملفات التي تم إنشاؤها.
إذا كان filecount
لا يزال مضبوطًا على صفر - لأنه لم يتم إنشاء ملفات سجل - فلن يتم تنفيذ نص الحلقة أبدًا لأن واحدًا ليس أقل من أو يساوي صفرًا. لهذا السبب تم filecount
متغير عدد الملفات على صفر عندما تم التصريح عنه ولماذا تمت زيادته قبل إنشاء الملف الأول.
داخل الحلقة ، نستخدم eval
مع rm_string
غير المدمر واسم الملف الذي يتم استرداده من المصفوفة. ثم نقوم بتعيين عنصر المصفوفة على سلسلة فارغة.
هذا ما نراه عند تشغيل البرنامج النصي.
./clear-logs.sh
ليس كل شيء سيئا
إن eval
كثيرًا له استخداماته بالتأكيد. مثل معظم الأدوات ، فإن استخدامها بتهور أمر خطير ، وبأكثر من طريقة.
إذا تأكدت من إنشاء السلاسل التي تعمل عليها داخليًا ولم يتم التقاطها من البشر أو واجهات برمجة التطبيقات أو أشياء مثل طلبات HTTPS ، فستتجنب المزالق الرئيسية.
ذات صلة: كيفية عرض التاريخ والوقت في Linux Terminal (واستخدامهما في Bash Scripts)