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

ההיסטוריה של systemd: למה הוא הפך לסטנדרט בלינוקס?

גלו מדוע SysV init נכשל בניהול תלויות ובתהליכי רקע, וכיצד systemd השתמש ב-control groups כדי להחליף את Upstart ו-launchd בתוך ארבע שנים בלבד בכל הפצות הלינוקס.

מדוע systemd ניצח

ההיסטוריה של systemd מתחילה בשני דברים ש־SysV init לא ידע לבצע. ל־SysV init (מערכת ה-init מסוג System V, מערכת העלייה ש־Linux ירשה מ־AT&T Unix) לא הייתה דרך לתאר תלויות של שירות, ולא הייתה דרך לדעת אילו תהליכים שייכים לשירות מרגע שהחל לפעול. מערכת systemd סיפקה מענה לשני האתגרים הללו באמצעות יכולות ליבה (kernel) שסקריפט shell אינו יכול להגיע אליהן: קבוצות בקרה (control groups) למעקב אחר תהליכים, ו-sockets מאזינים שנפתחו מראש לצורך קביעת סדר העלייה. שאר הסיפור הוא האופן שבו שני המענים הללו התפשטו לשאר מרחב המשתמש (userland), ושם החלו ההתנגדויות – וחלקן אכן היו מוצדקות.

מה SysV init עשה בפועל

במערכת SysV, תהליך PID 1 (מזהה תהליך 1, התהליך הראשון שהקרנל מפעיל) קרא את /etc/inittab, בחר runlevel, והריץ את הסקריפטים עבור אותו runlevel. הסקריפטים שכנו ב-/etc/init.d/. קישורים סימבוליים ב-/etc/rc3.d/ קבעו אילו מהם ירוצו ובאיזה סדר, כך ש-/etc/rc3.d/S20nginx הצביע על /etc/init.d/nginx ונקרא עם הארגומנט start.

#!/bin/sh
### BEGIN INIT INFO
# Provides:          nginx
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
### END INIT INFO

case "$1" in
  start)
    start-stop-daemon --start --quiet --pidfile /run/nginx.pid \
      --exec /usr/sbin/nginx
    ;;
  stop)
    start-stop-daemon --stop --quiet --retry TERM/30/KILL/5 \
      --pidfile /run/nginx.pid
    ;;
esac

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

התוכנית rc הריצה כל סקריפט בתורו והמתינה לסיומו. סקריפט שנתקע למשך 30 שניות בהמתנה לכתובת רשת עיכב את כל תהליך ה-boot ב-30 שניות, גם עבור שירותים שכלל אינם ניגשים לרשת.

כותרת ה-LSB (Linux Standard Base) בראש הסקריפט הייתה ניסיון לתקן זאת מבפנים. Debian 6.0 בשנת 2011 הפכה את insserv לברירת המחדל: היא קראה את Required-Start מכל סקריפט, בנתה גרף, ומספרה מחדש את הקישורים הסימבוליים. Debian יכלה אז להריץ סקריפטים בלתי תלויים בו-זמנית בעזרת startpar. זה עזר, אך לא פתר את הבעיה העמוקה יותר. התלות עדיין התבססה על סיום ריצה של סקריפט. החזרת 0 על ידי S20nginx משמעותה שפונקציית shell סיימה בהצלחה. אין זה אומר ש-nginx מקבל חיבורים.

חמישה דברים ששום סקריפט init לא יכול היה לפתור

  • עלייה במקביל. סידור לפי שם קובץ יוצר סדר ליניארי על פני כל השירותים במכונה, ולכן זמן העלייה איטי כסכום כל חלקיו.
  • מוכנות. סקריפט התחלה מסיים את פעולתו ברגע שהתהליך פוצל (fork), ולא כשהשירות מסוגל לשרת בקשות; לכן, הסקריפט הבא בתור מתחיל לעיתים קרובות מוקדם מדי.
  • ניטור (Supervision). תהליך מבצע fork פעמיים והתהליך האב מסיים, מה שמנתק אותו מהטרמינל ומעביר את האחריות עליו ל-PID 1. מערכת ה-init רואה תהליך בן שמסיים ואין לה קישור אמין לתהליך שנותר בחיים.
  • הפעלה לפי דרישה. inetd (שרת העל של האינטרנט) יכול היה להפעיל שירות עם הגעת חיבור, אך זו הייתה מערכת נפרדת עם קובץ תצורה משלה, והיא לא ביצעה שום פעולה בנוגע לסדר העלייה של שאר המערכת.
  • בקרת משאבים. שום דבר בסקריפט init לא יכול היה להגביל את צריכת הזיכרון של שירות או את נתח ה-CPU שלו. ulimit הוחל על תהליך בודד ו-nice נגע רק ב-scheduler, כך שתהליך בן שיצא משליטה נראה כמו כל תהליך אחר במכונה.

