systemd

זהירות פוסט ארוך מאוד

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

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

מהפכה נוספת, היא החלפת הגישה של sysv כמעט לגמרי, עם מנהלי init שונים, כאשר זה שלוקח את הכי הרבה אש, וגם בשימוש הרב ביותר הוא systemd. זה השם שלו, כפי שהוא כתוב. והd בסוף מצייג כמובן את המילה daemon, כי הוא יושב ב pid 1, ומנהל את העליה של כל השאר, אחרי שמנהל האתחול (כדוגמת grub) מריץ אותו.

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

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

בניגוד ל init הישן, ולדעתי הלא טוב, systemd מביא איתו גישה חדשה, אך בראש ובראשונה הוא פותר בעיות שפעם לא נחשבו לכאלו, וחלקם גם לא התקיימו, אבל כיום הן כן – תאימות בכתיבת services בראש ובראשונה.

עם init, כל הפצה או משפחה של הפצות, היו מחזיקות כלי עזר משלה בנושא, כולל פונקציות bash למשל, וחלק עם csh. והנה בעיה ראשונה, מה קורה אם אני רוצה שיהיה לי למשל zsh או psh וכיוב', אבל אני לא רוצה להתקין bash או sh ?

אבל יותר מזה, כתיבת Daemon בכל הפצה, דרשה כתיבה שונה של בדיוק אותו הדבר, וככה יוצרי תוכנה היו נמנעים מכך לחלוטין, או היו מספקים גרסאות לDebian וגרסאות ל Redhat עבור init (למשל), אבל הפצות שעובדות שונה, ובכן הן היו צריכות לכתוב משהו משל עצמם, או לספק תאימות לאחת מההפצות הגדולות יותר.

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

עכשיו init עובד בתפיסה של runlevel. זה אומר שיש מספר בין 0 ל 6, כאשר כל מספר בטווח אומר כיצד הריצה תהיה בעצם. כאשר 6 זה לאתחל את המחשב, ו0 הוא halt, והשאר אומרים כיצד לרוץ לתוך המערכת, למשל 1 אומר שזה משתמש single user אשר נועד לבצע פעולות תחזוקה כאשר יש בעיה במערכת עצמה.

בברירת המחדל, היו ספריות (מערכת בשם rc) עם מספר ה runlevel הרצוי, ובתוכם סקריפטים אשר היו מתחילים באות S או באות K (אותיות גדולות) ואחריהם מספר בין 00 ל 99. המספר ייצג את החשיבות עליה, כלומר מתי בזמן עליה להריץ אותם ביחד למספרים אחרים, כאשר מספר נמוך יותר מתבצע לפני מספר גבוה יותר. ה S אומר לבצע את הסקריפט בזמן עליה, והK בזמן סגירה מסודרת של המערכת. הפירוש של S זה start והפירוש של K זה kill.

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

יש המון בעיות בגישה של init – מה קורה כש iptables למשל חייב לעלות רק כאשר הרשת עלתה, ומיד, לפני כל דבר אחר, אבל הרשת לא עלתה, ולמעשה זה אומר ש iptables לא יכול לעלות, כי אין למשל devices בשביל לעבור עליו עם החוקים ?
יותר מזה, נגיד ויש לי 2 סוגי תסריטי firewall אבל הם מתנגשים בהם, למשל csf מול Fail2Ban איך אני בכלל מסביר את זה למערכת ?

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

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

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

עכשיו יותר מזה, כאשר דימון נכשל לעלות, בinit, הייתי צריך להתחיל לחפש בלוגים שונים מה קרה, למשל אם אפצ'י לא הצליח לעלות, אני אחפש בלוגים של אפצ'י, אבל מה קורה כאשר אין לי לוג כזה, למשל הבעיה היא שאין לאפצ'י הרשאות לרשום את הלוג ?

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

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

למשל הפקודה הבאה:

$ journalctl -u NetworkManager -f -b 1b51005fb9814285b9ee872da51682f3

אומרת קודם כל להציג רק מידע של NetworkManager, גם אם נגיד מדובר ב dhclient שרץ דרכו, אקבל אותו ללוג, בנוסף אני אומר לו להתנהג כמו tail -f, כלומר להמשיך להדפיס מידע ולא לצאת, בנוסף, תציג רק מ boot עם המספר שלו. כאשר ניתן לקבל את המידע על המזהה של ה boot גם כן.

כבר לא צריך להתחיל לחפש אם זה בלוג בשם messages או אולי boot או אולי system או כל דבר אחר, אני מקבל ניהול מסודר לזה.

עוד בעיה קשה בלינוקס היא כרטיסי רשת שונים. קרה לי במספר שרתים, בהם כרטיס הרשת הוחלף, או נכנס כרטיס חדש, ופתאום מה שהיה מקודם eth0 הפך להיות eth3. עכשיו לך תשנה את כל הסקריפטים של route וכיוב' בנושא.
יותר מזה, יש לך תחביר שונה בין Debian לבין RedHat לניהול הזה של הרשתות וכרטיסי הרשת.

ב RedHat ניסו איכשהו להתמודד עם זה בגישה שבה אם אני שם את ה Mac אז הוא מנסה לשים את אותו שם של device, בפועל זה לא תמיד עובד, ועושה כאבי ראש.

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

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

הבעיה הזו, בנוסף לצורך בתקשורת עם תוכנות אחרות בצורה אחידה, זקוקה לIPC, כלומר תקשורת בין תוכנות שונות לבין systemd. כאשר systemd החליט במקום לממש מחדש משהו משל עצמו, או אולי להסתמך על סיגנלים, להשתמש במערכת קיימת שנמצאת הרבה זמן בשימוש בשם d-bus.

