SSD Nodes Learn 🎉 VPS من $5.50/شهر
الأدلة Matt Connorبقلم Matt Connor

chmod 755 أم u+x؟ الفرق بين النمطين الرقمي والرمزي

تعلّم تغيير أذونات Linux باستخدام chmod، وافهم الأرقام الثمانية وصيغة u/g/o، ولماذا يفسد النمط الرقمي التكراري شجرة الملفات، وما الذي يصلحه X الكبير.

ما الذي يغيّره chmod

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

قراءة النمط وتغيير النمط مهمتان مختلفتان. إذا لم تكن حروف القائمة الطويلة واضحة لك بعد، فاقرأ أولاً ما الذي يعنيه drwxr-xr-x خانةً خانةً. يغيّر هذا الدليل هذه الأذونات فقط.

نفّذ كل ما يرد هنا باستخدام مستخدم تسجيل الدخول العادي. يتجاوز حساب root عمليات التحقق هذه، ولذلك لا يثبت تشغيل عرض توضيحي للأذونات باستخدام root شيئاً. إذا كنت لا تزال تعمل باستخدام root على خادم جديد، فأنشئ مستخدماً عادياً بأقل قدر من الامتيازات ثم تابع.

أنشئ بيئة اختبار يمكنك حذفها

cd "$(mktemp -d)"
touch notes.txt

ينشئ mktemp -d دليلاً فارغاً داخل /tmp ويطبع المسار الذي أنشأه، ويمرّر استبدال الأوامر ذلك المسار مباشرةً إلى cd. لا يلمس أي شيء مما يلي ملفاً يهمك.

يعرض أمر واحد نتيجة كل تغيير:

stat -c '%a %A %n' notes.txt

يطبع %a النمط كرقم ثماني، ويطبع %A النمط نفسه بصيغة الأحرف التي تستخدمها القائمة الطويلة، ويطبع %n الاسم. في الكتل التالية، السطر الذي يبدأ بـ $ هو ما تكتبه، والسطر الذي يليه هو ما طبعه الأمر. نفّذ الأوامر بنفسك. يجب أن يطابق الناتج على جهازك كل سطر، لأن النمط الرقمي لا يعتمد على أي شيء في بيئتك.

الصيغة الرقمية: رقم ثماني واحد لكل فئة

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

$ chmod 400 notes.txt
$ stat -c '%a %A %n' notes.txt
400 -r-------- notes.txt
$ chmod 200 notes.txt
$ stat -c '%a %A %n' notes.txt
200 --w------- notes.txt
$ chmod 100 notes.txt
$ stat -c '%a %A %n' notes.txt
100 ---x------ notes.txt

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

$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt
$ chmod 700 notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod 750 notes.txt
$ stat -c '%a %A %n' notes.txt
750 -rwxr-x--- notes.txt

الوضع الرقمي مطلق. فهو يكتب البتات التسعة كلها في كل مرة، ولذلك يكتب أيضاً بتات فئة لم تكن تفكر فيها.

$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt

لم يذكر الأمر الثاني شيئاً عن المجموعة أو عن جميع المستخدمين الآخرين، ومع ذلك تغيّرت بتاتهما. هذه هي طبيعة الصيغة الرقمية، ولذلك فهي الأداة الخاطئة لإجراء تعديل صغير. (يتعامل chmod أيضاً مع بتات setuid وsetgid وsticky، التي توجد في رقم رابع يسبق هذه الأرقام. هذا موضوع منفصل، ويقتصر هذا الدليل على الأرقام الثلاثة.)

الصيغة الرمزية: الفئة، ثم العامل، ثم البتات

اكتب الفئة أولاً. u هو المالك، وg هي المجموعة، وo هم جميع المستخدمين الآخرين، وa تعني الفئات كلها معاً. ثم اكتب العامل: يضيف + البتات، ويزيل - البتات، ويضبط = تلك الفئة على البتات التي تدرجها تماماً، ويمسح بقية بتاتها. ثم اكتب البتات نفسها، وهي r أو w أو x.

$ chmod 640 notes.txt
$ stat -c '%a %A %n' notes.txt
640 -rw-r----- notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txt
$ chmod g-r notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod o=r notes.txt
$ stat -c '%a %A %n' notes.txt
704 -rwx---r-- notes.txt

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

$ chmod u=rw,go=r notes.txt
$ stat -c '%a %A %n' notes.txt
644 -rw-r--r-- notes.txt
$ chmod go= notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt

يزيل go=، عند عدم كتابة أي شيء بعد علامة المساواة، كل البتات من المجموعة ومن جميع المستخدمين الآخرين. هذه هي الصيغة المناسبة لملف لا يجوز لأحد سوى مالكه قراءته، مثل الجزء الخاص من زوج مفاتيح SSH.

يمكن لـchmod أيضاً الإبلاغ عن التغييرات التي أجراها، وهذا مهم داخل script لا يراقب فيه أحد الشاشة.

chmod -v u+x notes.txt
chmod -v u+x notes.txt

يطبع -v سطراً لكل ملف أُعطي له. شغّل الأمرين وقارن السطرين على شاشتك: يسمّي السطر الأول الملف ويعرض نمط الصلاحيات قبل تغييره وبعده، بينما يعرض السطر الثاني النمط على أنه بقي كما هو، لأن البت المطلوب إضافته كان مضبوطاً مسبقاً. يطبع -c سطراً فقط عندما يتغيّر ملف فعلياً، لذلك فهو الخيار الأفضل للاحتفاظ به في سجل.

chmod 755 مقابل u+x: أي ترميز تستخدم؟

ابدأ بالملف نفسه مرتين، ثم قارن ما يتركه كل ترميز.

$ chmod 640 notes.txt
$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 640 notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txt

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

لا يأتي النمط الذي يبدأ به الملف الجديد من chmod على الإطلاق. بل يأتي من umask للعملية التي أنشأت الملف. شغّل umask وumask -S في الصدفة الخاصة بك لمعرفة القيمة المطبقة هناك. توقّع أن تختلف هذه القيمة بين التوزيعات، وبين صدفة تسجيل الدخول وخدمة systemd، وبين حساب وآخر. يحدد umask نمط كل ملف جديد، ولذلك فهو يحدد الحالة التي يبدأ منها الملف قبل تشغيل chmod.

ما الذي يفعله بت التنفيذ في دليل

هذا هو الالتباس الذي يستهلك أكبر قدر من الوقت. في الملف العادي، يعني بت التنفيذ أن النواة يمكنها تشغيل الملف. لا يحتوي الدليل على تعليمات، لذلك لا يوجد شيء يمكن تشغيله داخله. في الدليل، يعني بت التنفيذ الاجتياز: السماح بحل اسم داخل الدليل. للوصول إلى dir/file، تحتاج إلى هذا الإذن على dir. بت القراءة إذن منفصل، ويسمح بعرض أسماء العناصر الموجودة في الدليل. يمكنك امتلاك أحد الإذنين دون الآخر، ويصبح ذلك أسهل فهماً بعد أن تراه يحدث.