פער הניטור הוא זה שהסב נזק ביומיום. קובץ ה-PID היה הפתרון העקיף: השירות כתב את ה-process ID שלו ל-/run/nginx.pid, ופונקציית העצירה קראה את הקובץ בחזרה. אם השירות נהרג בצורה אלימה, הקובץ נשאר במקומו. ה-kernel עשוי היה לעשות שימוש חוזר באותו מספר עבור תהליך אחר, ו-start-stop-daemon --stop --pidfile שלח אות (signal) לכל מה שהחזיק במספר הזה באותו רגע. קובץ PID מיושן הוא הדרך שבה סקריפט init הורג את התהליך הלא נכון.

launchd פתר את בעיית ה-socket תחילה

חברת Apple הפיצה את launchd ב-Mac OS X 10.4 בשנת 2005, והוא נכתב על ידי Dave Zarzycki. תהליך אחד החליף את init, rc, xinetd, crond ו-watchdogd.

הרעיון שהיה ראוי לאימוץ הוא socket activation. ה-launchd יוצר כל socket מאזין תחילה, ורק לאחר מכן מפעיל את ה-daemons. לקוח שמתחבר ל-daemon שטרם עלה לא מקבל שגיאת connection refused, כיוון שה-kernel מחזיק את החיבור בתור ה-backlog של אותו socket עד שה-daemon קורא ל-accept(). סדר העלייה בין שני daemons מפסיק להיות משהו שעל אדם להגדיר. ה-socket מטפל בכך.

ה-launchd נבנה על גבי Mach IPC (תקשורת בין-תהליכית), השייך ל-kernel מסוג XNU של Apple ואין לו מקבילה ב-Linux. העברת הקוד לא הייתה מעשית מעולם. הרעיון חצה את הגבולות בכל זאת.

Upstart הפך אירועים ליחידת העבודה

Upstart של Canonical, שנכתב על ידי Scott James Remnant, הופץ ב-Ubuntu 6.10 באוקטובר 2006. Fedora 9 עד Fedora 14 השתמשו בו, וכך גם RHEL 6 ו-Chrome OS. הוא החליף את ה-runlevel באירוע, כאשר כל job הגדיר אילו אירועים יפעילו ויעצרו אותו.

# /etc/init/example.conf
start on filesystem and net-device-up IFACE!=lo
stop on runlevel [!2345]
respawn
respawn limit 10 5
exec /usr/local/bin/exampled

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

השנייה היא מעקב. Upstart עקב אחר daemon שיוצר תהליכי בן (forking) על ידי ספירת קריאות fork() עם ptrace, שהוגדרו כ-expect fork או expect daemon. אם טועים במספר ה-forks, Upstart מפקח על תהליך שכבר הסתיים, או ממתין ל-fork שכבר התרחש. התסמין הוא ש-initctl start נתקע ללא שגיאה, מצב שקובץ ה-job לא מאפשר להסביר.

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

חשיבה מחדש על PID 1, אפריל 2010

ב-30 באפריל 2010 פרסם Lennart Poettering פוסט בשם "Rethinking PID 1". Kay Sievers עבד איתו על הפרויקט. הטיעון כלל ארבעה חלקים:

  • הפעלה מופחתת. שירותים רבים יכולים להמתין עד שמישהו יבקש אותם בפועל.
  • הפסקת הגדרת סדר פעולות במקום שבו socket יכול לרמוז עליו. פתיחת כל ה-sockets במעבר אחד, ולאחר מכן הפעלת הכל בבת אחת.
  • מעקב אחר תהליכים באמצעות control groups במקום קובצי PID.
  • תיאור שירות בקובץ הצהרתי, כך שתיאור אחד יעבוד בכל הפצה.

הגרסה הראשונה שוחררה באותה שנה. Fedora 14 הציעה את systemd כאופציה בנובמבר 2010, ו-Fedora 15 הפכה אותו לברירת המחדל במאי 2011.

מדוע cgroups הפכו את הניהול לאמין

