الطّريق نحو فهم مُتغير المسار $PATH


محمد فوّاز عرابي

الغالب أنّ البرامج المفتوحة المصادر تتطلّب شيئًا من التّهيئة المُملّة عند أوّل استعمال، وقد يبدو للوهلة الأولى أنّ تلك التّهيئة تؤخّرك عن غايتك، التي هي حلّ المشكلة باستخدام الأداة المعنيّة، إلّا أنّ عمليّة التّهيئة فرصةٌ حسنةٌ للتّعوّد على استخدام واحدةٍ من أهمّ أدوات المهنة: سطر الأوامر.

يصيب سطر الأوامر بطبيعته الرّهبة في قلوب كثير من النّاس، إذ يرونه (في عُرف المجتمع) تقنيّة غامضةً يمارسها سحرةُ الحاسوب و"المُخترقون". الحقيقة أنّه سطر الأوامر ليس بهذه الرّوعة، فما هو إلا مجموعة من الأدوات شديدة البساطة أنشأها موظّفو Bell (الّتي تُعرف الآن بالاسم AT&T) لإنجاز مهامّ معظمها بسيط في السّبعينيّات من القرن الماضي، وليس فيها من التّطوّر التّقنيّ أكثر ممّا في فرن المايكروويف في مطبخك!

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

ولعلّ واحدًا من أهمّ تلك المفاهيم هو مفهوم المسار (Path).

تعتمد أدوات التّطوير للمتصفّح ومُعالجات CSS ومكتبات JavaScript وأدوات أخرى كثيرة على وجود Ruby أو Node.js مثبّتتين على جهازك. من هذه الأدوات Bower. يجمع بين هذه الأدوات كلّها أنّها ستُضطرّك إلى التّعامل مع المسار عاجلًا أو آجلًا، والسّبب أنّ يجب على المسار أن يعلم بوجود الأدوات الّتي تثبّتها في بيئة التّطوير على جهازك حتّى يستطيع سطر الأوامر أن يعمل بصورة صحيحةٍ.

قد تبدو الحاجة لفهم آليّة عمل المسار عودةً إلى الوراء، ولكنّك كلّما استخدمت أدوات سطر الأوامر أكثر، كان احتمال نشوء المُشكلات عن المسار أكبر. ولئلّا تُضيّع ساعات من يومك (أو ربّما لئلّا تبدأ برمي أغراضٍ ثقيلة على شاشة حاسوبك!)، تعّلم أساسيّات استخدام المسار.

مُتغيّر صغير ومتواضع

‏‎$PATH، كما تُفصح إشارة الدولار في أوّله والحروف الكبيرة الّتي تتلوها، مُتغيّر في بيئة Unix. القيمة المحفوظة في هذا المتغيّر هي قائمةً بمسارات إلى أدلّة (مُجلّدات)، مفصولةٍ بنقطتين (:)، كهذه القائمة:

/root/directory/binary:/root/other_directory/other_binary

إن كنت من أولئك المهووسين بتسمية المُتغيّرات، فقد تتساءل لما لم يُسمَّ المُتغيّر ‎$PATHS‎ (بصيغة الجمع)، كونه يحوي عدّة مسارات. اسمحوا لي بأن أخمّن السبب تخمينًا، فلربّما يُشير الاسم المُفرد إلى "مسار التّحميل المُكوّن من عدّة مسارات منفردة"، يبدو تخمينًا معقولًا!

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

بما أنّ ‏‎$PATH مُتغيّر، يمكننا تغييره كما نشاء، وفي أيّ وقت. يمكنك مثلًا كتابة هذا الأمر في الصّدفة (shell) لديك:

export PATH=banana

ما نتيجة هذا الأمر؟ جرّب تشغيله في نافذة جديدة داخل الطّرفيّة لديك أو في أي تطبيق صدفة تستخدمه، كبرنامج Terminal في OS X.

ثمّ جرّب بعد ذلك تنفيذ أي أمر Unix مثل ls (الّذي يطبع قائمة بمحتويات دليل/مُجلّد). ستكون النّتيجة: 

 ‎-bash: ls: command not found

‎ مع أنّ الأمر كان يعمل بلا مشكلات من قبل!

هذه الحيلة الشقيّة علّمتنا أنّ محتويات ‏‎$PATH ضروريّة جدًّا، وإلّا اختلط الحابل بالنّابل!

ولكن لماذا؟ لأنّ المسار يُحدّد ما يمكن تنفيذه في الصّدفة، فإن لم تعثر الصّدفة على شيءٍ يطابق اسمه ما كتبته، فلن تستطيع تنفيذه، والفكرة نفسها مُطبّقة في عدّة لغات برمجة وأطر عمل للويب مثل Rails.

كدت أنسى! لتصحيح هذه المشكلة، أغلق برنامج الطّرفية وأعد فتحه، فالعطل مؤقّتٌ في حالتنا، ولكن إيّاك أن تحفظ القيمة الخاطئة في ملفّ ‎~/.bash_profile‎، فعندها سيكون الوضع سيئًا للغاية!

حكاية عن البرامج الثّنائيّة

