שאלה מניעת עבודות כפולות כפולות


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

כדי לפתור את הבעיה עשיתי את התסריט לחפש את קיומו של קובץ מסוים ("lockfile.txt") ולצאת אם הוא קיים או touch אם לא. ללא שם: אבל זה הוא סמפור מחורבן למדי! האם יש נוהג טוב שאני צריך לדעת עליו? האם אני צריך לכתוב דמון במקום?


81
2017-11-09 11:32






תשובות:


ישנן כמה תוכניות להפוך את התכונה הזאת, לקחת את המטרד ואת באגים פוטנציאליים לעשות זאת בעצמך, ולהימנע מבעיה מנעול מעופש באמצעות הצאן מאחורי הקלעים, מדי (וזה סיכון אם אתה רק באמצעות מגע) . אני השתמשתי lockrun ו lckdo בעבר, אבל עכשיו יש flock(1) (בגירסאות חדשות של util-linux) שהוא נהדר. זה באמת קל לשימוש:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job

109
2017-11-09 11:57



lckdo הולך להיות מוסר מ moreutils, עכשיו הצאן (1) נמצא util-linux. וזה חבילה היא בעצם חובה במערכות לינוקס, אז אתה אמור להיות מסוגל להסתמך על נוכחותו של זה. לשימוש, להסתכל למטה. - jldugger
כן, הצאן הוא עכשיו האופציה המועדפת שלי. אני אפילו לעדכן את התשובה שלי כדי להתאים. - womble♦
האם מישהו יודע את ההבדל בין flock -n file command ו flock -n file -c command ? - Nanne
@Nanne, הייתי צריך לבדוק את הקוד כדי להיות בטוח, אבל הניחוש שלי משכיל זה -c מפעיל את הפקודה שצוין באמצעות פגז (לפי manpage), ואילו "חשוף"-c) פשוט execs הפקודה שניתנה. לשים משהו דרך הקליפה מאפשר לך לעשות כמו פגז דברים (כגון הפעלת פקודות מרובות מופרדות עם ; או &&), אבל גם פותח אותך להתקפות הרחבת פגז אם אתה משתמש קלט לא מהימן. - womble♦
זה היה ויכוח על (היפותטי) frequent_cron_job פקודה שניסתה להראות שהיא מנוהלת בכל רגע. הסרתי אותו מאז זה לא הוסיף שום דבר שימושי, וגרם בלבול (שלך, אם אף אחד אחר לא לאורך השנים). - womble♦


הדרך הטובה ביותר בקליפה היא להשתמש צאן (1)

(
  flock -x -w 5 99
  ## Do your stuff here
) 99>/path/to/my.lock

27
2017-11-09 11:45



אני לא יכול upvote שימוש מסובך של ניתוב מחדש fd. זה פשוט מדהים מדי. - womble♦
לא מנתח אותי בבש או ZSH, צריך לחסל את החלל בין 99 ו > ככה זה 99> /... - Kyle Brandt♦
@Javier: לא אומר שזה לא מסובך ו arcane, רק שזה מתועד, מסובך, ו arcane. - womble♦
מה יקרה אם אתה מפעיל מחדש את זה בזמן שזה פועל או לקבל את התהליך נהרג איכשהו? האם זה יהיה נעול לנצח? - Alex R
אני מבין את המבנה הזה יוצר מנעול בלעדי אבל אני לא מבין את המכניקה של איך זה נעשה. מה הפונקציה של '99' בתשובה זו? מישהו צריך להסביר את זה בבקשה? תודה! - Asciiom


בעצם, flock -n ניתן להשתמש במקום lckdo*, כך שתשתמש בקוד ממפתחי הקרנל.

בונים על דוגמה של womble, היית כותב משהו כמו:

* * * * * flock -n /some/lockfile command_to_run_every_minute

BTW, מסתכל על הקוד, כל flock, lockrun, ו lckdo לעשות בדיוק את אותו הדבר, אז זה רק עניין של אשר הוא הכי זמין לך.

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


21
2017-11-19 22:43





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

Lockfiles משמשים initscripts ועל ידי יישומים ושירותים רבים אחרים במערכות יוניקס.


2
2017-11-09 11:36



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


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


1
2017-11-09 11:45



אני מסכים עם זה בלבביות. אם יש לך משהו שצריך להפעיל מעת לעת, מה שהופך אותו daemon הוא "פטיש עבור פתרון אגוז". באמצעות lockfile כדי למנוע תאונות הוא פתרון הגיוני לחלוטין מעולם לא היתה לי בעיה להשתמש. - womble♦
@womble אני מסכים; אבל אני אוהב לשבור אגוזים עם פטישים! Youנות - wzzrd


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

אז, אם אתה לא רוצה לסבול lckdo או דומה, אתה יכול לעשות את זה:


PIDFILE=/tmp/`basename $0`.pid

if [ -f $PIDFILE ]; then
  if ps -p `cat $PIDFILE` > /dev/null 2>&1; then
      echo "$0 already running!"
      exit
  fi
fi
echo $$ > $PIDFILE

trap 'rm -f "$PIDFILE" >/dev/null 2>&1' EXIT HUP KILL INT QUIT TERM

# do the work


1
2017-11-09 14:33



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


דמון cron שלך לא צריך להיות מקומות עבודה אם המופעים הקודמים של אותם עדיין פועל. אני מפתח של daemon cron אחד dcron, ואנחנו מנסים במיוחד למנוע זאת. אני לא יודע איך ויקסי קרון או דמונים אחרים להתמודד עם זה.


1
2018-02-17 15:59