cgroup (קבוצת בקרה) הוא רכיב בליבת המערכת (kernel) לקיבוץ תהליכים, אשר הוטמע ב־Linux 2.6.24 בשנת 2008. systemd מציב כל שירות בתוך cgroup משלו. תהליך בן יורש את ה־cgroup של תהליך האב שלו, ותהליך ללא הרשאות מיוחדות אינו יכול לצאת ממנו בעצמו. לכן, טכניקת double forking אינה מסתירה דבר: PID 1 מחזיק בכל עת את הקבוצה המדויקת של תהליכים השייכים ליחידה. עצירת שירות משמעותה הריגת כל מה שנמצא בתוך ה־cgroup שלו, וזה בדיוק מה ש־KillMode=control-group מבצע כברירת מחדל.

systemctl status מדפיס את הקבוצה הזו:

● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-08-11 09:14:22 UTC; 3min ago
   Main PID: 1042 (nginx)
      Tasks: 3 (limit: 4653)
     Memory: 6.1M (peak: 7.4M)
     CGroup: /system.slice/nginx.service
             ├─1042 "nginx: master process /usr/sbin/nginx"
             ├─1043 "nginx: worker process"
             └─1044 "nginx: worker process"

הבלוק הזה הוא התשובה המלאה לבעיית קובצי PID מיושנים. אין קובץ שיכול להתיישן, כיוון שהרשימה היא מצב של ה־kernel.

אותו עץ נושא עמו גם מגבלות, כיוון ש־cgroups נבנו במקור עבור ניהול משאבים (accounting) עוד לפני שמישהו השתמש בהם למעקב. MemoryMax=, CPUQuota= ו־TasksMax= הם שורות בודדות כל אחד. הגדרת מגבלת זיכרון ומעבד קשיחה לשירות היא כיום פעולה של קובץ drop-in, בעוד שבשנת 2009 זה היה דורש patch לסקריפט shell שאף אחד לא טרח לכתוב.

מדוע כל ההפצות ביצעו מעבר בין 2011 ל-2015

  • Fedora 15, מאי 2011.
  • openSUSE 12.1, נובמבר 2011.
  • Mageia 2, מאי 2012.
  • Arch Linux, ברירת מחדל להתקנות חדשות מאוקטובר 2012.
  • RHEL 7, יוני 2014.
  • SLES 12, אוקטובר 2014.
  • Debian 8, אפריל 2015.
  • Ubuntu 15.04, אפריל 2015.

הסיבות היו ברובן טכניות ומשעממות, וזו הסיבה שהמעבר היה מהיר.

  • קובץ unit אחד עובד בכל הפצה, לכן פרויקטים במעלה הזרם (upstream) החלו לספק קובץ .service, והפצות הפסיקו לתחזק סקריפט shell נפרד לכל חבילה בכל גרסה.
  • מעקב אחר סשן שולחן עבודה עבר ל-systemd-logind לאחר ש-ConsoleKit הפסיק לקבל תחזוקה בסביבות 2012. GNOME נזקק ל-logind, לכן הפצה ללא systemd נאלצה למצוא תחליף. התחליף הזה, elogind, הוא logind של systemd שחולץ ומתוחזק בנפרד.
  • udev, מנהל ההתקנים, מוזג לעץ המקור של systemd באפריל 2012. הפצות שסיפקו את udev עקבו כעת אחר המאגר של systemd. בתגובה, Gentoo יצרה fork בשם eudev.
  • מכולות (containers) הפכו מעקב תהליכים אמין ומגבלות לכל שירות לחשובים יותר, שכן שניהם תכונות של cgroup. השאלה איזה מנהל שירותים (supervisor) מחזיק בתהליך של מכולה נותרה רלוונטית בכל פעם שאתם גורמים ל-Docker Compose לעלות מחדש לאחר אתחול.

ההחלטה של Debian הייתה הרועשת ביותר. הוועדה הטכנית הצביעה בפברואר 2014, התוצאה הייתה תיקו, והיו"ר, Bdale Garbee, הטיל את קולו המכריע לטובת systemd. ימים ספורים לאחר מכן הודיעה Ubuntu כי תלך בעקבות Debian במקום להמשיך עם Upstart. קבוצת מפתחי Debian יצרה fork להפצה בשם Devuan בנובמבר 2014 ושחררה את Devuan 1.0 במאי 2017.

ההתנגדויות, מוצגות בהגינות