تُدعى بعض البرامج القابلة للتنفيذ في Unix "ملفّات ثنائيّة (binaries)". لأكون صادقًا معك، هذا الاسم غير مناسب على الإطلاق، لأنّه يهتمّ بصيغة البرامج بدلًا من وظيفتها. عندما تكتب برنامج Unix يؤدّي مهمّة مُحدَّدة، فإنّك قد تحتاج إلى تجميعه (compile) قبل أن تتمكّن من تنفيذه، عمليّة التجميع هذه تُنتج ملفًّا ثنائيًّا (binary). تعتمد هذه الملفّات الصّيغة الثنائيّة لتمثيل التّعليمات بصورة يسهل تنفيذها على الحاسوب بدلًا من الملفّات النّصيّة البسيطة (كملفّات مصدر البرنامج source code).

في Unix مُجلّدات عديدة تُحفظ فيها هذه الملفّات الثّنائيّة، وبإمكانك معرفة المُجلّد الذي يُستخدم بصورة مبدئيّة لتحميل الملفّات الثّنائيّة في الملف ‎/etc/paths‎:

 # الأمر cat يطبع محتويات ملفّ
$ cat /etc/paths 
/usr/bin 
/bin 
/usr/sbin 
/sbin 
/usr/local/bin

في كلّ سطر من الملف دليل واحدٌ. وقد رُتّبت المسارات بأسلوب مدروس، فإذا وجد ملفّ ثنائيّ في مسارٍ منها، حُمِّل، وإن وجد ملفّ آخر بالاسم نفسه في مسار آخر، لم يُنظر إليه. أي إنّ المسارات المُرتّبة في أعلى القائمة ذات أولويّة أكبر من تلك الّتي تقع أدناها.

هذا هو سبب المشكلات الّتي تواجهها عندما تُحاول تثبيت برنامجٍ جديد موجودٍ مسبقًا على نظامك، كما في حالة تثبيت إصدارة جديدةٍ من Git على OS X بدل تلك المُرفقة مع النّظام. هذا أمرٌ سيّئ لأنّ Git 2.0 ممتاز!

عندما أستعمل cd (الّذي يُغيّر الدّليل الحاليّ) للانتقال إلى ‎/usr/bin‎ (وهو مُجلّد يشيع تخزين البرامج فيه) ثمّ أستعمل ls، فإنّنى أرى أكثر من ألف نتيجة! وهذا أمرٌ غير مُفيد، ولذا أستعمل grep ضمن الأمر ls | grep git لأُصفِّيَ النّتائج بحيث تقتصر على البرامج تحوي الكلمة "git":

$ ls | grep git 
git
git-cvsserver
git-receive-pack
git-shell 
git-upload-archive 
git-upload-pack

كما ترى، هناك نسخة من Git في ‎/usr/bin‎، وعند تثبيت نسخة نظيفة من OS X فستكون هذه النّسخة هي المُعتمدة، كما يُبيّن تنفيذ الأمر which git.

$ which git 
/usr/local/bin/git

مهلًا! لماذا تُخالف النّتيجة لديّ ما توقّعته؟ لنفحص الأمر بدقّة بإرفاق which بالخيار ‎-a‎:

$ which -a git
/usr/bin/git
/usr/local/bin/git

هذا يؤكّد وجود نسختين من Git مثبّتتين على نظامي، ولكنّ الأولى هي المُعتمدة عندما أُنفّذ أوامر git في سطر الأوامر.

تغيير المسارات

قرّرت تثبيت إصدارٍ مُختلف من Git على نظامي مُستخدمًا مُدير حزم اسمه Homebrew لأنّني أحبّ أن أُسيطر على الأدوات الّتي أستخدمها كلّ يوم وأحدّثها وقتما أشاء. كان بإمكاني تحديث نسخة Git المُرفقَة مع النّظام، لكنّني لا أعلم إن كان هذا سيُعطِب البرامج الّتي تعتمد على وجودها.

نعلم إذن أنّ البحث عن البرامج يتبع ترتيب القائمة في الملفّ ‎/etc/paths‎، فلم لا نُغيّر هذا التّرتيب؟

أرى أن المُجلّد ‎/usr/local/bin‎ الّذي يحوي إصدار Git الّذي ثبّته Homebrew يقع في نهاية الملفّ ‎/etc/paths‎، وهذا يعني أن برنامج git في ‎/usr/bin‎ يطغى على الإصدار الّذي أريده.

بالطّبع لا شيء يمنعك من تغيير التّرتيب في الملفّ ‎/etc/paths‎ بحيث تضع ‎/usr/local/bin‎ في أعلى القائمة لتُعتمد نسخة Git من Homebrew، وستصادف هذه النّصيحة كثيرًا على Stack Overflow، لكن صدّقني... هذا أمرٌ بالغ السوء، لا تفعله! لم يُقصد من هذه الملفّات أن يُعدّلها مستخدمٌ منفردٌ لأنّه تؤثّر على كلّ النظام (حتّى وإن كنت الوحيد الّذي تستعمل الحاسوب)، وقد يسبب هذا التّغيير مشكلات لن تُدرك أسبابها في المستقبل، فقد تعتمد إحدى الأدوات في OS X على التّرتيب الأصليّ للملفّ ‎/etc/paths‎.

