Claude لمسؤولي الأنظمة: 6 مهام يومية على الخادم
تعلّم كيف يساعدك Claude في قراءة سجلات وحدة فاشلة، وكتابة وحدات systemd، ومراجعة nginx وCompose، وما لا يجوز لصقه من مفاتيح وكلمات مرور.
Claude لمسؤولي الأنظمة: ابدأ بالنصيحة ثم بالتنفيذ
يعمل Claude بأفضل صورة كمراجع لمسؤولي الأنظمة. الصق مقتطفاً من سجل، أو ملف إعداد، أو أمراً لا تتعرّف إليه، أو نص خطأ، وستحصل على شرح يمكنك التحقق منه قبل تغيير أي شيء على الخادم. لا تكلّفك الإجابة الخاطئة شيئاً ما دمت لم تنفذها، لذلك فإن إبقاء النموذج في جانب تقديم النصيحة هو أساس السلامة بالكامل.
تتكرر ست مهام كل أسبوع على Linux VPS مستأجر (خادم خاص افتراضي). لكل مهمة أدناه نمط prompt فعّال، والأمر الذي يثبت صحة الإجابة، وحالة الفشل المتوقعة. لا تتطلب أي منها أن يتمكن النموذج من الوصول إلى خادمك. يمكنك اللصق من علامة تبويب في المتصفح أو من نافذة على سطح مكتبك، لأن يعمل Claude أصلاً على Linux كتطبيق سطح مكتب وواجهة CLI.
يهم الترتيب على خادم إنتاج: اقرأ الشرح، ونفّذ الفحص بنفسك، ثم قرر. الاستقلالية مناسبة على VM تجريبية. أما على الخادم الذي يقدّم الخدمة لعملائك، فالمراجعة أفضل، لأن النموذج لا يرى الحالة التي يبني تخمينه عليها.
ما يجب ألا تلصقه مطلقاً
كل ما يرد في الطلب يغادر خادمك. هناك أربع فئات يجب أن تبقى على الخادم:
- المفاتيح الخاصة:
~/.ssh/id_ed25519و/etc/ssh/ssh_host_*_key، وأي مفتاح TLS (أمان طبقة النقل) ضمن/etc/letsencrypt/live/. - ملفات بيانات الاعتماد:
.envو~/.aws/credentialsو/root/.docker/config.json، وكلمات مرور قاعدة البيانات الموجودة في أي ملف أو أي سطر سجل. - بيانات الحسابات:
/etc/shadowو/etc/gshadow. لا يحتاج أي سؤال من مسؤول النظام إلى تجزئة كلمة مرور للإجابة عنه. - أي بيانات تخص مستخدميك: عناوين البريد الإلكتروني، وصفوف الطلبات، وسجلات الطلبات التي تحتوي على ملفات تعريف ارتباط الجلسات أو PII (معلومات التعريف الشخصية).
المفاتيح العامة آمنة للصقها. أما المفاتيح الخاصة فليست آمنة، ويبدو الملفان متشابهين عند إلقاء نظرة سريعة، لذلك اقرأ السطر الأول قبل النسخ: الملف الذي يحتوي سطره الأول على BEGIN OPENSSH PRIVATE KEY لا تضعه مطلقاً في الطلب. يستحق التمييز الصحيح بين ملفات مفاتيح SSH عشر دقائق بمفرده.
نقّح البيانات قبل لصقها، بدلاً من الاعتماد على قدرتك على اكتشاف رمز واحد ضمن 200 سطر:
sudo journalctl -u myapp -n 200 --no-pager | sed -E 's/(token|secret|password|api[_-]?key)[=:][^[:space:]]+/\1=REDACTED/gI'هناك حالة خطرة خاصة بـDocker. يدرج docker compose config قيم .env في الناتج الذي يطبعه، لذلك يصبح هذا الناتج سراً حتى إذا لم يكن الملف الموجود على القرص سراً. استخدم docker compose config -q، فهو يتحقق من الصحة ولا يطبع شيئاً. لمعرفة السياسة الأوسع بشأن ما يُسمح للوكيل برؤيته، يشرح إبقاء الأسرار خارج وكلاء الذكاء الاصطناعي جانب البيئة.
المهمة 1: لماذا فشلت هذه الخدمة؟
ابدأ بالأمرين اللذين يحتويان على الإجابة:
systemctl status myapp.service --no-pager
sudo journalctl -u myapp.service -b -n 100 --no-pager -o short-isoألصق ناتج الأمرين مع السياق الذي لا يستطيع النموذج تخمينه: التوزيعة والإصدار، وما الذي غيّرته مؤخراً، وما إذا كانت الخدمة قد عملت من قبل، ومتى تعطلت. اطلب تحديد الآلية أولاً.
Ubuntu 24.04. كانmyapp.serviceيعمل بشكل سليم حتى عدّلت الوحدة قبل ساعة. إليكsystemctl statusوآخر 100 سطر من السجل. ما أول سطر يمثل خطأً فعلياً، وماذا يعني؟ لا تقدّم حلاً بعد.
إن عبارة "لا تقدّم حلاً بعد" تؤدي وظيفة مهمة في هذا الطلب. تخفي السجلات الفشل الأول بين محاولات إعادة التشغيل التي تسبب بها، ولذلك سيشرح النموذج آخر سطر يراه إذا طلبت منه تقديم حل. ويكون السطر المهم عادةً قبل الضجيج بنحو 20 سطراً.
تظهر الفائدة في سطر مثل Main PID: 1841 (code=exited, status=203/EXEC). تعني حالة الخروج 203/EXEC أن النواة لم تتمكن من تنفيذ الملف المحدد في ExecStart: إما أن المسار غير موجود، أو أن الملف موجود لكنه غير قابل للتنفيذ. كما ينتج السطر #! الذي يحدد مفسراً غير مثبت حالة الخروج نفسها. ويمكن اختبار كل ذلك باستخدام ls -l وhead -1.
نمط الفشل: اختلاق سبب. إذا ألصقت معلومات قليلة جداً، فسيسد النموذج الفجوة بتفسير عام، مثل "المنفذ مستخدم بالفعل". اسأل عندئذ: "أي سطر في المعلومات التي قدمتها يدعم ذلك؟" السبب الذي لا يستطيع أحد الإشارة إليه في النص ليس إلا تخميناً.
المهمة 2: صِغ ملف وحدة systemd أو إدخال cron
زوّده بالحقائق التي يحتاج إليها ملف الوحدة: الأمر الدقيق، والمستخدم الذي سيشغّله، ودليل العمل، وما إذا كان يجب أن ينتظر الشبكة، وما الذي ينبغي أن يحدث عند خروجه برمز غير صفري. ثم تحقّق من النتيجة قبل تفعيل أي شيء.
sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl start myapp.service
systemctl status myapp.service --no-pagerيحلّل systemd-analyze verify الملف بالطريقة التي يستخدمها systemd، ولذلك يكتشف ما قد تتجاوزه العين البشرية. يعرض التوجيه المكتوب خطأً /etc/systemd/system/myapp.service:7: Unknown key name 'Enviroment' in section 'Service', ignoring.. ويعرض الملف الثنائي المفقود Command /usr/local/bin/myapp is not executable: No such file or directory. لكن كلا الخطأين لا يظهر أثناء daemon-reload، ولذلك قد تُحمّل الوحدة بنجاح ثم تفشل فور تشغيلها.
يتكرر خطآن في الصياغة كثيراً. الأول هو After=network.target، الذي يعني فقط أن مكدس الشبكة أُعدّ، وليس أن عنواناً أصبح متاحاً. تفشل الخدمة التي ترتبط بعنوان IP محدد عند الإقلاع برسالة bind: Cannot assign requested address، ويكون الإصلاح هو Wants=network-online.target مع After=network-online.target. والثاني هو Type=simple لبرنامج يعمل كـdaemon: يتعامل systemd مع العملية الأولى باعتبارها الخدمة، ثم تخرج العملية الأب فوراً، فتُعلَّم الوحدة بأنها متوقفة بينما تستمر العملية الفعلية من دون إدارة. هذا هو الخطأ الذي يُرجح أن يقدمه لك نموذج، لأنه لا يستطيع معرفة ما إذا كان الملف الثنائي ينشئ عملية فرعية من الأمر وحده. لذلك من المفيد معرفة ما الذي تضمنه كل قيمة من Type= لـsystemd قبل قبول الصياغة.
بالنسبة إلى الجدولة، تحقّق منها بدلاً من قراءتها:
systemd-analyze calendar 'Mon *-*-* 04:00:00'يطبع ذلك الشكل الموحّد والوقت التالي الذي سيُنفَّذ فيه التعبير، ما يحسم أي خلاف حول معناه. إذا كنت تختار بين timer وcrontab، يشرح systemd services وtimers على VPS المفاضلة بينهما.
يتضمن Cron فخاً لن يحذرك منه أي نموذج ما لم تسأله. يشغّل Cron المهام ببيئة محدودة، ولذلك يكون PATH تقريباً /usr/bin:/bin ولا يُقرأ ملف تعريف shell مطلقاً. تفشل المهمة التي تعمل عند لصقها في الطرفية تحت cron برسالة /bin/sh: 1: docker: not found، لأن ذلك الملف الثنائي موجود في /usr/local/bin. استخدم المسارات المطلقة في crontab. إذا بدا إصرار ملف الوحدة على تحديد المستخدم والبيئة والتبعيات بالتفصيل نوعاً من التعقيد مقارنة بسطر crontab واحد، فتشرح المشكلات التي صُمم systemd لحلها سبب هذه التفاصيل.
المهمة 3: راجع ملف nginx أو Compose قبل تفعيله
هذه المهمة تحقق أفضل عائد. ألصق الملف، واذكر ما يفترض أن يفعله، واطلب شرحاً سطراً بسطر لما يفعله فعلياً.
يجب أن يقدّم هذا الـvhostexample.comعبر HTTPS، وأن يوجّه/apiإلى خدمة محلية على المنفذ 8080. أعد قراءته، واذكر أي شيء لا يطابق هذا الوصف.
ثم شغّل الأداة التي تتحقق من القواعد النحوية:
sudo nginx -t
docker compose config -qيعرض nginx -t الناتج nginx: configuration file /etc/nginx/nginx.conf test is successful، أو يذكر اسم الملف ورقم السطر، كما في nginx: [emerg] unknown directive "proxy_pas" in /etc/nginx/conf.d/app.conf:12. أما docker compose config -q فلا يعرض شيئاً عندما يُحلَّل الملف بنجاح، وقد يعرض رسالة مباشرة مثل yaml: line 7: did not find expected key عندما تخطئ في المسافات البادئة.
لا تتحقق أي من الأداتين من الغرض المقصود. يمكن لإعداد ينجح مع nginx -t أن يوجّه الطلبات إلى المنفذ الخطأ، أو يستمع على 0.0.0.0 بينما كنت تقصد 127.0.0.1. هنا تظهر فائدة النموذج، وهنا يفشل أيضاً: عندما تطلب منه إصلاح directive واحد، يعيد غالباً كتابة الملف بالكامل مع حذف اثنين من directives الخاصة بك دون تنبيه. اطلب الأسطر التي تغيّرت وسبب كل تغيير، ثم أجرِ التعديل يدوياً.
تحقق مما عرّضته فعلياً:
sudo ss -tulpnمن دون sudo سترى sockets التي تستمع، لكنك لن ترى العمليات التي تملكها. إذا فاجأك الناتج، فاقرأ ما هي المنافذ وكيف يربطها Linux. هذا شرح أقصر.
المهمة 4: اشرح الأمر غير المألوف قبل تشغيله
ألصق الأمر واطرح أربعة أسئلة عنه: ماذا يفعل كل خيار؟ ماذا يكتب؟ ماذا يحذف؟ ماذا يحدث إذا شغّلته مرتين؟ السؤال الأخير يكشف أضراراً أكثر من الأسئلة الأخرى.
خذ find /var/log -name '*.gz' -mtime +7 -delete مثلاً. توضح الإجابة الجيدة أن -mtime +7 يحسب فترات كاملة مدتها 24 ساعة ويتجاهل الجزء الكسري، لذلك يطابق الملفات التي مرّ على تعديلها 8 أيام على الأقل، وليس 7 أيام. وتوضح أيضاً أن find يقيّم تعبيره من اليسار إلى اليمين، لذلك فإن وضع -delete قبل -name يحذف كل شيء ضمن المسار الابتدائي. ترد هذه النقطة الثانية كتحذير في صفحة الدليل الخاصة بـfind، وقد تسببت في فقدان /var/log لدى بعض المستخدمين.
أو خذ rsync -a --delete /srv/app/ /backup/app/ مثلاً. تعني الشرطة المائلة اللاحقة في المصدر «محتويات هذا الدليل». إذا حذفتها، فستحصل على /backup/app/app/. وإذا أضفت --delete، فسيُحذف أي شيء موجود في الوجهة وغير موجود في المصدر. هذا صحيح عند إنشاء نسخة مطابقة، لكنه يسبب كارثة إذا كان مسار المصدر خاطئاً.
تحقق باستخدام الأداة، لا باستخدام النموذج:
rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7شغّل find من دون -delete، وستحصل على قائمة بدلاً من فقدان البيانات.
نمط الفشل: اختلاق الخيارات. يكون النموذج موثوقاً مع الأدوات التي تملك توثيقاً يمتد 30 عاماً، ويكون أضعف بكثير مع واجهات CLI الخاصة بالمورّدين (واجهات سطر الأوامر) ومع الأوامر الفرعية الحديثة، إذ قد ينتج خياراً يبدو صحيحاً تماماً لكنه غير موجود. يحسم --help الأمر خلال ثانية واحدة. ويُعد الاقتباس نقطة ضعف أخرى، لذلك عندما يغلّف أمر ما تعبير $(...)، اقرأ كيف يتوسع استبدال الأوامر قبل تشغيل الأمر بدلاً من الوثوق بالشرح.
المهمة 5: حوّل سجل shell إلى دليل إجراءات
لقد أمضيت ساعتين في تشغيل شيء بنجاح. هذه المعرفة موجودة في النص الظاهر في الطرفية، وستختفي الشهر المقبل.
history 200 > /tmp/session.txtاقرأ ذلك الملف واحذف كل سطر يحتوي على كلمة مرور أو token أو معرّف عميل قبل إرساله إلى أي مكان. يُعد سجل shell من أكثر الأماكن موثوقية للعثور على سر في جهاز Linux، لأن الجميع يكتب سراً مضمّناً في الأمر مرة واحدة على الأقل. اضبط HISTCONTROL=ignorespace في ~/.bashrc، وعندها لن يُكتب أي أمر تكتبه مع مسافة في بدايته إلى السجل إطلاقاً.
يطلب النص التوجيهي الذي ينتج دليلاً عملياً صالحاً إجراء اختبارات، وليس الخطوات فقط:
هذه جلسة shell حوّلت جهاز Debian 13 جديداً إلى تثبيت Postgres يعمل. اكتبها في صورة دليل إجراءات مرقّم. استخدم أمراً واحداً في كل خطوة. بعد كل خطوة، اذكر الأمر الذي يثبت نجاحها، واشرح شكل المخرجات السليمة. حدّد أي خطوة اعتمدت على مضيفي المحدد.
نمط الفشل: قصة مرتبة. تضمنت جلستك خطوة أخطأت فيها مرتين قبل إصلاحها، وهذه هي الخطوة التي يحذفها النموذج أثناء تنقيح النص، لأن السجل يبدو أنظف من دونها. قارن دليل الإجراءات بسجل shell، وأعد التصحيح إلى مكانه. كما أنه يختلق أوامر تحقق تبدو معقولة، لذلك نفّذ كل اختبار يكتبه قبل حفظ الملف. إذا كان دليل الإجراءات يتناول الإقلاع الأول، فقارنه مع الدقائق العشر الأولى على VPS جديد حتى لا تدوّن نسخة أسوأ من مشكلة سبق حلها.
المهمة 6: حوّل رسالة خطأ إلى إصلاح
الصق السلسلة النصية الدقيقة، والأمر الذي أنشأها، والتغيير الوحيد الذي أجريته قبل ظهورها. اطلب قائمة مرتبة بالأسباب، مع أمر يميّز كل سبب عن غيره. فهذا يحوّل الإجابة إلى شيء يمكن اختباره.
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use). رتّب الأسباب المحتملة، وقدّم أمراً واحداً لكل سبب يؤكده أو يستبعده.
آلية حدوث هذا الخطأ واضحة: هناك عملية أخرى تشغل المنفذ 80 بالفعل، وsudo ss -tulpn | grep ':80 ' يحددها. غالباً تكون هذه العملية نسخة ثانية من nginx master بقيت بعد فشل إعادة التحميل، أو Apache جرى سحبه كتَبعية وبدأ تشغيله حِزمه الخاصة.
نمط الفشل: إصلاح يعمل عن طريق إخفاء السبب. يؤدي chmod 777 و--privileged وتعطيل SELinux وتشغيل الخدمة بصلاحيات root إلى اختفاء الخطأ. ارفض أي إصلاح يوسّع الصلاحيات إلى أن يوضح النموذج سبب فشل الصلاحية المقيّدة. هذا التوضيح هو الإجابة الفعلية. أما الحل البديل فلا يؤدي إلا إلى إسكات الخطأ.
ما الذي يخطئ فيه باستمرار
- لا يستطيع رؤية خادمك. كل إجابة تعتمد على ما ألصقته، ولن يخبرك بأن المقتطف كان قصيراً جداً.
- يخلط بين الإصدارات. تتغير أسماء الحزم والخيارات الافتراضية بين التوزيعات والإصدارات، بينما يعمم النموذج بينها جميعاً.
- يكون فصيحاً عندما يخطئ. تبدو الآلية المختلقة تماماً مثل الآلية الصحيحة، ولذلك يأتي كل سبب مذكور أعلاه مع أمر يختبره.
- يفقد تسلسل الموضوع في الجلسات الطويلة. تتوقف الحقائق المذكورة في بداية محادثة مدتها ساعتان عن التأثير في الإجابات في نهايتها.
المشكلة الأخيرة عملية أكثر من كونها مشكلة في النموذج، وإدارة السياق في جلسة Claude Code طويلة هي الحل العملي: اجعل الجلسات أقصر، وخصص كل جلسة لمهمة واحدة.
وضع الوكيل على الخادم نفسه
كل ما سبق يقتصر على النسخ واللصق، لذلك لا يلمس النموذج جهازك. عند تشغيله على الخادم وقراءته للملفات وتنفيذه للأوامر، يتغير شكل المخاطر: فقد يؤدي أمر خاطئ الآن إلى إيقاف خدمة. امنحه مستخدماً خاصاً غير مميّز بدلاً من root، وأبقِه خارج خادم الإنتاج أثناء تعلّمك لطريقة عمله، وأنشئ لقطة أولاً. يشرح تشغيل Claude Code بأمان على VPS آلية العزل ونموذج الصلاحيات. أما تشغيل Claude Code داخل tmux فيعالج الجانب الآخر، لأن انقطاع جلسة SSH (secure shell) ينهي وكيلاً يعمل في الواجهة الأمامية قبل إتمام مهمته. أنشئ الحساب بالطريقة نفسها التي تنشئ بها أي حساب خدمة، كما يوضّح المستخدمون ذوو أقل قدر من الصلاحيات على VPS.
FAQ
هل يستطيع Claude قراءة سجلات خادمي مباشرة؟
ليس بمفرده. لا ترى واجهة الدردشة إلا النص الذي تلصقه فيها. أمّا Claude Code، عند تشغيله على الخادم كأداة لسطر الأوامر، فيستطيع قراءة الملفات وتشغيل الأوامر بالصلاحيات الممنوحة للمستخدم الذي بدأ تشغيله، وهذا قرار ثقة أكبر. في سؤال دعم عادي، يكون لصق مقتطف منقّح من 100 سطر أسرع وأكثر أماناً من منح وكيل وصولاً إلى shell.
ما الذي يجب ألا ألصقه من خادم أبداً؟
المفاتيح الخاصة، وملفات .env ومخازن بيانات الاعتماد الأخرى، و/etc/shadow، وأي بيانات تخص المستخدمين. احذف الرموز المميزة من مقتطفات السجل قبل أن تصل إلى prompt. هناك حالة غير واضحة: يضمّن ناتج docker compose config قيم .env الخاصة بك داخل الناتج، لذلك استخدم docker compose config -q، إذ يتحقق من الملف ولا يطبع شيئاً.
هل من الآمن السماح لـ Claude بتشغيل أوامر على VPS مخصّص للإنتاج؟
عامله كمسؤول جديد لا يملك أي سياق: لا بأس بالقراءة، لكن الكتابة تحتاج إلى مراجعة. في بيئة الإنتاج، اطلب منه شرح الأمر ثم شغّله بنفسك. إذا أردت أن ينفّذ وكيل الأوامر فعلاً، فامنحه حساباً مخصصاً غير ذي صلاحيات مرتفعة ومن دون sudo شامل، وابدأ على خادم staging حيث يؤدي الخطأ إلى إعادة بناء الخادم بدلاً من انقطاع الخدمة.
لماذا يقترح Claude flag غير موجود؟
لأنه يتنبأ بنص معقول، ويبدو flag المعقول مثل flag حقيقي. يحدث ذلك غالباً مع CLIs الخاصة بالمورّدين ومع subcommands الأحدث، حيث تكون الوثائق المتاحة للنموذج محدودة أو تكون قد تغيّرت منذ ذلك الحين. يُرجع كل من --help وman النتيجة الحاسمة، وأي أمر يحذف البيانات أو يستبدلها يستحق تجربة dry run أولاً.
كيف أتحقق من systemd unit قبل تفعيلها؟
شغّل sudo systemd-analyze verify /etc/systemd/system/myapp.service. يحلّل الملف باستخدام parser الخاص بـsystemd، ويبلغ عن التوجيهات غير المعروفة مع أرقام أسطرها، ويشير إلى وجود binary من ExecStart مفقود أو غير قابل للتنفيذ. ثم شغّل daemon-reload وstart، واقرأ systemctl status قبل أن enable هذه الوحدة، لأن unit التي تُحمَّل بنجاح قد تفشل عند تشغيلها لأول مرة.