أنظمة الحاسوب والشل و Docker
درس 1 من 8
1أنظمة الحاسوب والشل (Shell) و Docker
هذا الجزء يبني فهمك لما يحدث "خلف" أي برنامج تشغّله: كيف يتعامل النظام مع الملفات والصلاحيات، وكيف تتحكم به نصيًا عبر الشل، وكيف تعزل بيئات التشغيل بالحاويات.
ماذا تشاهد في الرسم: مخرج ls يصير مدخل grep، ومخرج grep يصير مدخل wc، فيظهر عدد ملفات بايثون في المجلد.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
هذا الدرس جسر قبل لغة C: تعود إلى ما تعرفه من الطرفية، لكن تنظر هذه المرة إلى ما خلف الستار. البرنامج الذي تشغّله عملية، والملف أرقام على القرص، والحاوية علبة مغلقة فيها كل ما يحتاجه البرنامج ليعمل بنفس الطريقة على أي جهاز.
النظام طبقات: العتاد ثم النواة ثم الشل والبرامج. الشل يربط الأوامر بالأنابيب وإعادة التوجيه، والصلاحيات تحمي الملفات، وملفات التهيئة مثل ~/.bashrc تضبط البيئة. وDocker يعزل البرنامج بمساحات أسماء النواة namespaces وحدود الموارد cgroups دون نظام تشغيل كامل كالآلة الافتراضية.
قبل أن تبدأ
🧠مفاهيم أساسية عن الملفات
تحتاج تفهم فكرة المجلدات والملفات كهيكل شجري قبل البدء.
الفكرة الجوهرية: طبقات النظام
شكل 1، الشل ليس نظام التشغيل نفسه، بل واجهة نصية تترجم أوامرك لطلبات تفهمها النواة (Kernel).
1الشل (Shell)
برنامج يقرأ أوامرك النصية وينفّذها، مثل bash. كل أمر تكتبه هو في الحقيقة اسم برنامج صغير يبحث عنه الشل وينفّذه.
2إعادة التوجيه والأنابيب (Redirection & Pipes)
> يعيد توجيه المخرجات لملف بدل الشاشة. | (الأنبوب) يمرّر مخرجات أمر كمدخلات لأمر آخر مباشرة، فتبني "خط تجميع" من أوامر بسيطة. فنيًا، الأنبوب ذاكرة مؤقتة صغيرة يديرها النظام نفسه بين العمليتين؛ كلا الأمرين يعملان في آن واحد لا الأول يكتمل تمامًا ثم يبدأ الثاني، والثاني يقرأ كل جزء من المخرجات فور توفّره، وهذا ما يجعل الأنابيب سريعة حتى مع كميات بيانات ضخمة.
3الصلاحيات (Permissions)
كل ملف له ثلاث فئات صلاحية (المالك، المجموعة، الآخرون) وثلاثة أنواع (قراءة r، كتابة w، تنفيذ x)، تُمثَّل رقميًا (مثل 755) أو رمزيًا (rwxr-xr-x). الرقم نفسه مجرد جمع لقيم ثابتة: قراءة = 4، كتابة = 2، تنفيذ = 1، فجمع الصلاحيات المطلوبة لكل فئة ينتج رقمها (مثلاً rwx = 4+2+1 = 7، و r-x = 4+1 = 5)، وهذا تمامًا كيف يتحقق النظام من كل طلب وصول: يقارن فئة الطالب (مالك/مجموعة/آخر) بالصلاحيات المشفَّرة في رقمها المقابل.
4ملفات التهيئة (Init Files)
ملفات مثل .bashrc تُنفَّذ تلقائيًا عند فتح جلسة شل جديدة، مكان مثالي لتعريف متغيرات بيئة (Environment Variables) واختصارات دائمة.
كيف يعمل، خطوة بخطوة: بناء خط أنابيب من أوامر
# عدّ عدد الأسطر التي تحتوي كلمة "error" في ملف سجلّ (log)، بعد فرزها أبجديًا cat server.log | grep "error" | sort | wc -l # ^ يطبع محتوى ^ يصفّي ^ يرتّب ^ يعدّ الأسطر # الملف كاملًا الأسطر فقط النهائية # فحص صلاحيات ملف سكربت وتعديلها ليكون قابلاً للتنفيذ للمالك فقط ls -l deploy.sh # يعرض مثلاً: -rw-r--r-- chmod 744 deploy.sh # 7=rwx للمالك، 4=r-- للمجموعة، 4=r-- للآخرين ./deploy.sh # الآن قابل للتنفيذ من صاحبه
شكل 2، كل أمر في السلسلة أعلاه بسيط جدًا بمفرده: قوة الشل الحقيقية في تركيب أوامر بسيطة بالأنابيب لحل مسائل معقّدة.
chmod 777 "لحل مشكلة الصلاحيات" بسرعة. هذا يمنح صلاحية الكتابة والتنفيذ للجميع بلا استثناء، ثغرة أمنية حقيقية. حدّد دائمًا أقل صلاحية كافية للعمل المطلوب.
من الشل إلى Docker: لماذا نعزل بيئات التشغيل؟
مشكلة كلاسيكية: "يعمل عندي لكن لا يعمل على خادم الإنتاج"، غالبًا بسبب اختلاف إصدارات المكتبات أو إعدادات النظام بين الجهازين. Docker يحل هذا بتغليف التطبيق مع كل ما يحتاجه (المكتبات، الإعدادات، حتى نظام ملفات مصغّر) في وحدة واحدة تعمل بنفس الطريقة في أي مكان.
| المفهوم | يمثّل |
|---|---|
| Image (صورة) | قالب ثابت للقراءة فقط يحتوي التطبيق وكل تبعياته، مثل وصفة طبخ مكتوبة. |
| Container (حاوية) | نسخة قيد التشغيل فعليًا من صورة معيّنة، مثل الطبق الفعلي المطهو من تلك الوصفة. |
| Dockerfile | ملف نصي يصف خطوات بناء الصورة (أي نظام أساس، أي حزم تُثبَّت، أي أمر يشغّل التطبيق). |
# مثال Dockerfile بسيط لتطبيق بايثون FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["python3", "app.py"]
تعمّق: ما يحدث داخل الحاسوب
قبل الشل وقبل C، يجب أن تعرف ما الذي يجري فعلًا داخل الحاسوب. هذه الأفكار تفسّر لاحقًا لماذا تُعدّ الذاكرة والمؤشرات أمرًا محوريًا.
أولًا: معمارية فون نيومان
الحاسوب الحديث يتبع نموذجًا يسمى معمارية فون نيومان: الذاكرة تخزّن البرنامج والبيانات معًا، ووحدة المعالجة المركزية (CPU) تجلب منها وتنفّذ. تتكوّن الـ CPU من وحدة حساب ومنطق (ALU) تجري العمليات، ووحدة تحكم (Control Unit) تنسق التنفيذ، ومسجلات (Registers) صغيرة وسريعة جدًا تحمل القيم الحالية. وتتصل بالذاكرة والأجهزة عبر ممرات تسمى الناقلات (Buses). ومنها فكرة أن البرنامج نفسه مجرد بيانات في الذاكرة.
شكل 3، مكونات الحاسوب وتدفق البيانات بينها.
ثانيًا: دورة الجلب والفك والتنفيذ
تعمل الـ CPU بلا توقف على حلقة من ثلاث خطوات. تجلب التعليمة التالية من عنوان تحدده مسجل خاص يسمى عداد البرنامج (Program Counter)، ثم تفكّ ترميزها لتعرف ماذا تعني، ثم تنفّذها، ويتقدم العداد للتعليمة التالية، إلا في حالة القفز حيث يُكتب عنوان جديد في العداد. ومن هنا تفهم أن الشرط والحلقة في أي لغة ليسا إلا قفزات تغيّر عداد البرنامج بناء على نتيجة مقارنة.
شكل 4، دورة التنفيذ الأساسية، والقفز كتعديل لعداد البرنامج.
ثالثًا: كيف تُمثَّل البيانات؟
كل شيء في الحاسوب أرقام ثنائية (0 و1). والبت وحدة واحدة، وكل ثمانية بتات تشكل بايت يستطيع تمثيل 256 قيمة (من 0 إلى 255). ولأن الثنائي طويل على العين، نكتب القيم غالبًا بالنظام السداسي عشر (Hex)، حيث يمثل كل رمز سداسي عشري أربعة بتات بالضبط، فبايت واحد يساوي رمزين.
| عشري | ثنائي | سداسي عشري | ملاحظة |
|---|---|---|---|
| 0 | 0000 0000 | 00 | أصغر قيمة في البايت |
| 10 | 0000 1010 | 0A | A تعني 10 |
| 65 | 0100 0001 | 41 | رمز الحرف A في ASCII |
| 255 | 1111 1111 | FF | أكبر قيمة في البايت |
وللتحويل من الثنائي إلى العشري تجمع قوى العدد 2 للخانات التي قيمتها 1. فالعدد 0100 0001 يساوي 64 + 1 = 65. أما الحروف فتُمثَّل بجدول ترميز مثل ASCII يعطي كل حرف رقمًا: الحرف A هو 65 والحرف a هو 97، والرقم المكتوب "0" هو 48 وليس صفرًا. ولهذا فالأرقام 65 و 0x41 و A قد تكون البايت نفسه مفسَّرًا بثلاث طرق: القراءة تعتمد على السياق لا على البتات.
رابعًا: ما مسؤوليات نظام التشغيل؟
⚙️العمليات
البرنامج ملف على القرص؛ أما العملية فهي برنامج قيد التشغيل له ذاكرته ومعرّفه (PID). يجدول النظام العمليات على الـ CPU بالتناوب السريع.
🧠الذاكرة
يوزّع الذاكرة على العمليات ويعزل كل واحدة عن الأخرى حتى لا تفسد إحداها بيانات الأخرى.
🗂️نظام الملفات
يحوّل أسماء الملفات والمجلدات إلى أماكن على القرص ويحفظ الصلاحيات.
🔌الأجهزة
يُخفي اختلاف الأجهزة خلف واجهة موحدة، فتقرأ من لوحة المفاتيح كما تقرأ من ملف.
خامسًا: المسارات المطلقة والنسبية
المسار المطلق يبدأ من الجذر / ويصف المكان بالكامل مهما كان موقعك، مثل /home/user/docs/a.txt. أما النسبي فيبدأ من المجلد الحالي: docs/a.txt، و .. تعني المجلد الأب و . المجلد الحالي. مثال: إن كنت في /home/user/docs فالمسار ../music/b.mp3 يعني /home/user/music/b.mp3.
سادسًا: رحلة تشغيل برنامج
شكل 5، من كتابة الأمر إلى عودة الموجّه.
تعمّق: الشل والملفات والصلاحيات
الشل لغة تخاطب بها نظام التشغيل. نفصّل هنا الأفكار التي تقف خلف أغلب الأوامر: بنية المجلدات، والروابط، وأحرف البدل، وعلامات الاقتباس، والتوسعات، والتدفقات، والصلاحيات.
أولًا: بنية شجرة الملفات في Linux
كل شيء في Linux شجرة واحدة جذرها /. وللمجلدات الرئيسية أدوار ثابتة تعرفها بالعرف: /home مجلدات المستخدمين، /etc ملفات الإعداد، /bin و /usr/bin الأوامر، /tmp ملفات مؤقتة، /var بيانات متغيرة مثل السجلات، /dev الأجهزة كملفات. وللمستخدم مجلد منزل (home) يعود إليه الأمر cd بلا وسيط. لاحظ الفرق بين / (جذر النظام) و /root (مجلد منزل المستخدم root) و ~ (اختصار لمنزلك أنت).
شكل 6، الشجرة الأساسية: كل ملف أو جهاز هو عقدة تحت الجذر.
ثانيًا: الرابط الصلب والرمزي
اسم الملف في Linux ليس الملف نفسه. الملف الحقيقي يُمثَّل ببنية في القرص تسمى inode تحمل بياناته وصلاحياته، والأسماء مجرد مداخل في المجلدات تشير إلى رقم inode. الرابط الصلب اسم آخر لنفس الـ inode: حذف أحد الاسمين لا يمحو البيانات ما دام اسم آخر موجودًا، ولا يعمل عبر أنظمة ملفات مختلفة ولا على المجلدات. أما الرابط الرمزي فملف صغير يحوي مسارًا نصيًا يشير إلى هدف، يشبه الاختصار: إذا حُذف الهدف يصبح الرابط معلّقًا لا يشير إلى شيء.
شكل 7، اسمان صلبان يشيران إلى inode واحد، ورابط رمزي يشير إلى اسم لا إلى inode.
| المعيار | رابط صلب | رابط رمزي |
|---|---|---|
| يشير إلى | inode | مسار نصي |
| بعد حذف الأصل | يعمل | يصبح معلّقًا |
| عبر أنظمة ملفات | لا | نعم |
| على المجلدات | لا | نعم |
ثالثًا: أحرف البدل ومن يوسّعها
نقطة تُفاجئ المبتدئ: حين تكتب ls *.txt فإن الشل هو من يحوّل *.txt إلى قائمة الملفات المطابقة، ثم يمرر القائمة إلى ls التي لا ترى النجمة أبدًا. وأحرف البدل الأساسية: * أي عدد من الأحرف، ? حرف واحد، و [abc] حرف من المجموعة. إذا لم يطابق شيء، تبقى الكلمة كما هي في الإعداد الافتراضي.
رابعًا: علامات الاقتباس وترتيب التوسعات
قبل تنفيذ أي أمر يمرر الشل السطر على مراحل توسع فيها الأشياء الخاصة. ثم يأتي الاقتباس لتحدد أي المراحل تريدها: علامة الاقتباس المفردة ' ' تعطّل كل شيء فتبقى الأحرف حرفية. المزدوجة " " تعطل أحرف البدل لكن تُبقي توسع المتغيرات $ والأوامر $( ). والشرطة المائلة العكسية \ تعطل الحرف الذي بعدها فقط.
| الصيغة | النتيجة عند وجود المتغير name بقيمة Ali | السبب |
|---|---|---|
echo $name | Ali | توسع المتغير |
echo "$name" | Ali | الاقتباس المزدوج يبقي التوسع |
echo '$name' | $name | الاقتباس المفرد حرفي |
echo "*.txt" | *.txt | أحرف البدل معطلة |
echo $(date) | ناتج الأمر date | استبدال الأمر |
شكل 8، الترتيب المبسّط لمراحل معالجة السطر داخل الشل.
خامسًا: التدفقات والأنابيب
لكل برنامج ثلاثة تدفقات جاهزة: المدخل القياسي stdin (الواصف 0)، والمخرج القياسي stdout (1)، والأخطاء stderr (2). الرمز > يوجّه المخرج إلى ملف (ويمحو ما فيه)، و >> يُلحق بنهايته، و < يجعل الملف مدخلًا، و 2> يوجّه الأخطاء وحدها، والأنبوب | يربط مخرج برنامج بمدخل التالي. هذه القطع الصغيرة تتجمّع لتكوّن أدوات قوية: كل أمر يؤدي شيئًا واحدًا، والأنبوب يركّبها.
شكل 9، سلسلة أنابيب: كل برنامج يمرر مخرجه إلى التالي، والأخطاء تذهب لمسار منفصل.
سادسًا: المستخدمون والصلاحيات بالأرقام
لكل ملف ثلاث فئات: المالك (u) والمجموعة (g) والبقية (o)، ولكل فئة ثلاث صلاحيات: قراءة (r) بقيمة 4، وكتابة (w) بقيمة 2، وتنفيذ (x) بقيمة 1. تجمع القيم لكل فئة فتحصل على رقم واحد، فيصبح rwxr-xr-- هو 754. وللمجلدات معنى مختلف: x تعني السماح بالدخول إليه، وr بسرد محتوياته، وw بإنشاء الملفات فيه وحذفها. ولا يستطيع المستخدم العادي نقل ملكية ملف لغيره (chown) حتى لا يتهرب أحد من حصص الأقراص أو يلقي ملفاته على الآخرين، فيحتاج صلاحيات الجذر عبر sudo.
| الرمز | العدد | الحساب |
|---|---|---|
| rwx | 7 | 4 + 2 + 1 |
| rw- | 6 | 4 + 2 |
| r-x | 5 | 4 + 1 |
| r-- | 4 | 4 |
| --- | 0 | 0 |
سابعًا: ملفات التهيئة وأين تُحمَّل
عند بدء الشل يقرأ ملفات تحدد بيئته. شل الدخول (login) يقرأ /etc/profile ثم أول ما يجده من ملفات الملف الشخصي في منزلك، بينما الشل التفاعلي غير الدخولي (كنافذة طرفية تفتحها داخل الواجهة) يقرأ ~/.bashrc. لذلك يضع كثيرون في ملف الدخول سطرًا يستدعي .bashrc. وأي تعديل في هذه الملفات لا يظهر في الشل المفتوح حتى تعيد تحميلها بالأمر source (أو النقطة).
اعتقاد أن chmod 777 حل لكل مشكلة صلاحيات. إنه يعطي الجميع حق الكتابة والتنفيذ، وهذا ثغرة أمنية تخفي المشكلة الحقيقية بدل أن تحلها.
تعمّق: الحاويات مقابل الآلات الافتراضية
تجربة "تعمل على جهازي" مشكلة قديمة: اختلاف النسخ والمكتبات بين الأجهزة. الحاويات تحلها بتعبئة البرنامج مع بيئته. نفصّل هنا كيف يختلف الحاوي عن الآلة الافتراضية، وما بنية الصورة، وكيف تعيش الحاوية وتموت.
أولًا: آلة افتراضية أم حاوية؟
الآلة الافتراضية تحاكي حاسوبًا كاملًا بنظام تشغيل كامل فوق مراقب (Hypervisor)، فتكون ثقيلة وبطيئة الإقلاع لكنها معزولة بقوة. الحاوية تشارك نواة النظام المضيف وتعزل العمليات والملفات بالمساحات الاسمية (namespaces) وتحدّ الموارد بالمجموعات الضابطة (cgroups)، فتكون خفيفة تُقلع بثوانٍ. الثمن أن كل الحاويات على جهاز واحد تعتمد على النواة نفسها.
شكل 10، الآلة الافتراضية تحمل نظامًا كاملًا لكل نسخة، والحاويات تتشارك نواة واحدة.
ثانيًا: الصورة والحاوية
الصورة (Image) قالب للقراءة فقط يضم نظام ملفات وبرنامجًا وإعداداته. الحاوية (Container) نسخة قيد التشغيل من صورة، وتشبه العلاقة بين الصنف والكائن في البرمجة. تُبنى الصورة من طبقات غير قابلة للتعديل تُكدَّس فوق بعضها، فتتشارك الصور الطبقات المشتركة وتوفر مساحة. وحين تعمل الحاوية تُضاف فوق الطبقات طبقة قابلة للكتابة مؤقتة، تُمحى بمحو الحاوية.
شكل 11، طبقات الصورة للقراءة فقط، وفوقها طبقة كتابة مؤقتة تُمحى مع الحاوية.
ثالثًا: دورة حياة الحاوية وحفظ البيانات
الحاوية تعيش بعمر العملية الرئيسية داخلها: إذا انتهت العملية انتهت الحاوية. تمر بحالات: منشأة، فقيد التشغيل، فمتوقفة، فمحذوفة. وبما أن طبقة الكتابة تُمحى مع الحاوية، فالبيانات المهمة يجب أن تُحفظ خارجها عمدًا بحجم (Volume) تديره Docker، أو بربط مجلد من المضيف (Bind Mount). من لا يفعل ذلك سيفقد بياناته حين يحذف الحاوية.
شكل 12، حالات الحاوية، وأوامر الانتقال بينها.
| الأمر | ما يفعله |
|---|---|
docker pull | ينزّل صورة من سجل (Registry) |
docker run | ينشئ حاوية من صورة ويشغلها |
docker ps | يعرض الحاويات العاملة (-a للكل) |
docker logs | يعرض مخرجات الحاوية |
docker exec | يشغّل أمرًا داخل حاوية عاملة |
جرّب بنفسك
ما وظيفة الأنبوب | في الشل؟
الأنبوب يربط أوامر بسيطة في «خط تجميع»، أما > فتعيد توجيه المخرجات إلى ملف.
ماذا تعني الصلاحيات 755 على ملف؟
7 = rwx للمالك، و5 = r-x للمجموعة، و5 = r-x للآخرين (rwxr-xr-x).
المشكلة الكلاسيكية «يعمل عندي لكن لا يعمل على الخادم». ما الذي يحلّها Docker؟
الاختلاف في إصدارات المكتبات وإعدادات النظام هو سبب المشكلة؛ الحاوية تحمل البيئة معها.
بطاقات مراجعة سريعة
تحقق من فهمك
لماذا نفضّل cmd1 | cmd2 على تخزين نتيجة cmd1 في ملف مؤقت ثم تمريره لـcmd2؟
الأنبوب يمرّر البيانات مباشرة في الذاكرة دون كتابة/قراءة ملف وسيط على القرص، فهو أسرع وأنظف، ولا يترك ملفات مؤقتة تحتاج حذفها لاحقًا.
لو حذفت Container معيّن، هل يختفي الـImage الذي بُني منه؟
لا، الـImage يبقى محفوظًا كقالب مستقل، ويمكنك إنشاء Container جديد منه في أي وقت؛ حذف Container يمسح فقط تلك النسخة قيد التشغيل وأي تغييرات غير محفوظة بداخلها.
احسب الرقم الذي يمثل صلاحيات rw-r-----.
6 للمالك (4+2)، و4 للمجموعة، و0 للبقية: 640.
حذفت الملف الأصلي فتوقف رابط عن العمل، أي نوع هو؟
رابط رمزي، لأنه يحمل مسارًا نصيًا إلى الهدف.
ماذا تطبع echo "$name" لو كانت name=Ali؟ وماذا تطبع '$name'؟
الأولى Ali والثانية $name حرفيًا.
لماذا تفقد بياناتك عند حذف حاوية لم تربطها بحجم؟
لأن طبقة الكتابة مؤقتة وتُمحى مع الحاوية.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
مقالات2
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.