SSD Nodes Learn 🎉 VPS החל מ־$5.50/חודש
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-08-13

Claude למנהלי מערכות: אוטומציה של משימות שרת שגרתיות

גלו כיצד להשתמש ב-Claude לניתוח לוגים, כתיבת קבצי systemd וסקירת הגדרות nginx. למדו מהן שש המשימות הבטוחות לביצוע ומהם סוגי המידע הרגיש שאסור להדביק לעולם ב-prompt.

Claude עבור מנהלי מערכות: תחילה ייעוץ, לאחר מכן ביצוע

Claude עבור מנהלי מערכות פועל בצורה המיטבית ככלי לסקירה. אתם מדביקים קטע מתוך לוג, קובץ תצורה, פקודה שאינכם מזהים או מחרוזת שגיאה, ומקבלים הסבר שניתן לבדוק לפני שמבצעים שינוי כלשהו בשרת. תשובה שגויה אינה גורמת לנזק כל עוד לא הרצתם אותה, לכן שמירה על המודל בצד המייעץ של הקו הזה היא כל מודל הבטיחות.

בכל שבוע עולות שש משימות בשרת VPS (שרת וירטואלי פרטי) מבוסס Linux. לכל אחת מהמשימות להלן יש תבנית prompt שעובדת, הפקודה שמאמתת את התשובה, ומצב הכשל שצריך לצפות לו. אף אחת מהן אינה דורשת מהמודל גישה לשרת שלכם.

הסדר חשוב בשרת production: קראו את ההסבר, הריצו את הבדיקה בעצמכם, ורק אז החליטו. אוטונומיה היא בסדר בשרת VM לניסויים. בשרת שמשרת את הלקוחות שלכם, הסקירה מנצחת, כיוון שהמודל אינו יכול לראות את המצב (state) שעליו הוא מנחש.

מה אסור להדביק לעולם

