الدليل المعماري لهيكلية ملفات لينكس FHS: كيف يعمل النظام خلف الكواليس؟

الدليل المعماري لهيكلية ملفات لينكس FHS: كيف يعمل النظام خلف الكواليس؟

تتعامل أنظمة لينكس مع وسائط التخزين والعتاد والعمليات البرمجية من خلال شجرة هرمية موحدة تبدأ من الجذر /، متخليةً تماماً عن منطق محركات الأقراص المنفصلة السائد في أنظمة مثل ويندوز. يضبط معيار FHS (اختصاراً لـ Filesystem Hierarchy Standard) أماكن استقرار البرامج والملفات وتوزيع الصلاحيات لضمان توافق البرمجيات عبر مختلف التوزيعات. يفكك هذا المقال الهيكلية المعمارية للنظام من منظور إداري حديث، مستعرضاً التحولات الجذرية في المعايير الحديثة وصولاً إلى FHS 3.0.

فلسفة الشجرة الواحدة ومصفوفة تصنيف البيانات في FHS

ينطلق لينكس من مبدأين هندسيين: “كل شيء عبارة عن ملف” (Everything is a file)، والشجرة الشاملة الموحدة (Unified Single Tree). لا توجد حروف للأقراص مثل C: أو D:؛ بل تُركّب (Mount) جميع وسائط التخزين المحلية، ومشاركات الشبكة، والأنظمة الافتراضية داخل نقاط تثبيت محددة تتفرع مباشرة من الجذر /. لتنظيم هذه الشجرة دون فوضى، يعتمد معيار FHS على مصفوفة تصنيف ثنائية الأبعاد تضع كل بايت في موضعه الصحيح بناءً على حالتين وظيفيتين:

  • الملفات القابلة للمشاركة (Shareable) مقابل غير القابلة للمشاركة (Unshareable): البيانات القابلة للمشاركة هي التي يمكن تخزينها على خادم مركزي وقراءتها عبر خوادم أو أجهزة متعددة عبر الشبكة (مثل مكتبات /usr أو ملفات وثائق البرامج). في المقابل، تشمل البيانات غير القابلة للمشاركة الملفات الحصرية لخادم معين، كملفات تهيئة الشبكة في /etc وسجلات النظام في /var/log.
  • الملفات الثابتة (Static) مقابل المتغيرة (Variable): البيانات الثابتة لا تتغير إلا بتدخل مدير النظام أو عبر ترقية الحزم البرمجية (مثل الأنوية ومجلدات البرامج التنفيذية في /bin و/boot). أما البيانات المتغيرة، فتخضع للتعديل المستمر التلقائي من العمليات النشطة وقواعد البيانات وسجلات الأحداث دون تدخل بشري مباشر.

المسارات السيادية: تشريح أعضاء النظام الحيوية

تحت المجلد الجذر /، توجد مجموعة من المسارات الأساسية التي تضمن إقلاع النظام وتشغيل خدماته واستقرار صلاحياته. يؤدي كل مسار وظيفة محددة بدقة صارمة وفق المعيار:

  • /etc: مخصص لملفات التهيئة والإعدادات الثابتة الخاصة بالنظام محلياً. يجب ألا يحتوي هذا المسار مطلقاً على برمجيات تنفيذية ثنائية (Binaries)، وتقتصر محتوياته على ملفات نصية تضبط سلوك الخدمات والشبكات والمستخدمين.
  • /var: يحوي البيانات المتغيرة (Variable Data) التي تتضخم وتتعدل باستمرار أثناء عمل الخادم، مثل سجلات النظام (Logs) في /var/log، وصفحات الويب الافتراضية، ومخازن قواعد البيانات وحزم التحديثات المؤقتة. يُعزل هذا المجلد غالباً في قسم تخزين منفصل على الخوادم لمنع امتلاء القرص واختناق العمليات الأساسية.
  • /boot: يضم كل ما يلزم لتنفيذ عملية الإقلاع الأولية، بما في ذلك ملفات محمل الإقلاع (GRUB)، وصورة النواة الحقيقية المضغوطة (vmlinuz)، وملف نظام الملفات الأولي في الذاكرة (initramfs).
  • /home مقابل /root: يُخصص مسار /home للمجلدات الشخصية لجميع المستخدمين العاديين، حيث يحصل كل مستخدم على مسار فرعي معزول. أما /root، فهو المجلد المنزلي الحصري لحساب المستخدم الخارق (Superuser)؛ وسبب وجوده في مجلد الجذر مباشرة وليس داخل /home هو ضمان وصول مدير النظام إليه حتى لو فشل تركيب قسم /home المنفصل أثناء صيانة الطوارئ.
  • /opt مقابل /usr/local: يُستخدم /opt لتثبيت حزم البرمجيات التراكمية المستقلة (Add-on applications) التي لا توفرها التوزيعة رسمياً ولا تلتزم بتفكيك ملفاتها داخل FHS (مثل تثبيت حزم متكاملة مثل Google Chrome أو حزم إدارة قواعد البيانات الخاصة). في المقابل، يُخصص /usr/local للبرمجيات التي يتم تجميعها وبناؤها يدوياً من المصدر (Compiled from source) على الخادم نفسه، بحيث تتبع هيكلية الشجرة القياسية (تحتوي على مجلدات فرعية مثل bin وlib).
  • /srv: مسار نص عليه معيار FHS ليحتوي على البيانات التي يقدمها الخادم لجهات خارجية، مثل ملفات خادم FTP أو مستودعات المشاريع البرمجية.