$ mkdir vault
$ printf 'hello\n' > vault/secret.txt
$ chmod 600 vault/secret.txt
$ chmod 100 vault
$ echo vault/*
vault/*
$ cat vault/secret.txt
hello

طبع الصَدَفة النمط كما هو دون تغيير، لأن توسيع vault/* يتطلب قراءة الدليل، ولأن نمط glob لا يطابق شيئاً يُمرَّر كنص حرفي بدلاً من إصدار خطأ. نجح cat أيضاً لأنك زوّدت الصَدَفة بالاسم بنفسك، وكان الاجتياز مسموحاً. بدّل البتين الآن.

$ chmod 400 vault
$ echo vault/*
vault/secret.txt
$ cat vault/secret.txt
cat: vault/secret.txt: Permission denied

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

$ chmod 500 vault
$ cat vault/secret.txt
hello

لماذا يؤدي استخدام chmod -R مع وضع رقمي إلى إتلاف شجرة

يمر -R عبر الشجرة بأكملها ويطبّق الوضع الذي تحدده على كل عنصر يصادفه. تحتاج الأدلة وملفات البيانات إلى بتات مختلفة، لذلك لا يمكن لرقم مطلق واحد أن يكون صحيحاً لكليهما. أنشئ شجرة صغيرة وراقب كيف يحدث الخطأ.

$ mkdir -p site/css
$ touch site/index.html site/css/main.css
$ printf '#!/bin/bash\necho hi\n' > site/deploy.sh
$ chmod 755 site site/css site/deploy.sh
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.sh

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

$ chmod -R 755 site
$ stat -c '%a %A %n' site/index.html site/css/main.css
755 -rwxr-xr-x site/index.html
755 -rwxr-xr-x site/css/main.css

لم يتعطل شيء، وهذه هي المشكلة. هذا الخطأ صامت، لذلك يبقى في التعليمات المنسوخة لسنوات. أصبح ملفان من ملفات البيانات يبدوان كأنهما برامج. يخزّن Git بت التنفيذ، لذلك يحمل commit التالي التغيير إلى كل من يستنسخ المستودع، وينقله rsync وtar إلى كل جهاز تنسخ إليه الشجرة.

الخطأ المتكرر الثاني واضح. طبّق وضعاً لا يتضمن بت التنفيذ على دليل، فيُغلق الدليل.

$ chmod 644 site
$ stat -c '%a %A %n' site
644 drw-r--r-- site
$ echo site/*
site/css site/deploy.sh site/index.html
$ cd site
bash: cd: site: Permission denied
$ cat site/index.html
cat: site/index.html: Permission denied

تظل الأسماء مدرجة لأن بت القراءة بقي مفعّلاً، لكن كل مسار يمر عبر الدليل يُغلق لأن بت التنفيذ لم يبقَ مفعّلاً. ينفّذ chmod -R 644 site ذلك على كل دليل في الشجرة باستخدام أمر واحد. ولا تكون النتيجة موحّدة دائماً، لأن chmod يحتاج إلى المرور عبر الأدلة نفسها التي يلغي صلاحية اجتيازها، لذلك تحقّق مما طُبّق فعلياً باستخدام find site -type d -exec stat -c '%a %n' {} + بدلاً من الافتراض. أعد الوضع السابق قبل المتابعة.

$ chmod 755 site
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/index.html
755 drwxr-xr-x site
644 -rw-r--r-- site/index.html

لا يوفر chmod التكراري طريقة للتراجع. لا يسجّل chmod ما استبدله، لذلك تقع مسؤولية الإصلاح عليك، إذ يتعين عليك إعادة بناء الأوضاع استناداً إلى ما تعتقد أنها كانت عليه. هذا هو العمل البطيء وغير المؤكد نفسه الذي يتطلبه إعادة بناء الملفات بعد تنفيذ rm -rf بالخطأ، والدرس هو نفسه: تحقّق من هدف الأمر التكراري قبل الضغط على Enter.

الحرف X الكبير: تنفيذ الأوامر على الأدلة، وليس على كل ملف

تقبل الأوضاع الرمزية X وكذلك x. يضبط X بت التنفيذ فقط حيث يكون ذلك منطقياً: على دليل، أو على ملف عادي يملك بت تنفيذ مسبقاً لفئة مستخدم ما. هذه هي القاعدة نفسها التي أردت من -R اتباعها.

$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.sh

أمر واحد يكفي، فبقيت الأدلة قابلة للعبور ولم تتغير ملفات البيانات. احتفظ البرنامج النصي ببت التنفيذ لأنّه كان يملكه مسبقاً، وهذا هو الجزء الثاني من قاعدة X. يقرأ X الوضع الذي يملكه الملف حالياً، لذلك لا يمكنه إعادة بت تنفيذ فُقدت جميع نسخه من الملف.

$ chmod 644 site/deploy.sh
$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site/deploy.sh
644 -rw-r--r-- site/deploy.sh
$ site/deploy.sh
bash: site/deploy.sh: Permission denied
$ chmod u+x site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
744 -rwxr--r-- site/deploy.sh
$ site/deploy.sh
hi

تعمل القاعدة نفسها في الاتجاه الآخر. يوسّع X بت تنفيذ يملكه الملف مسبقاً إلى فئة أخرى:

$ chmod go+X site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
755 -rwxr-xr-x site/deploy.sh

لذلك يُستخدم x الصغير مع ملف واحد محدد تريد جعله قابلاً للتنفيذ، بينما يُستخدم X لفحص شجرة كاملة. عندما تريد وضعاً دقيقاً لكل نوع بدلاً من قاعدة تعتمد على الوضع الحالي، اقسم عملية البحث باستخدام find.

find site -type d -exec chmod 755 {} +
find site -type f -exec chmod 644 {} +
chmod u+x site/deploy.sh

يحدّد -type d الأدلة، ويحدّد -type f الملفات العادية، لذلك يحصل كل نوع على الوضع المناسب له. يجمع -exec ... + مسارات متعددة في استدعاء واحد لـ chmod بدلاً من بدء عملية لكل ملف، وهذا مهم في شجرة تحتوي على آلاف الإدخالات. يستعيد البرنامج النصي بت التنفيذ في سطر منفصل، عن قصد.

تحقق من النتيجة قبل المغادرة

يبحث أمران عن الأخطاء المهمة بعد أي تغيير تكراري. يعرض الأمر الأول الأدلة التي لم يعد بإمكانك الدخول إليها.

find . -type d ! -perm -u+x

يعرض الأمر الثاني الملفات التي يمكن لأي حساب على الجهاز تعديلها.

find . -type f -perm -o+w

في -perm -o+w، تعني - في البداية هذه البتات على الأقل، ولذلك يطابق الأمر ملفاً تحتوي فئة o فيه على بت الكتابة، بصرف النظر عن البتات الأخرى المضبوطة. النتيجة المطلوبة هي ألا يعرض أي من الأمرين شيئاً. شغّل الأمرين من أعلى أي شجرة غيّرتها للتو باستخدام -R، وشغّل stat -c '%a %A %n' على المسارات القليلة التي قصدت تغييرها، لكي تتأكد من أن النمط الذي تعتقد أنك ضبطته هو النمط الذي يحتفظ به kernel فعلياً.

FAQ

ما الفرق بين chmod 755 و chmod u+x؟

الوضع الرقمي مطلق. فهو يكتب كل بتات الأذونات في الملف، لذلك تُعاد كتابة الفئات التي لم تفكر فيها أيضاً. أما الوضع الرمزي فهو تعديل. يضيف u+x بتاً واحداً للمالك ويترك كل بت آخر كما هو. استخدم الصيغة الرقمية عندما تعرف الحالة النهائية الدقيقة التي تريدها للملف. واستخدم الصيغة الرمزية عندما تريد إضافة شيء واحد أو إزالته. شغّل stat -c '%a %A %n' <file> قبل كل أمر وبعده، وسيظهر الفرق في المخرجات.

لماذا يُعد تشغيل chmod -R 755 على مجلد يحتوي على ملفات ويب فكرة سيئة؟

لأن -R يطبّق الوضع المطلق نفسه على المجلدات والملفات العادية، مع أن هذين النوعين يحتاجان إلى بتات مختلفة. يحتاج المجلد إلى بت التنفيذ حتى يمكن اجتيازه. أما ملفات البيانات مثل HTML وCSS فلا تحتاج إليه، ووضعها كملفات قابلة للتنفيذ يُسجّل كتغيير في git في الالتزام التالي، وينسخه rsync إلى الخادم التالي. استخدم chmod -R u=rwX,go=rX <dir> حتى يُطبَّق بت التنفيذ على المجلدات فقط، أو نفّذ العملية عبر find باستخدام -type d و-type f حتى يحصل كل نوع على وضعه الخاص.

ماذا يفعل بت التنفيذ في المجلد؟

إنه يمنح صلاحية الاجتياز، وليس التنفيذ. لا يوجد داخل المجلد شيء يمكن تشغيله. يتيح بت التنفيذ حلّ اسم داخل المجلد، لذلك تحتاج إليه في كل مجلد على طول المسار قبل أن تتمكن من فتح الملف الموجود في نهايته. أما بت القراءة فهو مستقل ويمنح صلاحية عرض الأسماء. يمكنك امتلاك أحدهما دون الآخر: عند امتلاك بت التنفيذ وحده، يمكنك فتح ملف تعرف اسمه مسبقاً، بينما لا تستطيع الصدفة توسيع نمط glob في ذلك المجلد. وعند امتلاك بت القراءة وحده، يمكنك رؤية الأسماء، لكن تفشل كل محاولة لفتح أحدها.

متى ينبغي أن أستخدم X الكبيرة بدلاً من x الصغيرة؟

استخدم X كلما كان الأمر عودياً. يضبط X بت التنفيذ على المجلدات، وعلى الملفات العادية فقط عندما يكون أحد بتات التنفيذ مضبوطاً مسبقاً. بذلك تجعل عملية واحدة شجرة الملفات قابلة للاجتياز دون تحويل ملفات البيانات إلى برامج. استخدم x الصغيرة عندما تشير إلى ملف واحد وتقصد ذلك الملف تحديداً. تجدر الإشارة إلى حد واحد: لا يستطيع X استعادة بت تنفيذ أُزيل بالفعل من كل بتات التنفيذ في ملف، لأنه لم يعد لديه بت يطابقه. أعد ضبط ذلك البت باستخدام chmod u+x <file>.

هل يغيّر chmod مالك الملف؟

لا. يغيّر chmod بتات الأذونات فقط. تحدد chown ملكية المستخدم، وتحدد chgrp ملكية المجموعة، ويتطلب تسليم ملف إلى مستخدم آخر حساب root. هذا مهم لأن الأذونات تُقرأ وفقاً للمالك والمجموعة المسجلين في الملف، وليس وفقاً لمن كتبه آخر مرة. شغّل stat -c '%U %G %a %n' <file> لعرض المالك والمجموعة والوضع معاً قبل أن تقرر أيّاً من الأوامر الثلاثة تحتاج إليه فعلاً.