בזכות השימוש ב d-bus, עכשיו ניתן למשל ליצור מערכת login אשר לא תדבר בשפת systemd, אלא בשפת d-bus. מה שאומר שעכשיו המערכות יכולות להיות גנריות יותר, אבל מצד שני, לעבוד בשפה משותפת.
כלומר עכשיו אני יכול לקחת את KDM או GDM ולהתאים אותם ל systemd בצורה אחידה, והם יכולים לנהל הכל באמצעות systemd ו d-bus.

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

סיכום:

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

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

10 מחשבות על “systemd

  1. א

    לא הבנתי עדיין מספיק.
    לא נכנסתי לעומקם של דברים, אבל מבחינתי השאלה היא האם זו מערכת מורכבת שמספקת יכולות שונות בכיוונים שונים, או שזו מערכת פשוטה ודוקא בגלל הפשטות שלה מתאימה למגוון מצבים ויישומים. המערכת הראשונה לא טובה בעיני, בעוד השניה רצויה.
    דוגמה לדבר מתחום שונה – הרשתות לפני Ethernet היו מתוחכמות וחזקות בהרבה ממנה לכאורה, הן מבחינת ביצועים והן מבחינת יכולות. אבל, וזה האבל הגדול, הפשטות הגדולה של את'רנט, גרמה ליצרנים לבחור בו (משיקולי עלות), ולאחר מכן ראו שניתן לייצר בקלות מוצרים משלימים שמרחיבים את היכולות והאיכויות למקומות שרשתות אחרות בכלל לא חלמו עליהם.
    אם systemd זה האת'רנט של ניהול התהליכים – הרי שזה כלי מבורך. ולא – כדאי להתרחק לדעתי.

    1. ik_5 מאת

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

  2. צפריר כהן

    D זה כמובן 50 (כאשר V זה 5). זה משקף את דעתו של מחבר systemd על מה שהיה קודם (די בצדק. אבל הוא גם קצת שחצן ומעצבן).

    אני באופן כללי מרוצה מאוד מ־systemd אבל רוצה לציין כמה נקודות קטנות:

    1. הזכרת את NetworkManager. האם networkd מחליף את NetworkManager?

    2. השינוי בדביאן שיצר לך את eth3 נועד להשיג את אותה מטרה של enp0s25 – שם קבוע לכל כרטיס. במערכות שאנחנו מפיצים ביטלנו את השינוי הזה בעזרת ביטול חוק ה־udev האמור מכיוון שמדובר בפועל על אותו התקן גם אם כתובתו השתנתה.

    3. הגלגול הקודם של logind הוא ConsoleKit שלא היה קשור ל־systemd. גם הוא (כמו שאר הקיטים בני דורו) התבסס על ממשק d-bus.

    4. בעיית iptables לא נפתרת מאליה עם systemd. אבל הנה הפתרון הסטנדרטי במערכת המקורית של דביאן:
    * מה שצריך לרוץ לפני עליית איזשהו ממשק רשת הולך לסקריפט ב־‎/etc/rcS.d
    * מה שצריך לרוץ לפני עליית חיבור רשת מסוים מורץ ע"י hook script של אותה מערכת רשת. עם מדובר על ifupdown: הסקריפט נמצא ב־/etc/network/if-pre-up.d/. אם מדובר על NetworkManager, מדובר על /etc/NetworkManager/dispatcher.d/pre-up.d/
    * כל חבילה שמה את הסקריפטים שלה באופן עצמאי. האם צריכה להיות התנגשות בין החבילות השונות? שאלה טובה. הבעיה הזו קיימת באותה מידה עם systemd.

    5. בדביאן השקיעו כבר הרבה עבודה להבטיח ש־/bin/sh במערכת לא יהיה חייב להיות bash (ליתר דיוק: posix sh עם עוד כמה דרישות קטנות). יש לציין שאם תבטל את /bin/sh הרבה מאוד דברים לא יעבדו. לא רק סקריפטי האתחול.

    6. grub מריץ את ליבת מערכת ההפעלה (הקרנל). הליבה מריצה בסופו של דבר את התהליך הראשון. systemd עדיין לא מנסה להיות גם הליבה.

    1. ik_5 מאת

      1. אני עובד עם NetworkManager. אני לא אפשרתי את networkd, וכך למעשה בחרתי במשהו אחר במקום, זה חלק מהכוח של systemd.

      2. אצלי פשוט היתה תקלה בBIOS במקרה הזה, שהוא אמנם דיווח שהכרטיס זמין, אבל לא הדליק אותו (תיקנו עם עדכון לBIOS), אבל עד שמצאנו שזה המצב, הכנסנו כרטיס רשת PCI-E במקרה הזה, והמספור שונה. מכיר את החוקים ב udev, מצאתי שלא תמיד הם תופסים 😦

      4. מצטער אם כתבתי את זה בצורה שזה פותר. מן הסתם צריך ליצור unit שעובד נכון.
      אישית אני מעדיף את התפיסה של דביאן, אבל לצערי מרבית השרתים שאני עובד איתם הם עם CentOS ו RHEL.

    1. ik_5 מאת

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

  3. פינגבק: מזלגות נעוצים | לראות שונה

  4. פינגבק: סיכום אוגוסט פנגווין 2015 | לראות שונה

  5. פינגבק: נגנז בגנזך 23.10.2014: שערורית נעלמת, אייר גיטאר, systemd, קבוצתיות ביפן, חדרה, מחווה לאליוט סמית’ ועוד ועוד – ניימן

כתיבת תגובה

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