أنظمة الملفات الوهمية: واجهات الاتصال بالذاكرة والعتاد

لا تشير جميع المجلدات في شجرة لينكس إلى كتل تخزينية على أقراص SSD أو NVMe؛ بل يحتوي النظام على ما يُعرف بأنظمة الملفات الافتراضية (Pseudo/Virtual Filesystems). تتولد هذه الملفات ديناميكياً داخل ذاكرة الوصول العشوائي (RAM) وتتصل بالنواة مباشرة:

  • /proc: واجهة اتصال لحظية بنواة لينكس (Kernel Space). عند فتح هذا المجلد، تقرأ بيانات الذاكرة الفعلية للعمليات النشطة، وإحصاءات المعالج، واستخدام الذاكرة. لا يشغل أي ملف داخله حيزاً من القرص الصلب حتى لو أظهر الأمر ls أن حجم ملف النواة الأساسي /proc/kcore يعادل حجم الرام المثبت بالكامل.
  • /sys: واجهة تواصل مهيكلة مع نظام عتاد الجهاز (Sysfs) ظهرت مع إصدارات النواة 2.6 لتخفيف الضغط عن /proc. يعرض هذا المسار شجرة الأجهزة والمنافذ والمشغلات (Drivers)، ويسمح لمدير النظام بتعديل خيارات استهلاك الطاقة ووحدات المعالجة آنياً عبر التعديل في قيم الملفات.
  • /dev: يحتوي على عقد الأجهزة (Device Nodes). في فلسفة لينكس، الأقراص الصلبة (مثل /dev/sda)، والمنافذ التسلسلية، ومولدات الأرقام العشوائية (مثل /dev/urandom)، ومصارف البيانات الصامتة (مثل /dev/null) تُمثّل وتُعامل برمجياً كملفات قراءة وكتابة.

المسارات المؤقتة: الفرق الدقيق بين /tmp و /run

يخلط العديد من مدراء الأنظمة بين الملفات المؤقتة وبيانات وقت التشغيل. يكمن الفارق في دورة حياة البيانات والمرحلة التي تُطلب فيها:

يُعد المسار /tmp مخصصاً للملفات المؤقتة التي تنشئها البرامج وتطبيقات المستخدمين أثناء المعالجة (مثل ملفات التصدير المؤقتة أو أجزاء التنزيل). يخضع هذا المسار للحذف التلقائي إما دورياً أو عند كل إعادة تشغيل للنظام. على النقيض من ذلك، يمثل المسار /run نظام ملفات مؤقت في الذاكرة (tmpfs) مخصص لبيانات وقت التشغيل (Runtime Data) للخدمات الحية منذ آخر إقلاع فقط؛ مثل معرّفات العمليات (PID files)، ومقابس الاتصال البرمجية (Sockets). لا تُخزن في /run أي بيانات قبل بدء النواة، ويُعاد توليده نظيفاً عند كل إقلاع دون ترك أي أثر على القرص التخزيني.

التحول المعماري الحديث: حقيقة دمج UsrMerge ومعيار FHS 3.0

تحت إشراف منظمة FreeDesktop.org، شهد معيار FHS 3.0 تغييرات حاسمة تواكب حوسبة الحاويات والتخزين السريع. كان النظام القديم يقسم الأدوات التنفيذية بصرامة: الأدوات الحيوية للإقلاع والإصلاح تبقى في /bin و/sbin والمكتبات في /lib، بينما توضع الأدوات الثانوية في /usr/bin. جاء ذلك الفصل نتيجة قيود فيزيائية في سعة الأقراص الصلبة القديمة في سبعينيات القرن الماضي.