היקף. פרויקט אחד מפיץ כיום את PID 1, את ה־daemon של הלוגים, ניהול session של התחברות, מנהל ההתקנים, daemon להגדרת רשת, פותר DNS (מערכת שמות מתחם), לקוח NTP (פרוטוקול זמן רשת), מריץ מכולות ומטען אתחול (boot loader). ההגנה המקובלת, לפיה מדובר בקבצים בינאריים נפרדים שאין חובה להתקין, היא נכונה אך אינה עונה על ההתנגדות. ברגע שסביבת שולחן עבודה זקוקה ל־logind, ו־logind משוחרר מעץ המקורות של systemd, הבחירה אינה חופשית עוד. זה מה שהמושג "צימוד" (coupling) אומר בטיעון הזה, וזה אכן קרה.

היומן הבינארי. journald כותב בפורמט בינארי מאונדקס במקום בטקסט פשוט. אתם מקבלים יכולות שטקסט מעולם לא הציע: סינון לפי יחידה (unit) ולפי עדיפות, שדות מובנים, ומטא-דאטה שהתוכנית השולחת אינה יכולה לזייף, כיוון ש־journald מתעד את ה־unit ואת ה-cgroup בעצמו. journalctl -u nginx -p err --since "-1h" מחליף שימוש ב־grep עם ביטוי רגולרי של תאריך. למחיר הזה יש משמעות ממשית. במכונה שאינה עולה, לא ניתן לקרוא את הלוג עם less מתוך shell של מצב הצלה. במקום זאת, מפנים את journalctl לדיסק המעוגן:

sudo journalctl --directory /mnt/var/log/journal --boot -1 --priority err

יש כאן מלכודת שנייה שתופסת אנשים פעם אחת. journald שומר לוגים ב-/run/log/journal, כלומר בזיכרון, אלא אם כן /var/log/journal קיים. במכונה שבה הוא לא קיים, ל-journalctl -b -1 אין מה להציג לאחר אתחול, שזה בדיוק הרגע שבו הייתם זקוקים לו. בדקו ותקנו זאת:

journalctl --disk-usage
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

journalctl --disk-usage אמור כעת לדווח על יומנים מאורכבים תחת /var/log/journal. אם אתם רוצים גם טקסט פשוט, הגדירו את ForwardToSyslog=yes בתוך /etc/systemd/journald.conf והשאירו את rsyslog מותקן.

יכולת ניפוי שגיאות (debug) של האתחול. כאשר יחידה נתקעת, הקונסולה מציגה שורה אחת ותו לא:

[  *** ] A start job is running for Wait for Network to be Configured (1min 32s / no limit)

הכלים להתקדם מעבר לכך אכן קיימים: systemctl list-jobs בזמן שהיא תקועה, systemd-analyze blame ו-systemd-analyze critical-chain לאחר מכן, ו-systemd.log_level=debug בשורת הפקודה של ה-kernel. הגרסה ההוגנת של התלונה היא שסקריפט init יכול היה להיקרא מתחילתו ועד סופו על ידי כל מי שהכיר sh, בעוד שיחידה תקועה דורשת לדעת לאיזו מתוך תריסר פקודות לגשת. זהו מחיר ממשי. הוא משולם פעם אחת לכל מנהל מערכת, והוא שולם על ידי מנהלי מערכת רבים בו-זמנית.

ברירת מחדל שמשתנה עבור כולם. גרסה 230 של systemd בשנת 2016 שינתה את ברירת המחדל של logind כך שתהליכי משתמש שנותרו מאחור ייהרגו בעת התנתקות. תהליכי tmux ו-screen מנותקים היו מתים כאשר ה-session שהפעיל אותם הסתיים. הפצות הפיצו את KillUserProcesses=no בתוך /etc/systemd/logind.conf, והתשובה הנתמכת היא loginctl enable-linger <user>. ברירת מחדל אחת בפרויקט אחד שינתה הרגל שמיליוני אנשים הסתמכו עליו, וזה מה ש"יותר מדי מה-userland במקום אחד" אומר בפועל.