بدلًا من ذلك، عدّل المُتغيّر ‏‎$PATH في بيئتك أنت، في نسختك أنت من الملفّ ‎.bash_profile‎، الموجودة في ‎/Users/yourusername/.bash_profile‎.

ما عليك إلّا أن تجعل البحث يُجرى في ‎/usr/local/bin‎ أوّلًا في الملفّ ‎.bash_profile‎:

# في الملفّ /Users/olivierlacan/.bash_profile
export PATH=/usr/local/bin:$PATH

وهذا يؤدّي إلى تصدير مُتغيّر البيئة ‎$PATH‎ الجديد وذلك بطباعة المُتغيّر الحاليّ وإسباقه بـ ‎/usr/local/bin‎ على يسار كلّ المسارات الأخرى. بعد حفظ الملفّ ‎~/.bash_profile‎، وإعادة تشغيل الصّدفة، يُفترض أن ترى هذه النّتيجة عند استدعاء echo على المُتغيّر:

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

لاحظ أنّ ‎/usr/local/bin‎ مذكور مرّتين في المتغيّر ‎$PATH‎ ولا بأس في هذا. ولأنّه ذُكر أوّلًا، فكلّ البرامج الّتي تُحمّل منه في المّرة الأولى ستُتجاهَل عند الوصول إليه ثانيةً. كنت أتمنّى وجود طريقة آمنة وبسيطة لتغيير ترتيب المسارات، ولكنّ الحلول الّتي أعرفها شديدة التّعقيد. بإمكانك دومًا تجاوز القيمة المبدئيّة لـ‎$PATH‎ بالكامل، ولكن فقط عندما تُدرك تمامًا ما الّذي تفعله وأيّ المسارات يجب تضمينها.

على مفترق المسارات

بعد أن عدّلت المسار ‎$PATH‎ كما يحلو لك، بإمكانك التأكّد من أنّ البرنامج المرغوب يُستدعى عندما تُنفّذ الأمر git:

$ which git 
/usr/local/bin/git 

$ git --version 
git version 2.0.0
/usr/bin/git --version git version 1.8.5.2 (Apple Git-48)

عظيم! الإصدارة 2.0.0 من Git هي الّذي يتلقّى أوامر git (وهي الإصدارة الّتي ثبّتها Homebrew)، بينما تغيب الإصدارة 1.8.5.2 المُرفقة مع النّظام. إن قرّرت ألّا تستخدم الإصدارة 2.0.0 بعد الآن، ليس عليك سوى إزالتها وستعود الإصدارة الأقدم للعمل بصورة انسيابيّة.

احمِ مسارك

تُضيف أدوات تطوير (وتصميم) كثيرة أوامر برمجيّة إلى الملفّ ‎.bash_profile‎ بعد تثبيتها، والغالب أنّها لا تخبرك بذلك، فإن وجدت مسارات غريبة مُدرجةً في الملفّ، فقد يُفسّر ذلك بطء تحميل جلسة جديدة كلّ مرّة (الأمر الّذي يحدث عند فتح صدفة جديدة أو لسان جديد في الطّرفيّة): مُتغيّر ‎$PATH‎ طويل، يتطلّب وقتًا طويلًا لتحميله.

إليكم مساري اليوم:

/Users/olivierlacan/.rbenv/shims:/Users/olivierlacan/.rbenv/bin:/usr/local/bin:/usr/local/heroku/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/MacGPG2/bin

تصعب قراءته قليلًا، لذا أُفضّل تجزئته على سطور باستخدام الأمر tr (الّذي يستبدل حروفًا مُحدّدة):

$ echo $PATH | tr ':' '\n'
/Users/olivierlacan/.rbenv/shims
/Users/olivierlacan/.rbenv/bin
/usr/local/bin
/usr/local/heroku/bin
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin
/opt/X11/bin
/usr/local/MacGPG2/bin

أشياءٌ كثيرة تحدث هنا، ولكن فهمها أسهل وهي موزّعة على سطور. جرّب تنفيذ الأمر ذاته، فإنّ لم تفهم سبب وجود إحدى السّطور، فاحرص على إيجاده، فقد تتعلّم شيئًا مُفيدًا.

قد لا تبدو فائدة تعلّم ‎$PATH‎ وكيفيّة عمله عظيمةً. ولكن لأنك مُطوِّر ويب، فستحتاج إلى التّعامل مع سطر الأوامر، وقد تتعطّل إحدى أدواتك يومًا، والآن وقد تعلّمت مسارك وكيف يبدو وهو نظيف، والأسلوب الصّحيح لتعديله، وكيف تتأكّد من أنّه يعلم بوجود برامجك، فإنّ عودتك إلى "مسارك" المهنيّ ستستغرق دقائق بدلًا من ساعات!

ترجمة (بتصرّف) لمقال The $PATH to Enlightement لصاحبه Oliver Lacan



1 شخص أعجب بهذا


تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن