سؤال ما الفرق بين تنفيذ نص Bash النصي مقابل الحصول عليه؟


ما الفرق بين تنفيذ النص البرمجي Bash مثل A وتزويد برنامج نصي Bash مثل B؟

A
> ./myscript

B
> source myscript

228
2017-12-11 15:24


الأصل




الأجوبة:


إجابة مختصرة: ستقوم المصادر بتشغيل الأوامر في عملية shell الحالية. تنفيذ سيتم تشغيل الأوامر في عملية shell جديدة. لازلت مشوش؟ ثم يرجى مواصلة قراءة الجواب الطويل.

المصطلح:

لتوضيح بعض الارتباك العام حول بناء الجملة وتنفيذها إلى المصدر:

./myscript

نفذ - اعدم  myscript بشرط أن الملف قابل للتنفيذ وموجود في الدليل الحالي. شرطة النقاط الرائدة (./) يدل على الدليل الحالي. يعد هذا ضروريًا لأن الدليل الحالي ليس في العادة $PATH.

myscript

نفذ - اعدم  myscript إذا كان الملف قابل للتنفيذ ويوجد في بعض الدليل في $PATH.

source myscript

مصدر  myscript. الملف لا يجب أن يكون قابلاً للتنفيذ ، ولكن يجب أن يكون نصًا نصيًا صالحًا. يمكن أن يكون الملف في الدليل الحالي أو في دليل في $PATH.

. myscript

مصدر  myscript. هذا النحو هو يحددها POSIX. باش محددة source كاسم مستعار لأمر النقطة.

برهنة:

يعتبر myscript.sh مع المحتوى التالي:

#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD

قبل تنفيذ النص البرمجي أولاً ، نتحقق من البيئة الحالية:

$ env | grep FOO
$ echo $PWD
/home/lesmana

المتغير FOO لم يتم تعريف ونحن في الدليل الرئيسي.

الآن نحن نفذ - اعدم الملف:

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

تحقق من البيئة مرة أخرى:

$ env | grep FOO
$ echo $PWD
/home/lesmana

المتغير FOO لم يتم ضبطه ولم يتغير دليل العمل.

يظهر إخراج البرنامج النصي بوضوح أنه تم تعيين المتغير وتم تغيير الدليل. يظهر التحقق بعد ذلك أن المتغير لم يتم تعيينه ولم يتغير الدليل. ماذا حدث؟ تم إجراء التغييرات في الجديد الصدف. ال تيار قذيفة ولدت الجديد قذيفة لتشغيل البرنامج النصي. يتم تشغيل البرنامج النصي في shell الجديد ويتم تفعيل كافة التغييرات على البيئة في shell الجديد. بعد الانتهاء من البرنامج النصي يتم تدمير shell الجديد. يتم إتلاف كافة التغييرات التي تم إجراؤها على البيئة في shell الجديد باستخدام shell الجديد. يتم طباعة نص الإخراج فقط في shell الحالي.

الآن نحن مصدر الملف:

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

تحقق من البيئة مرة أخرى:

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

تم تعيين متغير FOO وتغيير دليل العمل.

لا يؤدي إنشاء النص البرمجي إلى إنشاء غلاف جديد. يتم تشغيل كافة الأوامر في shell الحالي والتغييرات إلى البيئة نافذة المفعول في shell الحالي.

لاحظ أنه في هذا المثال البسيط ، يكون إخراج التنفيذ هو نفسه مصدر النص البرمجي. هذا ليس بالضرورة الحال دائما.

مظاهرة أخرى:

خذ بعين الاعتبار التالية البرنامج النصي pid.sh:

#!/bin/sh
echo $$

(المتغير الخاص $$ يوسع إلى PID من عملية shell قيد التشغيل الحالي)

أولاً اطبع PID الخاص بالصدفة الحالية:

$ echo $$
25009

مصدر النص البرمجي:

$ source pid.sh
25009

قم بتنفيذ البرنامج النصي ، لاحظ PID:

$ ./pid.sh
25011

المصدر مرة أخرى:

$ source pid.sh
25009