في التوزيعات الحديثة (مثل دبيان 12، أوبونتو 22.04 و24.04، وريدهات 9، وآرش لينكس)، تم تبني مشروع UsrMerge بالكامل. أصبحت مجلدات /bin و/sbin و/lib عبارة عن روابط رمزية (Symlinks) تشير مباشرة إلى نظيراتها داخل /usr. يُلغي هذا الدمج التكرار غير المبرر، ويسهل إدارة البرمجيات بصيغ معزولة للقراءة فقط، ويوفر بيئة مثالية لعمل الحاويات السحابية وتحديثات الأنظمة غير القابلة للتغيير (Immutable Systems).

فحص بنية النظام عملياً باستخدام Bash

يوفر السكربت التالي وسيلة آلية لتدقيق مطابقة النظام لمعايير UsrMerge الحديثة وتحديد أنواع أنظمة الملفات المركبة على المسارات الجذرية:

#!/usr/bin/env bash
# Script Name: audit_fhs_structure.sh
# Purpose: Verify UsrMerge status and inspect virtual vs storage filesystems

set -euo pipefail

echo "=========================================================="
echo "          Linux FHS Architecture & Merge Auditor          "
echo "=========================================================="
echo ""

# Section 1: Checking UsrMerge symlink consistency
echo "[+] Checking UsrMerge Migration Status:"
core_paths=("/bin" "/sbin" "/lib" "/lib64")

for dir in "${core_paths[@]}"; do
    if [ -L "$dir" ]; then
        target=$(readlink -f "$dir")
        echo "  [MERGED / SYMLINK] : $dir points to -> $target"
    elif [ -d "$dir" ]; then
        echo "  [LEGACY / SEPARATE]: $dir exists as an unmerged directory."
    else
        echo "  [NOT FOUND]        : $dir does not exist."
    fi
done

echo ""

# Section 2: Distinguishing Virtual, RAM, and Physical Filesystems
echo "[+] Auditing Filesystem Engine on Crucial Root Mounts:"
printf "%-10s %-12s %-18s %s\n" "Mount" "FSType" "Source Device" "Nature"
echo "----------------------------------------------------------------------"

fhs_mounts=("/" "/boot" "/dev" "/proc" "/sys" "/run" "/tmp")

for mnt in "${fhs_mounts[@]}"; do
    if [ -d "$mnt" ]; then
        mount_data=$(findmnt -n -o FSTYPE,SOURCE "$mnt" 2>/dev/null | head -n1 || true)
        fstype=$(awk '{print $1}' <<< "$mount_data")
        fssource=$(awk '{print $2}' <<< "$mount_data")

        case "$fstype" in
            proc|sysfs|devtmpfs)
                nature="Kernel Virtual Memory"
                ;;
            tmpfs)
                nature="Volatile Memory (RAM)"
                ;;
            ext4|xfs|btrfs|zfs)
                nature="Persistent Block Storage"
                ;;
            *)
                nature="Special / Other ($fstype)"
                ;;
        esac

        printf "%-10s %-12s %-18s %s\n" "$mnt" "$fstype" "$fssource" "$nature"
    fi
done

شرح عمل السكربت سطر بسطر

  • السطران 1 و2: تحديد بيئة تشغيل السكربت عبر مفسر bash مع ترويسة توضيحية لغرض السكربت.
  • السطر 5: تفعيل وضع التحقق الصارم set -euo pipefail لمنع تمرير الأخطاء غير المعالجة، وإيقاف التنفيذ في حال استخدام متغير غير معرّف أو فشل أي أمر متسلسل.
  • الأسطر 7 إلى 10: طباعة ترويسة الفحص للمستخدم لتنظيم المخرجات على الشاشة.
  • السطران 13 و14: تجهيز مصفوفة نصية core_paths تحتوي على المسارات التاريخية الأربعة التي شملها مشروع الاندماج UsrMerge.
  • الأسطر 16 إلى 26: حلقة تكرار تمر على مسارات المصفوفة؛ تفحص الشرط -L للتأكد مما إذا كان المسار مجرد رابط رمزي (Symlink)، وتستخرج هدفه الحقيقي باستخدام readlink -f، أو توضح إذا ما كان المجلد لا يزال تقليدياً وغير مدمج باستخدام الشرط -d.
  • الأسطر 30 إلى 32: طباعة ترويسة جدولية منسقة تفصل نوع نظام الملفات وحالته التخزينية باستخدام الأمر printf.
  • السطر 34: مصفوفة fhs_mounts تضم أهم المسارات السيادية المطلوب فحص موضع تثبيتها الفيزيائي والافتراضي.
  • الأسطر 36 إلى 40: التحقق من وجود المجلد، ثم استدعاء أداة الاستعلام عن التثبيت findmnt لاستخراج معمارية نظام الملفات والمصدر المباشر دون نصوص زائدة، مع تمرير القيم إلى متغيرات مستقلة عبر awk.
  • الأسطر 42 إلى 56: بنية شرطية case تحلل نوع نظام الملفات: تصنف proc وsysfs وdevtmpfs كأنظمة وهمية للنواة، وtmpfs كملفات متطايرة في الذاكرة العشوائية، والأنظمة مثل ext4 أو xfs كأقراص تخزين دائمة مستمرة، ثم تطبع السجل منسقاً.

