הגדרת קרונטאב למשימות תקופתיות בשרתים

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

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

מדוע משימות ב-cron מפסיקות להתבצע בשקט

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

הסיבה כמעט תמיד בסביבה: cron מפעיל את המשימה לא מהסשן שלכם, אלא במעטפת לא אינטראקטיבית עם סט מצומצם של משתנים. PATH אחר — והתוכנית לא נמצאת; ספריית עבודה אחרת — ונתיבים יחסיים מובילים לשום מקום; משתני גישה שלא הוזרקו — והסקריפט נופל באימות. איש אינו בודק את קוד היציאה, ועל הנפילה לומדים רק מדואר של משתמש-על, שאיש אינו קורא.

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

וכאשר משימה מתוזמנת עולה לדרך לעיתים קרובות יותר ממשך העבודה עצמה, המופעים חופפים זה לזה ומתחרים על אותם קבצים — כלפי חוץ הכול «ירוק», עד שהתוצאה נדרסת.

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

מה נותן הרצה מנוהלת של משימות תקופתיות

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

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

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

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

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

דרכים להרצת משימות לפי לוח זמנים: השוואת גישות

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

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

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

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

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

ביקורת והגדרה של cron: כיצד בנויה העבודה

cron סובל אי-סדר במשך שנים: משימות מועתקות במעבר שרתים, מכפילות זו את זו, נופלות בשקט — הפלט הולך לשום מקום, ועל התקלה לומדים מנתונים חסרים. אנו מפרטים סדר עבודה שבו כל שינוי הפיך, ולוח הזמנים נקרא תוך שתי דקות.

  1. ספירת מלאי של לוחות זמנים. אוספים משימות מקבצי המערכת והמשתמש — כולל אלו שמוגדרים בתצורת הפריסה ולכן אינם נראים ברשימה רגילה.
  2. ביקורת לוח הזמנים. בונים כרונולוגיה של היממה: מחפשים הרצות בו-זמניות, חפיפות של חלונות לילה ומשימות שזמן העבודה שלהן גדל ומכסה שכנות. מסמנים קריטיות, כפילויות ומועמדות למחיקה.
  3. בדיקת הסביבה. תהליך מ-cron אינו יורש את פרופיל המשתמש, לכן בודקים משתני סביבה, ספריית עבודה, הרשאות, נתיב למפרש וגישה לשירותים חיצוניים. מה שלא עובר בירושה — רושמים במשימה במפורש.
  4. סכימת הרצות. מכנסים את התוצאה לטבלה: מה רץ, באיזו תדירות, בשם מי, לאן כותב את התוצאה ואיך מדווח על שגיאה. הטבלה הופכת לנקודת השוואה בעת עריכות.
  5. הגדרת משימות. כותבים מחדש את לוח הזמנים לפי הסכימה: מפזרים הרצות בזמן, שמים נעילה מפני חפיפות למשימות ארוכות, קובעים הגבלת זמן ריצה וקוד יציאה מפורש.
  6. בדיקה. מריצים משימות ידנית ולפי לוח הזמנים, משווים יומנים וקודי יציאה, מדמים תקלה — שירות לא זמין, חוסר הרשאות, דיסק מלא.
  7. העברה לתמיכה. מוסרים סכימה, תיאורי משימות, נקודות התראה ונוהל חזרה לאחור, ומסכמים מי מבצע שינויים בלוח הזמנים ואיך הם מתועדים.

תצורות, סכימות ונוהלים: מה נשאר בפרויקט

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

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

מקרה בוחן: איך לוח הזמנים של משימות הפך לצפוי

מה היה לפני השינויים

צי של עשרות שרתים, לוחות זמנים נערכו ידנית ישירות על המכונות — דרך cron הסטנדרטי ו-crontab -e. חלק מהמשימות הוכפלו על שני צמתים, חלקן עלו על גבי ההרצה הקודמת: הגיבוי לא הספיק להסתיים, וההרצה הבאה כבר נלחמה על אותם קבצים.

על התקלה למדו לא מהתראה, אלא משאלת בוקר «למה אין דוח», — זמן הגילוי נמדד בשעות. שיעור ההרצות הכושלות עמד על 24%, וחלון הלילה של שירותים סמוכים עמד ללא שימוש עשרות דקות בשבוע.

מה שינו

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

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

מה יצא

שיעור התקלות ירד מ-24% ל-2% — את הנותרות נותנים שירותים חיצוניים, ולא לוח הזמנים עצמו. זמן הגילוי התקצר מכמה שעות לדקות: ההתראה מגיעה לפני שהמשתמש מבחין בהשלכות. את ההשבתה של תהליכים סמוכים בחלון הלילה הסרנו לחלוטין — המשימות כבר אינן חופפות בזמן ובקבצים.

מסגרת כזו הפכה להגדרת בסיס של השרת, ולא לאוסף הסכמות ידניות, והיא מועברת לסביבות חדשות בלי לכתוב מחדש.

מה לעשות אם cron כבר מוגדר, אבל המשימות נופלות?

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

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

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

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

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

תשובות לשאלות נפוצות על לוח זמנים של משימות

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

מה לעשות אם שתי משימות חופפות?

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

איך להתחשב באזורי זמן?

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

איך להבין שמשימה לא בוצעה?

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

איך להעביר משימות לשרת אחר?

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

מה לעשות בכמה שרתים?

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

נדון בלוח הזמנים של משימות ונחזור עם תוכנית עבודה

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

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

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

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