תלות כברירת מחדל היא שטח פנים לאבטחה. במרץ 2024, הדלת האחורית ב-xz-utils כוונה כלפי sshd ב-Debian וב-Ubuntu. גרסת ה-upstream של OpenSSH אינה מקשרת את libsystemd. אותן הפצות ביצעו patch כדי ש-sshd יוכל לדווח על מוכנות ל-systemd, ו-libsystemd משך פנימה את liblzma, שם שכנה הדלת האחורית. פרוטוקול המוכנות עצמו הוא datagram בודד שנשלח ל-socket ששמו ב-$NOTIFY_SOCKET, כך שמעולם לא נדרשה עבורו ספרייה. התגובה של systemd הייתה לטעון ספריות דחיסה עם dlopen, כך שהן אינן מקושרות עוד כברירת מחדל. סוג דומה של באג מציג את אותה צורה: בשנת 2017 ערך User= שהתחיל בספרה טופל כשגוי והיחידה רצה כ-root במקום להיכשל, כך ששגיאת הקלדה הפכה להסלמת הרשאות. גרסאות מאוחרות יותר מסרבות להפעיל את היחידה.

היסטוריה בשורת הפקודה של systemctl שלכם

כל בעיה שצוינה לעיל היא כעת הנחיה אחת בקובץ שניתן לקרוא.

  • אתחול טורי הפך ל-After= ול-Wants=, ו-systemd-analyze critical-chain מציג מה עיכב בפועל את האתחול שלכם.
  • מוכנות הפכה ל-Type=notify, שבו השירות כותב READY=1 ל-$NOTIFY_SOCKET כשהוא מסוגל לשרת בקשות. Type=forking עם PIDFile= עדיין קיים עבור דמונים ישנים, וזהו הסוג שנכשל עם start operation timed out. Terminating. כאשר קובץ ה-PID לעולם אינו מופיע.
  • ניטור הפך ל-cgroup, לכן Restart=on-failure עם RestartSec= מחליף סקריפט עטיפה, ו-StartLimitBurst= עוצר לולאת קריסה מלהמשיך לרוץ לנצח.
  • inetd הפך ליחידת .socket שיושבת לצד יחידת ה-.service.
  • ulimit הפך ל-MemoryMax=, CPUQuota= ו-TasksMax=.
  • השורה su - appuser -c בסקריפט init הפכה ל-User=, NoNewPrivileges=yes ו-ProtectSystem=strict, כך ש-הרצת שירות כמשתמש ללא הרשאות מיוחדות היא צורת ברירת המחדל של יחידה ולא עבודה נוספת.
[Unit]
Description=Example API
Wants=network-online.target
After=network-online.target postgresql.service
Requires=postgresql.service

[Service]
Type=notify
ExecStart=/usr/local/bin/exampled
Restart=on-failure
RestartSec=2
MemoryMax=512M
CPUQuota=50%
TasksMax=128
User=exampled
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
StateDirectory=exampled

[Install]
WantedBy=multi-user.target

שורה אחת בקובץ הזה היא הטעות שכולם עושים פעם אחת. Requires=postgresql.service היא דרישה, לא סדר פעולות: היא מציינת שהיחידה שלכם תיכשל אם Postgres ייכשל, והיא לא אומרת להפעיל את Postgres קודם. ללא After=postgresql.service שניהם מתחילים באותו רגע, והשירות שלכם מתחבר לפורט ששום דבר לא מאזין בו עדיין. השניים נפרדים בכוונה, כי לעיתים רוצים אחד ללא השני. ProtectSystem=strict מעגן את מערכת הקבצים במצב קריאה בלבד עבור שירות זה, וזו הסיבה ש-StateDirectory= קיים: הוא נותן לשירות נתיב אחד לכתיבה תחת /var/lib.

המקום הברור ביותר לראות את 2005 על שרת 2026 הוא SSH ב-Ubuntu 24.04, שמפיצה את systemd 255 נכון לאוגוסט 2026. ssh.service מופעל באמצעות socket כברירת מחדל: ssh.socket מחזיק את ה-socket המאזין, ו-sshd מתחיל כאשר מגיעה התחברות. לכן ל-Port 2222 ב-/etc/ssh/sshd_config אין השפעה, מכיוון ש-sshd אינו התהליך שפתח את הפורט. השינוי שייך ליחידת ה-socket.

sudo systemctl edit ssh.socket
[Socket]
ListenStream=
ListenStream=2222

ה-ListenStream= הריק מנקה את הערך שעבר בירושה מהיחידה הארוזה. השאירו אותו בחוץ ותקבלו את שני הפורטים, מכיוון ש-systemd משרשר לרשימה במקום להחליף אותה. לאחר מכן החילו ובדקו, תוך שמירה על session שני של SSH פתוח כל הזמן:

sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
sudo ss -lntp | grep 2222