כל מה שמוזן ב־prompt עוזב את השרת שלך. ארבע קטגוריות חייבות להישאר על השרת:

  • מפתחות פרטיים: ~/.ssh/id_ed25519, /etc/ssh/ssh_host_*_key, וכל מפתח TLS (ר"ת של transport layer security) תחת /etc/letsencrypt/live/.
  • קובצי הרשאות: .env, ~/.aws/credentials, /root/.docker/config.json, וסיסמאות מסדי נתונים בכל קובץ או שורת לוג.
  • נתוני חשבון: /etc/shadow ו־/etc/gshadow. אין שאלת ניהול מערכת שדורשת hash של סיסמה כדי לקבל מענה.
  • כל מה ששייך למשתמשים שלך: כתובות אימייל, שורות הזמנה, לוגים של בקשות המכילים session cookies או PII (מידע מזהה אישי).

מפתחות ציבוריים בטוחים לשיתוף. מפתחות פרטיים אינם בטוחים, ושני סוגי הקבצים נראים דומים במבט חטוף, לכן קרא את השורה הראשונה לפני ההעתקה: קובץ שהשורה הראשונה שלו מכילה BEGIN OPENSSH PRIVATE KEY לעולם לא אמור להיכנס לתוך prompt. שמירה על סדר במפתחות ה-SSH שלך היא משימה ששווה להקדיש לה עשר דקות.

בצע עריכה (redaction) לפני ההדבקה, במקום לסמוך על עצמך שתזהה אסימון (token) בודד בתוך 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, שמאמתת את התצורה מבלי להדפיס דבר. לגבי המדיניות הרחבה יותר בנוגע למה מותר לסוכן לראות, מניעת זליגת סודות לסוכני AI מכסה את הצד של סביבת העבודה.

משימה 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 עבד כשורה עד שערכתי את ה-unit לפני שעה. להלן systemctl status ו-100 השורות האחרונות מה-journal. איזו שורה היא השגיאה האמיתית הראשונה, ומה היא אומרת? אין עדיין תיקון.

המשפט "אין עדיין תיקון" מבצע עבודה חשובה בהנחיה זו. לוגים קוברים את הכשל הראשון תחת הניסיונות החוזרים שהוא גרם להם, לכן מודל שמתבקש לספק תיקון יסביר את השורה האחרונה שהוא ראה. השורה שחשובה היא בדרך כלל עשרים שורות מעל הרעש.

התמורה היא שורה כמו Main PID: 1841 (code=exited, status=203/EXEC). סטטוס יציאה 203/EXEC אומר שה-kernel לא הצליח להריץ את הקובץ שצוין ב-ExecStart: או שהנתיב לא קיים, או שהקובץ קיים אך אינו ניתן להרצה. שורת #! המציינת מפרש (interpreter) שאינו מותקן תפיק את אותו סטטוס. כל אלו ניתנים לבדיקה באמצעות ls -l ו-head -1.

דפוס כשל: סיבה מומצאת. אם תדביקו מעט מדי, המודל ימלא את החלל במשהו גנרי, כמו "הפורט כבר בשימוש". התרופה היא שאלה אחת אחורה: "איזו שורה ממה שסיפקתי תומכת בזה?". סיבה שאף אחד לא יכול להצביע עליה בטקסט היא ניחוש.

משימה 2: יצירת קובץ unit עבור systemd או רשומה ב-cron

ספקו את הנתונים הנדרשים לקובץ ה-unit: הפקודה המדויקת, המשתמש שמריץ אותה, תיקיית העבודה, האם עליו להמתין לרשת, ומה עליו לעשות במקרה של יציאה עם קוד שגיאה. לאחר מכן, ודאו את תקינות הקובץ לפני הפעלתו.

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 עושה זאת, ולכן הוא מזהה שגיאות שעין אנושית עלולה להחמיץ. הנחיה (directive) שגויה תציג /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, וזו הסיבה שקובץ unit יכול להיטען בהצלחה ועדיין להיכשל ברגע ההרצה.

שתי טעויות נפוצות חוזרות על עצמן שוב ושוב. הראשונה היא After=network.target, שמשמעותה רק שחבילת הרשת הוגדרה, ולא שכתובת IP אכן קיימת. שירות שמנסה להיקשר (bind) לכתובת IP ספציפית ייכשל בעת האתחול עם bind: Cannot assign requested address, והפתרון הוא Wants=network-online.target בשילוב עם After=network-online.target. השנייה היא Type=simple עבור תוכנית שמבצעת daemonize: ‏systemd מתייחס לתהליך הראשון כאל השירות, תהליך האב מסתיים מיד, וה-unit מסומן כמת בעוד התהליך האמיתי ממשיך לרוץ ללא ניהול.

עבור תזמון, בדקו אותו במקום לקרוא אותו:

systemd-analyze calendar 'Mon *-*-* 04:00:00'

פקודה זו מדפיסה את הצורה המנורמלת ואת הפעם הבאה שהביטוי יופעל, מה שמכריע כל ויכוח לגבי משמעותו. אם אתם מתלבטים בין timer לבין crontab, המדריך שירותי systemd ו-timers ב-VPS מפרט את השיקולים.

ל-cron יש מלכודת שאף מודל לא יזהיר אתכם מפניה אלא אם תשאלו. Cron מריץ משימות עם סביבה מינימלית, כך ש-PATH הוא בערך /usr/bin:/bin ופרופיל ה-shell שלכם לעולם לא נקרא. משימה שעובדת כשמדביקים אותה ב-terminal נכשלת תחת cron עם /bin/sh: 1: docker: not found, כיוון שהקובץ הבינארי נמצא ב-/usr/local/bin. השתמשו בנתיבים מלאים (absolute paths) בתוך crontabs.

משימה 3: סקירת קובץ Nginx או Compose לפני העלייה לאוויר

משימה זו מניבה את התוצאות הטובות ביותר. הדביקו את הקובץ, ציינו מה הוא אמור לעשות, ובקשו פירוט שורה-אחר-שורה של מה שהוא מבצע בפועל.

ה-vhost הזה אמור להגיש את example.com מעל HTTPS ולבצע proxy ל-/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 כאשר ההזחה (indentation) שלכם שגויה.

אף אחד מהכלים הללו לא בודק כוונה. תצורה שעוברת את nginx -t עדיין יכולה לבצע proxy לפורט הלא נכון, או להאזין ב-0.0.0.0 כאשר התכוונתם ל-127.0.0.1. הפער הזה הוא המקום שבו המודל מוכיח את ערכו, אך זהו גם המקום שבו הוא עלול להיכשל: כאשר מתבקש לתקן הוראה אחת, הוא לעיתים קרובות מחזיר את כל הקובץ כשהוא כתוב מחדש, תוך השמטה שקטה של שתיים מההוראות שלכם. בקשו את השורות ששונו ואת הסיבה לכל שינוי, ולאחר מכן בצעו את העריכה ידנית.

אמתו מה חשפתם בפועל:

sudo ss -tulpn

ללא sudo אתם רואים את ה-sockets המאזינים אך לא את התהליכים שבבעלותם. אם הפלט הזה מפתיע אתכם, מהם פורטים וכיצד Linux מקשרת אותם היא קריאה קצרה ומומלצת.

משימה 4: הסבר פקודה לא מוכרת לפני הרצתה

הדביקו את הפקודה ושאלו ארבע שאלות עליה: מה עושה כל דגל (flag), מה היא כותבת, מה היא מוחקת, ומה קורה אם מריצים אותה פעמיים. השאלה האחרונה חושפת נזק פוטנציאלי רב יותר מהאחרות.

קחו לדוגמה את find /var/log -name '*.gz' -mtime +7 -delete. תשובה טובה תסביר ש־-mtime +7 סופר יממות מלאות של 24 שעות ומתעלם מהשארית, ולכן הוא יתאים לקבצים בני שמונה ימים לפחות ולא שבעה. היא גם תציין ש־find מעריך את הביטוי שלו משמאל לימין, כך שהעברת -delete לפני -name תמחק את כל מה שנמצא תחת נתיב ההתחלה. הנקודה השנייה הזו מופיעה בדף ה-man של find כאזהרה, והיא עלתה לאנשים ב־/var/log שלהם.

או קחו את rsync -a --delete /srv/app/ /backup/app/. הלוכסן (slash) בסוף המקור אומר "התוכן של תיקייה זו". הסירו אותו ותקבלו את /backup/app/app/. הוסיפו את --delete וכל מה שנמצא ביעד וחסר במקור יוסר; זהו מצב תקין עבור שיקוף (mirror), אך אסון כאשר נתיב המקור שגוי.

אמתו מול הכלי, לא מול המודל:

rsync -a --delete --dry-run /srv/app/ /backup/app/ | head -20
find /var/log -name '*.gz' -mtime +7

הריצו את find ללא -delete ותקבלו רשימה במקום אובדן נתונים.

מצב כשל: הזיית דגלים (flag hallucination). המודל אמין בכלים בעלי תיעוד של שלושים שנה, אך חלש משמעותית מול ממשקי שורת פקודה (CLI) של ספקים ופקודות משנה חדשות; במקרים אלו הוא עלול לייצר דגל שנשמע הגיוני לחלוטין אך אינו קיים. --help פותר זאת בשנייה. ציטוטים (quoting) הם נקודת תורפה נוספת, לכן כאשר פקודה עוטפת ביטוי $(...), קראו את כיצד החלפת פקודה מתרחבת לפני הרצת הפקודה במקום לסמוך על ההסבר.

משימה 5: הפיכת היסטוריית ה-shell למדריך עבודה (runbook)

בילית שעתיים בפתרון בעיה מסוימת. הידע הזה נמצא כרגע ב-scrollback של הטרמינל שלך, והוא ייעלם בחודש הבא.

history 200 > /tmp/session.txt

קרא את הקובץ ומחק כל שורה המכילה סיסמה, token או מזהה לקוח לפני שאתה מעביר אותו למקום אחר. היסטוריית ה-shell היא אחד המקומות האמינים ביותר למציאת סודות במערכת Linux, כיוון שכל אחד מקליד סוד בשורת הפקודה לפחות פעם אחת. הגדר את HISTCONTROL=ignorespace בתוך ה-~/.bashrc שלך, ופקודה שמתחילה ברווח לא תיכתב להיסטוריה כלל.

ה-prompt שמייצר מדריך עבודה שמיש דורש בדיקות, לא רק שלבים:

זהו תיעוד של סשן shell שהפך שרת Debian 13 חדש להתקנה עובדת של Postgres. כתוב זאת כמדריך עבודה ממוספר. פקודה אחת לכל שלב. לאחר כל שלב, ציין את הפקודה שמוכיחה שהפעולה הצליחה ותאר כיצד נראה פלט תקין. סמן כל שלב שהיה תלוי במאפיינים ספציפיים של המארח שלי.

מצב כשל: סיפור מסודר מדי. הסשן שלך הכיל שלב שביצעת פעמיים לפני שהצליח, וזה בדיוק השלב שהמודל ינסה להחליק, כיוון שהתמליל נראה נקי יותר בלעדיו. השווה את המדריך מול ההיסטוריה שלך והחזר את התיקון. המודל גם נוטה להמציא פקודות אימות שנראות הגיוניות, לכן הרץ כל בדיקה שהוא כותב לפני שאתה שומר את הקובץ. אם המדריך עוסק בהגדרה ראשונית של שרת, קרא אותו מול עשר הדקות הראשונות ב-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 שני שנותר מאחור עקב טעינה מחדש (reload) שנכשלה, או ב-Apache שהותקן כחלק מתלות והופעל על ידי החבילה שלו.

מצב כשל: פתרון שעובד על ידי הסתרת הסיבה. chmod 777, --privileged, השבתת SELinux, והרצת השירות כ-root – כולם גורמים לשגיאה להיעלם. סרבו לכל פתרון שמרחיב הרשאות עד שהמודל יסביר מדוע ההרשאה המצומצמת נכשלה. הסבר זה הוא התשובה האמיתית. פתרון עוקף (workaround) רק משתיק את השגיאה.

מה הוא מפספס, באופן עקבי

  • הוא לא יכול לראות את השרת שלכם. כל תשובה היא פונקציה של מה שהדבקתם, והוא לא יציין אם הקטע שסיפקתם קצר מדי.
  • הוא סוטה בגרסאות. שמות חבילות ודגלי ברירת מחדל משתנים בין הפצות ובין גרסאות, והמודל מבצע ממוצע ביניהם.
  • הוא רהוט גם כשהוא טועה. מנגנון מומצא נקרא בדיוק כמו מנגנון תקין, וזו הסיבה שכל סיבה לעיל מלווה בפקודה שבודקת אותה.
  • הוא מאבד את הרצף בשיחות ארוכות. עובדות מתחילת שיחה של שעתיים מפסיקות להשפיע על התשובות בסופה.

הנקודה האחרונה היא בעיית עבודה יותר מאשר בעיית מודל, ו-ניהול הקשר בשיחת Claude Code ארוכה הוא הפתרון המעשי: שיחות קצרות יותר, משימה אחת בכל פעם.

התקנת הסוכן על השרת עצמו

כל מה שצוין לעיל ניתן להעתקה ולהדבקה, כך שהמודל לעולם לא ניגש למכונה שלכם. ברגע שהוא רץ על השרת, קורא קבצים ומריץ פקודות, אופי הסיכון משתנה: פקודה שגויה עלולה כעת להשבית שירות. הקצו לו משתמש ללא הרשאות מנהל (unprivileged user) במקום להריץ אותו כ-root, הרחיקו אותו משרת הייצור עד שתלמדו את אופן פעולתו, ובצעו snapshot לפני כן. המדריך הרצה בטוחה של Claude Code על גבי VPS מפרט בנושא ארגז חול (sandboxing) ומודל ההרשאות. המדריך הפעלת Claude Code בתוך tmux פותר את החלק השני, שכן ניתוק של סשן SSH (secure shell) קוטע סוכן שרץ בחזית באמצע עבודתו. בנו את החשבון כפי שהייתם בונים כל חשבון שירות, כפי שמוסבר ב-משתמשים בעלי הרשאות מינימליות ב-VPS.

FAQ

האם Claude יכול לקרוא את לוגי השרת שלי ישירות?

לא באופן עצמאי. ממשק הצ'אט רואה רק את הטקסט שאתם מדביקים לתוכו. Claude Code, המופעל על השרת ככלי שורת פקודה, יכול לקרוא קבצים ולהריץ פקודות בהרשאות המשתמש שהפעיל אותו, מה שמהווה החלטת אמון משמעותית יותר. עבור שאלת תמיכה רגילה, הדבקה של קטע ערוך באורך 100 שורות היא מהירה ובטוחה יותר מאשר מתן גישת shell לסוכן.

מה לעולם אין להדביק מתוך שרת?

מפתחות פרטיים, קובצי .env ומאגרי הרשאות אחרים, /etc/shadow, וכל מידע השייך למשתמשים שלכם. ערכו (Redact) אסימונים (tokens) מתוך קטעי לוג לפני שהם מגיעים ל-prompt. מקרה אחד שאינו מובן מאליו: הפלט של docker compose config מכיל את ערכי ה-.env שלכם כשהם מוטמעים בתוכו, לכן השתמשו ב-docker compose config -q, אשר מאמת את הקובץ ואינו מדפיס דבר.

האם זה בטוח לתת ל-Claude להריץ פקודות על VPS בסביבת ייצור (Production)?

התייחסו אליו כאל מנהל מערכת חדש ללא הקשר: קריאה היא בסדר, אך כתיבה דורשת בקרה. בסביבת ייצור, בקשו הסבר והריצו את הפקודה בעצמכם. אם אתם בכל זאת מעוניינים שסוכן יבצע פעולות, העניקו לו חשבון ייעודי ללא הרשאות מיוחדות (unprivileged) וללא גישת sudo גורפת, והתחילו בסביבת staging שבה טעות תעלה לכם בבנייה מחדש במקום בהשבתה.

מדוע Claude מציע דגל (flag) שלא קיים?

מכיוון שהוא חוזה טקסט סביר, ודגל סביר נראה בדיוק כמו דגל אמיתי. זה קורה בעיקר עם כלי שורת פקודה של ספקים (vendor CLIs) ותתי-פקודות חדשות, שבהם התיעוד שעליו התבסס המודל דל או השתנה מאז. --help ו-man הם הקובעים, וכל פקודה שמוחקת או דורסת קבצים ראויה להרצה בבדיקה (dry run) תחילה.

כיצד בודקים יחידת systemd לפני שמפעילים אותה?

הריצו את sudo systemd-analyze verify /etc/systemd/system/myapp.service. הפקודה מנתחת את הקובץ באמצעות המנתח (parser) של systemd עצמו, מדווחת על הנחיות לא מוכרות עם מספרי השורות שלהן, ומסמנת קובץ בינארי של ExecStart שחסר או שאינו ניתן להרצה. לאחר מכן הריצו את daemon-reload, start, וקראו את systemctl status לפני שתבצעו enable, כיוון שיחידה שנטענת בצורה תקינה עדיין עלולה להיכשל בהרצה הראשונה שלה.