الأخطاء الشائعة في إدارة هيكلية FHS وطرق تفاديها

  1. الخلط الكارثي بين مجلد الجذر ومجلد المستخدم الجذر:

    يخلط المبتدئون بين مجلد الجذر العام / (أصل النظام التخزيني بأكمله) والمجلد المنزلي الخاص بمدير النظام /root. محاولة نقل أو تفريغ محتويات / ظناً أنه مجلد حساب الـ root يدمر خريطة النظام ويؤدي إلى انهيار فوري غير قابل للإصلاح دون وسائط إنقاذ خارجية.

  2. محاولة تنظيف وحذف الملفات الضخمة داخل /proc:

    عند فحص المساحة باستخدام بعض الأدوات السطحية، يلاحظ مدراء الأنظمة الجدد ملفات ذات أحجام عملاقة في /proc (مثل ملف /proc/kcore) فيحاولون حذفها لتحرير المساحة. لا تشغل هذه الملفات أي بايت على وسائط التخزين بل تمثل استعراضاً برمجياً للذاكرة العشوائية، ومحاولة حذفها أو إفراغها تتسبب في أخطاء نواة (Kernel Panic) فورية.

  3. تثبيت حزم البرامج الخارجية في /usr مباشرة:

    يقوم بعض المطورين بفك ضغط ملفات تنفيذية لتطبيقات طرف ثالث يدوياً داخل /usr/bin أو /usr/lib. هذا المسار مخصص حصراً لمدير حزم النظام (مثل apt أو dnf). عند ترقية النظام، قد تُحذف هذه الملفات أو تتعارض مع مكتبات رسمية أخرى. الحل الهندسي السليم هو تثبيت التطبيقات المستقلة داخل /opt أو وضع الأدوات المجمعة محلياً في /usr/local.

  4. الخلط بين استخدامات /mnt و /media:

    يُخصص مسار /media للأجهزة القابلة للإزالة التي يركبها النظام تلقائياً عبر واجهات سطح المكتب وبيئات العرض (مثل وحدات USB والأقراص الضوئية). استخدام هذا المسار للتركيبات اليدوية الدائمة للخوادم يؤدي إلى تضارب مع خدمات إدارة وسائط النظام (مثل UDisks). الحل هو استخدام /mnt حصرياً لنقاط التثبيت المؤقتة واليدوية التي ينفذها مدير النظام لأغراض الصيانة.

متى تلتزم بمعيار FHS بصرامة ومتى تتجاوزه؟

يعد الالتزام الصارم بمعيار FHS إلزامياً إذا كنت تبني حزماً برمجية مخصصة للمستودعات الرسمية للتوزيعات، أو تدير خوادم إنتاجية تقليدية تعتمد على عزل الأقسام (Partitions) لضمان حماية النظام من الاختناق ومراقبة السجلات في /var، أو تبرمج أدوات نظام يجب أن تعمل عبر مختلف توزيعات لينكس دون فشل في الروابط. في المقابل، يصبح التجاوز المعماري لهذا المعيار مقبولاً ومبرراً هندسياً في بيئات الحاويات المصغرة (Containers مثل صور Distroless وAlpine) حيث يتم التخلص من أغلب فروع الشجرة لتقليص مساحة الهجوم والحجم، أو عند الاعتماد على أنظمة التشغيل غير القابلة للتغيير والحزم المعزولة حديثاً (مثل Flatpak وSnap وNixOS) التي تعيد تنظيم ملفات البرمجيات في مسارات مستقلة تماماً خارج التسلسل الهرمي التقليدي.