كيفية استخدام Eval في Linux Bash Scripts

نشرت: 2022-08-22
كمبيوتر محمول Linux يعرض موجه bash
fatmawati achmad zaenuri / Shutterstock.com

من بين جميع أوامر Bash ، من المحتمل أن يكون eval القديم الضعيف هو الأسوأ سمعة. مبرر ، أم مجرد صحافة سيئة؟ نناقش استخدام ومخاطر أوامر Linux الأقل شهرة.

نحن بحاجة إلى التحدث عن Eval

عند استخدامها بلا eval ، يمكن أن يؤدي التقييم إلى سلوك غير متوقع وحتى انعدام الأمن في النظام. من أصواتها ، ربما لا ينبغي لنا استخدامها ، أليس كذلك؟ كذلك ليس تماما.

يمكنك أن تقول شيئًا مشابهًا عن السيارات. في الأيدي الخطأ ، هم سلاح فتاك. يستخدمها الناس في غارات مداهمات وكعربات هروب. هل يجب أن نتوقف جميعًا عن استخدام السيارات؟ لا بالطبع لأ. ولكن يجب استخدامها بشكل صحيح ، ومن قبل الأشخاص الذين يعرفون كيفية قيادتها.

كيفية التعامل مع المتغيرات في Bash
ذات الصلة كيفية العمل مع المتغيرات في Bash

الصفة المعتادة المطبقة على 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 "

استخدام EV مع متغير سلسلة لعد الكلمات في ملف

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

 أولًا = كيف
الثاني = المهوس

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

 متغيرات القط. txt
EVAL "$ (متغيرات القط. txt)"
صدى $ الأولى $ الثانية 

الوصول إلى المتغيرات المحددة من قبل Eval في الغلاف الحالي

باستخدام 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 

استخدام chmod لجعل نص برمجي قابل للتنفيذ

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

عندما نقوم بتشغيل البرنامج النصي الخاص بنا ، نرى النص من 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 .

9 أمثلة على الحلقات في نصوص لينكس باش
ذات صلة 9 أمثلة على الحلقات في لينكس باش سكربت

يقوم بطباعة المتغير الجديد إلى نافذة المحطة ثم يزيد المتغير total بقيمة المتغير الجديد.

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

أخيرًا ، نطبع قيمة المتغير total .

 ./loop.sh 

استخدام EVAL لإنشاء المتغيرات ديناميكيًا

ذات صلة: التمهيدي: 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 . تتم طباعة الاسم على نافذة المحطة. في نص برمجي حقيقي ، يمكنك أيضًا إنشاء الملف الفعلي.

كيفية إيقاف البرنامج النصي Bash مؤقتًا باستخدام أمر Linux Sleep
ذات صلة كيفية إيقاف البرنامج النصي Bash مؤقتًا باستخدام أمر Linux Sleep

يتم محاكاة نص البرنامج النصي باستخدام الأمر sleep . يقوم بإنشاء ملف السجل الأول ، وينتظر ثلاث ثوانٍ ، ثم يقوم بإنشاء ملف آخر. يقوم بإنشاء أربعة ملفات سجل ، متباعدة بحيث تختلف الطوابع الزمنية في أسماء الملفات الخاصة بهم.

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

إذا كان filecount لا يزال مضبوطًا على صفر - لأنه لم يتم إنشاء ملفات سجل - فلن يتم تنفيذ نص الحلقة أبدًا لأن واحدًا ليس أقل من أو يساوي صفرًا. لهذا السبب تم filecount متغير عدد الملفات على صفر عندما تم التصريح عنه ولماذا تمت زيادته قبل إنشاء الملف الأول.

داخل الحلقة ، نستخدم eval مع rm_string غير المدمر واسم الملف الذي يتم استرداده من المصفوفة. ثم نقوم بتعيين عنصر المصفوفة على سلسلة فارغة.

هذا ما نراه عند تشغيل البرنامج النصي.

 ./clear-logs.sh 

حذف الملفات التي تم تخزين أسمائها في مصفوفة

ليس كل شيء سيئا

إن eval كثيرًا له استخداماته بالتأكيد. مثل معظم الأدوات ، فإن استخدامها بتهور أمر خطير ، وبأكثر من طريقة.

إذا تأكدت من إنشاء السلاسل التي تعمل عليها داخليًا ولم يتم التقاطها من البشر أو واجهات برمجة التطبيقات أو أشياء مثل طلبات HTTPS ، فستتجنب المزالق الرئيسية.

ذات صلة: كيفية عرض التاريخ والوقت في Linux Terminal (واستخدامهما في Bash Scripts)