قم بالتنفيذ مرة أخرى:

$ ./pid.sh
25013

يمكنك أن ترى أن تشغيل المصدر يعمل في نفس العملية بينما يؤدي تنفيذ البرنامج النصي إلى إنشاء عملية جديدة في كل مرة. هذه العملية الجديدة هي الجديد قذيفة التي تم إنشاؤها لتنفيذ البرنامج النصي. لا يؤدي إنشاء النص البرمجي إلى إنشاء غلاف جديد ، وبالتالي يبقى عنصر PID كما هو.

ملخص

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

الاختلافات هي:

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

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


أنظر أيضا:


290
2017-08-16 21:58



استخدام واحد من المصادر هو خلق شكل بدائي من ملف التكوين للنصوص الخاصة بك. تبدأ بتحديد متغيرات مختلفة للقيم الافتراضية ، ثم المصدر في شيء ما مثل myscript.conf - ويمكن أن يحتوي النص البرمجي المصدر على عبارات التعيين التي تتجاوز أي قيم تريدها. نظرًا لأن البرنامج النصي المصدر لا يبدأ بـ # / bin / bash ، لا يتم تشجيعه على تنفيذه مباشرة. - LawrenceC
لذلك ، يشبه المصدر نوعًا ما تشغيله في نطاق عالمي ، ويؤدي التنفيذ إلى إنشاء نطاق محلي جديد. هل يمكن تمديد هذا إلى وظيفة في برنامج نصي؟ لتنفيذ وظيفة (عادة) أو "مصدر" ذلك؟ - aliteralmind
هل هناك فرق بين استخدام source myscript.sh و . myscript.sh؟ - Holloway
عمليا لا فرق عند استخدام باش. المصدر هو اسم مستعار للنقطة في bash. - lesmana
أنا أحب ذلك عندما يقدم الناس مثل هذه الأمثلة المتقنة حتى أنه يمكن حتى لمبتدئين من لينكس مثلي يفهمون. شكر! - Julius


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

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

إذا كان لديك وسائط موضعية في shell الحالي ، فلن تتغير.

لذلك إذا كان لدي ملف a.sh تحتوي:

echo a $*

وأنا كذلك:

$ set `date`
$ source ./a.sh

أحصل على شيء مثل:

a Fri Dec 11 07:34:17 PST 2009

بينما:

$ set `date`
$ ./a.sh

يعطيني:

a

امل ان يساعد.


21
2017-12-11 15:35



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


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

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


7
2017-12-11 15:27





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


4
2017-12-11 15:25





بالإضافة إلى أعلاه ، تنفيذ البرنامج النصي باسم ./myscript يتطلب تنفيذ إذن لملف myscript بينما لا يتطلب تحديد المصادر أي إذن تنفيذ. ذلك هو السبب chmod +x myscript غير مطلوب من قبل source myscript


4
2018-02-23 07:27



صحيح ، ولكن إذا كانت هذه مشكلة ، فيمكنك دائمًا تشغيلها bash myscript. - Daniel Beck♦


إذا كنت أتذكر الصحيح ، تنفيذ البرنامج النصي يدير الملف التنفيذي في #! قم بمحاذاة ملف البرنامج النصي كوسيطة (عادةً ما تبدأ في shell جديد وتقوم بتوصيل البرنامج النصي بشكل فعال إلى shell الجديد ، كما هو الحال مع #!/bin/sh
في حين ، يؤدي تنفيذ البرنامج النصي إلى تنفيذ كل سطر في بيئة shell الحالية ، وهو أمر مفيد لتحول غلافك الحالي (على سبيل المثال ، توفير طريقة لتعريف وظائف shell ومتغيرات بيئة التصدير).


3
2017-12-11 15:27





source ينفذ الأمر النصي المقدم (إذن قابل للتنفيذ هو ليس إلزاميا) في ال تيار بيئة قذيفة ، في حين ./ ينفذ المقدمة تنفيذ النصي في الجديد الصدف.

أيضًا ، تحقق من هذه الإجابة على سبيل المثال: https://superuser.com/a/894748/432100


2
2018-03-27 14:04