ss אמור להציג socket אחד בפורט 2222 בבעלות systemd, לא בבעלות sshd. זהו התכנון של launchd, עשרים שנה מאוחר יותר, על ה-VPS שלכם. אם אתם מעדיפים את ההתנהגות הישנה, sudo systemctl disable --now ssh.socket ואחריו sudo systemctl enable --now ssh.service יתנו לכם sshd שרץ זמן רב וקורא שוב את Port מהתצורה שלו.

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

FAQ

מדוע הפצות Linux החליפו את SysV init ב־systemd?

מסיבות הנדסיות ותחזוקתיות. SysV init קבע את סדר השירותים לפי שם הקובץ, מה שמהווה מיקום ולא תלות, והוא איבד מעקב אחר תהליכי daemon שביצעו fork מהתהליך הראשי, מה שגרם לקובצי PID ישנים להרוג את התהליך הלא נכון. מערכת systemd פתרה את בעיית הסדר באמצעות socket activation והנחיות תלות, ופתרה את בעיית המעקב באמצעות control groups. הסיבה התחזוקתית הכריעה את המהירות: קובץ unit אחד עובד בכל הפצה, לכן פרויקטים במעלה הזרם (upstream) סיפקו קובץ .service, ומתחזקי ההפצות הפסיקו לכתוב סקריפט shell לכל חבילה. Fedora 15 עברה למערכת זו במאי 2011, ו־Ubuntu 15.04 הייתה האחרונה מבין ההפצות הגדולות שעשתה זאת, באפריל 2015.

האם systemd הוא קובץ בינארי ענק אחד?

לא. עץ המקור בונה תוכניות נפרדות רבות. ה־PID 1 הוא /usr/lib/systemd/systemd, בעוד ש־journald, logind ו־udevd הם תהליכים נפרדים עם קבצים בינאריים משלהם; הריצו את ls /usr/lib/systemd/ כדי לראות אותם במערכת שלכם. הביקורת שנותרה נוגעת לצימוד הגרסאות ולא לגודל הבינארי: תוכניות אלו משוחררות יחד וחולקות ממשקים פנימיים, לכן הפצות נוטות לקחת אותן כסט, ותוכנות כמו GNOME החלו לצפות ל־logind באופן ספציפי.

האם אני עדיין יכול להריץ Linux ללא systemd?

כן. Devuan מספקת את sysvinit, ב־Gentoo ברירת המחדל היא OpenRC, ב־Void משתמשים ב־runit, ב־Alpine משתמשים ב־busybox init עם OpenRC, ו־Slackware שומרת על סקריפטים בסגנון BSD. המחיר הוא עבודה על תאימות. תוכנות שולחן עבודה המצפות ל־logind זקוקות ל־elogind, שהוא ה־logind של systemd המתוחזק כחבילה עצמאית, וכמות גדולה והולכת של תוכנות שרת מסופקות כיום רק עם קובץ .service, כך שעליכם לכתוב ולתחזק את סקריפט העלייה בעצמכם.

מדוע ה־journal הוא בינארי ולא קובץ טקסט פשוט?

מכיוון ש־journald מאחסן שדות מובנים עם אינדקס, מה שמאפשר סינון לפי unit, סינון לפי עדיפות, ומטא-דאטה שהתוכנית השולחת אינה יכולה לזייף: journald מתעד את ה־unit, ה־cgroup וה־UID האמיתי בעצמו במקום לסמוך על שורת הלוג. המחיר הוא שצריך את journalctl כדי לקרוא אותו, גם ממערכת הצלה, שם מפנים אותו לכונן המעוגן בעזרת journalctl --directory /mnt/var/log/journal. אם ברצונכם גם בטקסט, הגדירו את ForwardToSyslog=yes בתוך /etc/systemd/journald.conf.

מה החליף את עריכת סקריפט ה־/etc/init.d שלי?

קבצי Drop-in. אל תערכו את ה־unit בתוך /usr/lib/systemd/system/, מכיוון ששדרוג חבילה ידרוס אותו. הריצו את sudo systemctl edit nginx.service ו־systemd ייצור את /etc/systemd/system/nginx.service.d/override.conf, אשר ממוזג מעל ה־unit של החבילה. הפקודה systemctl cat nginx.service מציגה את התוצאה הממוזגת, ו־systemd-delta מפרטת כל דריסה (override) במערכת. לאחר כל עריכה ידנית, הריצו את sudo systemctl daemon-reload, אחרת הפקודה הבאה תדפיס Warning: The unit file, source configuration file or drop-ins of nginx.service changed on disk.

#systemd#linux#init#sysvinit#history