systemd کی تاریخ اور اس کی کامیابی کی وجہ
SysV init کی دو بنیادی حدود، Upstart اور launchd کی ابتدائی کوششیں، اور وہ 4 سال جن میں تقریباً ہر distribution نے systemd اپنایا۔ درست اعتراضات بھی جانیں۔
systemd کیوں کامیاب ہوا
systemd کی تاریخ دو ایسی صلاحیتوں سے شروع ہوتی ہے جو SysV init فراہم نہیں کر سکتا تھا۔ SysV init، یعنی System V init، startup system ہے جو Linux نے AT&T Unix سے حاصل کیا، اور اس میں یہ بیان کرنے کا کوئی طریقہ نہیں تھا کہ کوئی service کن چیزوں پر منحصر ہے۔ اس میں یہ معلوم کرنے کا بھی کوئی طریقہ نہیں تھا کہ service شروع ہونے کے بعد کون سے processes اسی service سے متعلق ہیں۔ systemd نے دونوں مسائل ایسے kernel features کے ذریعے حل کیے جن تک shell script رسائی حاصل نہیں کر سکتی: processes کو track کرنے کے لیے control groups، اور startup order طے کرنے کے لیے پہلے سے open کیے گئے listening sockets۔ باقی تاریخ اس بات کی ہے کہ یہ دونوں حل userland کے دوسرے حصوں تک کیسے پھیلے۔ اعتراضات اسی مرحلے پر شروع ہوئے، اور ان میں سے کئی اعتراضات درست تھے۔
SysV init نے حقیقت میں کیا کیا
SysV سسٹم پر PID 1 (process ID 1، یعنی kernel کے شروع کردہ پہلے process) نے /etc/inittab کو پڑھا، ایک runlevel منتخب کیا، اور اس runlevel کے scripts چلائے۔ یہ scripts /etc/init.d/ میں موجود ہوتے تھے۔ /etc/rc3.d/ میں موجود symbolic links یہ طے کرتے تھے کہ کون سے scripts چلیں گے اور کس ترتیب سے چلیں گے۔ اسی لیے /etc/rc3.d/S20nginx، /etc/init.d/nginx کی طرف اشارہ کرتا تھا اور اسے start argument کے ساتھ چلایا جاتا تھا۔
#!/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
;;
esacS20nginx میں موجود 20 ایک position ہے، dependency نہیں۔ اس کا مطلب ہے کہ یہ script S19 کے بعد اور S21 سے پہلے چلتا ہے۔ یہ نہیں بتاتا کہ ایسا کیوں ہے۔ اس لیے کوئی نظام اس کی جانچ نہیں کر سکتا، اور نہ ہی کسی انسان کے یہ فیصلہ کیے بغیر دو غیر متعلق scripts کو محفوظ طور پر بیک وقت چلا سکتا ہے کہ ایسا کرنا محفوظ ہے۔
rc program ہر script کو باری باری چلاتا اور اس کے exit ہونے کا انتظار کرتا تھا۔ اگر کوئی script network address کے انتظار میں تیس seconds کے لیے block ہو جائے تو پورا boot تیس seconds کے لیے رک جاتا تھا، حتیٰ کہ ان services کے لیے بھی جو network کو کبھی استعمال نہیں کرتیں۔
اس script کے شروع میں موجود LSB (Linux Standard Base) header، اس مسئلے کو اندرونی طور پر حل کرنے کی ایک کوشش تھا۔ 2011 میں Debian 6.0 نے insserv کو default بنا دیا۔ یہ ہر script سے Required-Start پڑھتا، ایک graph بناتا، اور symlinks کو دوبارہ number کرتا تھا۔ اس کے بعد Debian startpar کے ذریعے آزاد scripts کو بیک وقت چلا سکتا تھا۔ اس سے بہتری آئی، لیکن بنیادی مسئلہ برقرار رہا۔ Dependency اب بھی script کے exit ہونے پر منحصر تھی۔ S20nginx کا 0 واپس کرنا صرف یہ بتاتا ہے کہ shell function واپس آ گیا ہے۔ اس کا مطلب یہ نہیں کہ nginx connections قبول کر رہا ہے۔
وہ پانچ کام جنہیں کوئی init script درست نہیں کر سکتی
- متوازی آغاز۔ فائل نام کے لحاظ سے ترتیب مشین کی ہر service پر ایک مکمل ترتیب قائم کرتی ہے، اس لیے boot کا وقت تمام services کے اوقات کے مجموعے کے برابر ہو جاتا ہے۔
- readiness۔ start script اس وقت ختم ہو جاتی ہے جب وہ daemon کو fork کر دیتی ہے، نہ کہ اس وقت جب daemon request فراہم کرنے کے قابل ہو۔ اس لیے اگلی script اکثر بہت جلد شروع ہو جاتی ہے۔
- نگرانی۔ daemon دو مرتبہ fork کرتا ہے اور اس کا parent ختم ہو جاتا ہے۔ اس سے daemon terminal سے الگ ہو کر PID 1 کو reparent ہو جاتا ہے۔ init کو child کے ختم ہونے کا علم ہوتا ہے، لیکن زندہ رہنے والے process سے اس کا کوئی قابلِ اعتماد تعلق نہیں رہتا۔
- ضرورت کے وقت آغاز۔ inetd (internet super-server) connection آنے پر daemon شروع کر سکتا تھا، لیکن یہ اپنی الگ configuration file والا جدا system تھا۔ boot کے وقت باقی تمام services کی ترتیب پر اس کا کوئی اثر نہیں تھا۔
- وسائل کا کنٹرول۔ init script میں کوئی ایسا طریقہ نہیں تھا جو service کی memory یا CPU میں اس کے حصے کی حد مقرر کر سکے۔
ulimitصرف ایک process پر لاگو ہوتا تھا، جبکہniceصرف scheduler کو متاثر کرتا تھا۔ اس لیے service کا بے قابو child مشین کے کسی بھی دوسرے process جیسا دکھائی دیتا تھا۔
نگرانی کا یہ خلا روزمرہ استعمال میں سب سے زیادہ مسئلہ پیدا کرتا تھا۔ اس کا عارضی حل PID file تھی۔ daemon اپنا process ID /run/nginx.pid میں لکھتا تھا، اور stop function وہ file دوبارہ پڑھ لیتا تھا۔ اگر daemon کو سختی سے ختم کیا جاتا تو file باقی رہتی۔ پھر kernel اسی number کو کسی اور process کے لیے دوبارہ استعمال کر لیتا، اور start-stop-daemon --stop --pidfile اس process کو signal بھیج دیتا جو اس number کا نیا مالک ہوتا۔ پرانی PID file کی وجہ سے init script غلط process کو ختم کر سکتی ہے۔
launchd نے socket کا مسئلہ پہلے ہی حل کر دیا تھا
Apple نے 2005 میں Mac OS X 10.4 کے ساتھ launchd جاری کیا۔ اسے Dave Zarzycki نے لکھا تھا۔ ایک process نے init، rc، xinetd، crond اور watchdogd کی جگہ لے لی۔
قابلِ تقلید خیال socket activation تھا۔ launchd پہلے ہر listening socket بناتا ہے، پھر daemons شروع کرتا ہے۔ جو client ابھی تک شروع نہ ہونے والے daemon سے connect ہوتا ہے، اسے connection refused نہیں ملتا، کیونکہ kernel اس socket کی backlog queue میں connection رکھتا ہے، یہاں تک کہ daemon accept() کو call کرتا ہے۔ دو daemons کے درمیان ترتیب اب کسی انسان کے بتانے کی محتاج نہیں رہتی۔ Socket خود یہ کام سنبھال لیتا ہے۔
launchd کو Mach IPC (inter-process communication) پر بنایا گیا تھا۔ یہ Apple کے XNU kernel کا حصہ ہے اور Linux میں اس کا کوئی equivalent نہیں ہے۔ اس code کو port کرنا کبھی حقیقت پسندانہ نہیں تھا۔ تاہم یہ خیال پھر بھی دوسری جگہوں تک پہنچ گیا۔
Upstart نے events کو کام کی بنیادی اکائی بنایا
Canonical کا Upstart، جسے Scott James Remnant نے لکھا تھا، October 2006 میں Ubuntu 6.10 کے ساتھ جاری ہوا۔ Fedora 9 سے Fedora 14 تک اس کا استعمال ہوا، اور RHEL 6 اور Chrome OS میں بھی یہی استعمال ہوتا تھا۔ اس نے runlevel کی جگہ event متعارف کرایا، جبکہ job میں یہ بتایا جاتا تھا کہ اسے کن events پر start اور stop ہونا چاہیے۔
# /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 کہتی ہے، "یہ ہونے پر مجھے start کریں"، اس لیے dependencies سے متعلق معلومات غلط file میں موجود ہوتی ہیں: service جانتی ہے کہ اسے کن چیزوں کی ضرورت ہے، لیکن وہ یہ نہیں جان سکتی کہ اگلے سال کس service کو اس کی ضرورت ہوگی۔ کسی service کو شامل کرنے کے لیے اکثر موجودہ job میں ترمیم کرنا پڑتی تھی تاکہ وہ نیا event جاری کرے۔
دوسرا مسئلہ tracking کا تھا۔ Upstart کسی forking daemon کی نگرانی اس طرح کرتا تھا کہ fork() calls کو ptrace کے ذریعے شمار کرتا تھا، جسے آپ expect fork یا expect daemon کے طور پر configure کرتے تھے۔ اگر forks کی تعداد غلط بتائی جائے تو Upstart ایسے process کی نگرانی کرتا ہے جو پہلے ہی exit ہو چکا ہو، یا ایسے fork کا انتظار کرتا ہے جو پہلے ہی ہو چکا ہو۔ اس کی علامت initctl start کا بغیر کسی error کے معطل رہنا ہے، اور job file اس کی کوئی وضاحت فراہم نہیں کرتی۔
Upstart کے contributors کے لیے Canonical کے contributor agreement پر دستخط کرنا بھی ضروری تھا۔ یہ engineering fault نہیں تھا، لیکن اس سے یہ ضرور متاثر ہوا کہ اس project پر کون کام کرتا تھا۔
PID 1 پر دوبارہ غور، April 2010
30 April 2010 کو Lennart Poettering نے "PID 1 پر دوبارہ غور" کے عنوان سے ایک تحریر شائع کی۔ Kay Sievers نے ان کے ساتھ اس منصوبے پر کام کیا۔ اس مؤقف کے چار حصے تھے۔
- کم چیزیں شروع کریں۔ بہت سی services اس وقت تک انتظار کر سکتی ہیں جب تک کوئی واقعی انہیں طلب نہ کرے۔
- جہاں socket ترتیب کا تعین کر سکتا ہو، وہاں صریح ترتیب متعین نہ کریں۔ تمام sockets ایک ہی مرحلے میں کھولیں، پھر سب کچھ بیک وقت شروع کریں۔
- processes کو PID files کے بجائے control groups کے ذریعے track کریں۔
- service کو declarative file میں بیان کریں، تاکہ ایک ہی description ہر distribution پر کام کرے۔
اسی سال پہلی release جاری ہوئی۔ Fedora 14 نے November 2010 میں systemd کو ایک option کے طور پر شامل کیا، اور Fedora 15 نے May 2011 میں اسے default بنا دیا۔
نگرانی کو قابلِ اعتماد بنانے میں cgroups کا کردار
cgroup (control group) عمل کے گروپ بنانے کے لیے kernel کی سہولت ہے، جسے 2008 میں Linux 2.6.24 میں شامل کیا گیا۔ systemd ہر service کو اپنے الگ cgroup میں رکھتا ہے۔ child اپنے parent کا cgroup وراثت میں لیتا ہے، اور غیرمجاز process خود کو اس سے باہر منتقل نہیں کر سکتا۔ اس لیے double forking کچھ بھی پوشیدہ نہیں رکھتا: PID 1 ہر وقت ان تمام processes کا درست مجموعہ رکھتا ہے جو کسی unit سے متعلق ہیں۔ کسی service کو روکنے کا مطلب اس کے cgroup میں موجود ہر چیز کو ختم کرنا ہے، اور یہی default KillMode=control-group کرتا ہے۔
systemctl status اس group کو دکھاتا ہے:
● 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"یہ block stale PID file کے مسئلے کا مکمل جواب ہے۔ کوئی file stale نہیں ہو سکتی، کیونکہ فہرست kernel state ہوتی ہے۔
یہی tree limits بھی نافذ کرتا ہے، کیونکہ cgroups کو tracking کے لیے استعمال ہونے سے پہلے accounting کے لیے بنایا گیا تھا۔ MemoryMax=، CPUQuota= اور TasksMax= میں سے ہر ایک ایک سطر پر مشتمل ہے۔ کسی service پر سخت memory اور CPU حد مقرر کرنا آج ایک drop-in file ہے، جبکہ 2009 میں یہ ایسے shell script کے لیے patch ہوتا جسے کسی نے لکھا ہی نہیں تھا۔
ہر distribution نے 2011 اور 2015 کے درمیان تبدیلی کیوں کی
- Fedora 15، مئی 2011۔
- openSUSE 12.1، نومبر 2011۔
- Mageia 2، مئی 2012۔
- Arch Linux، اکتوبر 2012 سے نئی installations کے لیے default۔
- RHEL 7، جون 2014۔
- SLES 12، اکتوبر 2014۔
- Debian 8، اپریل 2015۔
- Ubuntu 15.04، اپریل 2015۔
وجوہات زیادہ تر غیر دلچسپ تھیں، اسی لیے تبدیلی تیزی سے ہوئی۔
- ایک ہی unit file ہر distribution پر کام کرتی ہے، اس لیے upstream projects نے
.servicefile ship کرنا شروع کر دی، اور distributions نے ہر package اور ہر release کے لیے الگ shell script maintain کرنا بند کر دیا۔ - ConsoleKit کی 2012 کے آس پاس maintenance بند ہونے کے بعد desktop session tracking
systemd-logindمیں منتقل ہو گئی۔ GNOME کو logind درکار تھا، اس لیے systemd کے بغیر distribution کو متبادل تلاش کرنا پڑا۔ یہ متبادلelogindہے، جو systemd کے logind کو الگ کر کے مستقل طور پر maintain کرتا ہے۔ - udev، جو device manager ہے، اپریل 2012 میں systemd کے source tree میں merge کر دیا گیا۔ udev ship کرنے والی distributions اب systemd کی repository track کر رہی تھیں۔ اس کے جواب میں Gentoo نے
eudevfork کیا۔ - Containers نے reliable process tracking اور ہر service کے لیے limits کو زیادہ اہم بنا دیا، کیونکہ دونوں cgroup features ہیں۔ یہ سوال کہ container process کا مالک کون سا supervisor ہے، اب بھی اہم رہتا ہے، جب آپ Docker Compose stack کو reboot کے بعد دوبارہ شروع کرواتے ہیں۔
Debian کا فیصلہ سب سے زیادہ نمایاں تھا۔ Technical Committee نے فروری 2014 میں ووٹ دیا۔ ووٹ برابر رہا، اور chair Bdale Garbee نے systemd کے حق میں فیصلہ کن ووٹ دیا۔ چند دن بعد Ubuntu نے اعلان کیا کہ وہ Upstart کے ساتھ جاری رہنے کے بجائے Debian کی پیروی کرے گا۔ Debian developers کے ایک گروپ نے نومبر 2014 میں distribution کو Devuan کے طور پر fork کیا، اور مئی 2017 میں Devuan 1.0 جاری کیا۔
اعتراضات، منصفانہ انداز میں بیان کردہ
دائرہ کار۔ اب ایک ہی project PID 1، logging daemon، login session management، device manager، network configuration daemon، DNS (domain name system) resolver، NTP (network time protocol) client، container runner اور boot loader فراہم کرتا ہے۔ عام دفاع یہ ہے کہ یہ الگ binaries ہیں جنہیں آپ کو install کرنا ضروری نہیں۔ یہ بات درست ہے، لیکن اعتراض کا جواب نہیں دیتی۔ جب desktop کو logind درکار ہو اور logind کو systemd کے tree سے الگ release کیا جائے، تو انتخاب آزاد نہیں رہتا۔ بحث میں coupling سے یہی مراد تھی، اور ایسا ہو چکا ہے۔
Binary journal۔ journald plain text کے بجائے indexed binary format میں لکھتا ہے۔ اس سے وہ سہولتیں ملتی ہیں جو text کبھی نہیں دیتا تھا: فی-unit اور فی-priority filtering، structured fields، اور ایسا metadata جس میں sending program جعل سازی نہیں کر سکتا، کیونکہ journald خود unit اور cgroup record کرتا ہے۔ journalctl -u nginx -p err --since "-1h"، grep کی جگہ date regular expression استعمال کرتا ہے۔ اس کی لاگت بھی حقیقی ہے۔ جو machine boot نہیں ہو رہی ہو، اس پر rescue shell سے less کے ذریعے log نہیں پڑھ سکتے۔ اس کے بجائے mounted disk کو journalctl کے حوالے کریں:
sudo journalctl --directory /mnt/var/log/journal --boot -1 --priority errیہاں ایک دوسرا مسئلہ بھی ہے جو لوگوں کو کم از کم ایک بار ضرور پیش آتا ہے۔ journald logs کو /run/log/journal میں رکھتا ہے، جو memory ہے، جب تک /var/log/journal موجود نہ ہو۔ ایسی machine پر جہاں یہ موجود نہیں، reboot کے بعد journalctl -b -1 کے پاس دکھانے کے لیے کچھ نہیں ہوتا، حالانکہ عین اسی وقت آپ کو log درکار ہوتی ہے۔ اسے check اور fix کریں:
journalctl --disk-usage
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journaldjournalctl --disk-usage کو اب /var/log/journal کے تحت archived journals report کرنے چاہییں۔ اگر plain text بھی چاہیے تو /etc/systemd/journald.conf میں ForwardToSyslog=yes set کریں اور rsyslog کو installed رکھیں۔
Boot کی debug کرنے کی صلاحیت۔ جب کوئی unit hang ہو جائے تو console پر ایک line دکھائی دیتی ہے اور اس کے بعد کچھ نہیں ہوتا:
[ *** ] A start job is running for Wait for Network to be Configured (1min 32s / no limit)مزید investigation کے tools موجود ہیں: unit کے stuck ہونے کے دوران systemctl list-jobs، اس کے بعد systemd-analyze blame اور systemd-analyze critical-chain، اور kernel command line پر systemd.log_level=debug۔ اعتراض کی منصفانہ صورت یہ ہے کہ جس شخص کو sh معلوم ہو، وہ init script کو شروع سے آخر تک پڑھ سکتا تھا، جبکہ stuck unit کے لیے یہ جاننا پڑتا ہے کہ درجن بھر commands میں سے کون سی استعمال کرنی ہے۔ یہ حقیقی لاگت ہے۔ ہر administrator اسے ایک بار ادا کرتا ہے، اور بہت سے administrators نے اسے ایک ہی وقت میں ادا کیا۔
ایسا default جو سب کے لیے بدل جائے۔ 2016 میں systemd 230 نے logind کا default تبدیل کیا، جس کے تحت logout پر باقی رہ جانے والے user processes ختم کیے جانے لگے۔ Detached tmux اور screen sessions، ان sessions کے ختم ہوتے ہی بند ہو گئے جنہوں نے انہیں شروع کیا تھا۔ Distributions نے KillUserProcesses=no کو /etc/systemd/logind.conf میں ship کیا، اور supported جواب loginctl enable-linger <user> ہے۔ ایک project میں ایک default کی تبدیلی نے اس عادت کو بدل دیا جس پر لاکھوں لوگ انحصار کرتے تھے۔ عملی طور پر "بہت زیادہ userland ایک ہی جگہ رکھنا" کا مطلب یہی ہے۔
Default dependency، security surface ہوتی ہے۔ March 2024 میں xz-utils کے backdoor نے Debian اور Ubuntu پر sshd کو target کیا۔ Upstream OpenSSH، libsystemd سے link نہیں ہوتا۔ ان distributions نے اسے patch کر کے شامل کیا تاکہ sshd، systemd کو readiness report کر سکے، اور libsystemd نے liblzma کو dependency کے طور پر شامل کیا، جہاں backdoor موجود تھا۔ Readiness protocol خود $NOTIFY_SOCKET میں نامزد socket کو بھیجا جانے والا ایک single datagram ہے، اس لیے اس کے لیے library کبھی ضروری نہیں تھی۔ systemd کے جواب میں compression libraries کو dlopen کے ذریعے load کیا جانے لگا، تاکہ وہ default طور پر linked نہ ہوں۔ اسی نوعیت کا ایک متعلقہ bug بھی یہی pattern دکھاتا ہے: 2017 میں digit سے شروع ہونے والی User= value کو invalid سمجھا گیا اور unit fail ہونے کے بجائے root کے طور پر چل گئی، لہذا ایک typo privilege escalation بن گیا۔ بعد کے versions unit کو start کرنے سے انکار کرتے ہیں۔
اپنے systemctl پرامپٹ میں تاریخ
اوپر بیان کیا گیا ہر مسئلہ اب ایک ایسی directive ہے جسے آپ ایک file میں پڑھ سکتے ہیں۔
- Serial boot،
After=اورWants=بن گیا، جبکہsystemd-analyze critical-chainدکھاتا ہے کہ آپ کے boot کو حقیقت میں کس چیز نے روکے رکھا۔ - Readiness،
Type=notifyبن گئی۔ سروس دستیاب ہونے پرREADY=1کو$NOTIFY_SOCKETمیں لکھتی ہے۔ پرانے daemons کے لیےType=forkingکے ساتھPIDFile=اب بھی موجود ہے، اور جب PID file ظاہر نہ ہو تو یہی typestart operation timed out. Terminating.کے ساتھ ناکام ہوتی ہے۔ - Supervision اب cgroup کے ذریعے ہوتی ہے۔ اس لیے
Restart=on-failureکے ساتھRestartSec=، wrapper script کی جگہ لے لیتا ہے، جبکہStartLimitBurst=crash loop کو ہمیشہ چلتے رہنے سے روکتا ہے۔ - inetd اب ایک
.socketunit بن گیا ہے، جو.serviceunit کے ساتھ موجود ہوتا ہے۔ ulimit،MemoryMax=،CPUQuota=اورTasksMax=بن گیا۔- init script کی
su - appuser -cline ابUser=،NoNewPrivileges=yesاورProtectSystem=strictبن گئی ہے۔ اسی لیے سروس کو غیر مراعات یافتہ user کے طور پر چلانا unit کی بنیادی ساخت ہے، اضافی کام نہیں۔
[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اس file میں ایک line ایسی ہے جس میں ہر شخص ایک بار ضرور غلطی کرتا ہے۔ Requires=postgresql.service ایک requirement ہے، ordering نہیں۔ اس کا مطلب ہے کہ Postgres ناکام ہو تو آپ کی unit بھی ناکام ہو جائے گی؛ اس کا مطلب یہ نہیں کہ Postgres پہلے start ہو۔ After=postgresql.service کے بغیر دونوں ایک ہی وقت start ہوں گے، اور آپ کی سروس ایسے port سے connect کرنے کی کوشش کرے گی جس پر ابھی کوئی process listening نہیں ہے۔ دونوں کو جان بوجھ کر الگ رکھا گیا ہے، کیونکہ بعض اوقات آپ کو ایک چاہیے ہوتا ہے، دوسرا نہیں۔ ProtectSystem=strict اس سروس کے لیے file system کو read-only mount کرتا ہے۔ اسی لیے StateDirectory= موجود ہے: یہ سروس کو /var/lib کے تحت ایک writable path فراہم کرتا ہے۔
2026 کے server پر 2005 کو دیکھنے کی واضح مثال Ubuntu 24.04 پر SSH ہے، جو August 2026 تک systemd 255 کے ساتھ release ہوتا ہے۔ ssh.service default طور پر socket activated ہے: ssh.socket listening socket سنبھالتا ہے، اور connection آنے پر sshd start ہوتا ہے۔ اس لیے /etc/ssh/sshd_config میں Port 2222 کا کوئی اثر نہیں، کیونکہ port کھولنے والا process sshd نہیں ہے۔ تبدیلی socket unit میں کرنی ہوگی۔
sudo systemctl edit ssh.socket[Socket]
ListenStream=
ListenStream=2222خالی ListenStream= packaged unit سے وراثت میں ملنے والی value صاف کرتا ہے۔ اسے چھوڑ دیں تو دونوں ports حاصل ہوں گے، کیونکہ systemd list کو replace کرنے کے بجائے اس میں value شامل کرتا ہے۔ اس کے بعد apply کریں اور جانچیں، اور پورے عمل کے دوران دوسری SSH session کھلی رکھیں:
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
sudo ss -lntp | grep 2222ss میں port 2222 پر ایک socket درج ہونا چاہیے، جس کی ملکیت systemd کی ہو، sshd کی نہیں۔ یہ launchd کا design ہے، بیس سال بعد، آپ کے VPS پر۔ اگر آپ پرانا طریقہ چاہتے ہیں تو sudo systemctl disable --now ssh.socket کے بعد sudo systemctl enable --now ssh.service چلانے سے ایک طویل عرصے تک چلنے والا sshd ملے گا، جو دوبارہ اپنی config سے Port پڑھتا ہے۔
آپ کو ان میں سے کون سی تفصیلات نظر آئیں گی، اس کا انحصار آپ کے چلائے جانے والے release پر ہے۔ اسی لیے upgrade کا منصوبہ بنانے سے پہلے LTS اور interim Ubuntu release کے درمیان فرق جاننا مفید ہے۔ ایک سے زیادہ machines پر unit file کا ہر جگہ یکساں ہونا اس بات کی وجہ ہے کہ متعدد servers کو ایک جگہ سے manage کرنا اب configuration کا مسئلہ ہے، shell scripting کا نہیں۔ اور جب آپ اپنی units لکھتے ہیں تو service اور timer کا جوڑا وہ کام کرتا ہے جسے 2009 میں آپ init script اور cron line کے درمیان تقسیم کرتے۔
FAQ
Linux distributions نے SysV init کو systemd سے کیوں تبدیل کیا؟
اس کی دو engineering وجوہات اور ایک maintenance وجہ تھیں۔ SysV init خدمات کو filename کے مطابق ترتیب دیتا تھا، جو dependency کے بجائے صرف position ہوتی ہے۔ یہ ایسے daemon کا track بھی کھو دیتا تھا جو اپنے parent سے fork ہو جاتا تھا۔ اسی وجہ سے پرانی PID files غلط process کو ختم کر سکتی تھیں۔ systemd نے socket activation اور dependency directives کے ذریعے ordering کا مسئلہ حل کیا، اور control groups کے ذریعے process tracking کا مسئلہ حل کیا۔ Maintenance کی وجہ نے adoption کی رفتار طے کی: ایک unit file ہر distribution پر کام کرتی ہے۔ اس لیے upstream projects نے .service file فراہم کی، اور distribution maintainers نے ہر package کے لیے الگ shell script لکھنا بند کر دیا۔ Fedora 15 نے May 2011 میں تبدیلی کی، جبکہ Ubuntu 15.04 April 2015 تک آخری بڑی distribution تھی جو اس سے الگ رہی۔
کیا systemd ایک بہت بڑا binary ہے؟
نہیں۔ Source tree سے کئی الگ programs build ہوتے ہیں۔ PID 1 /usr/lib/systemd/systemd ہے، جبکہ journald، logind اور udevd اپنے الگ binaries کے ساتھ الگ processes ہیں۔ اپنے system پر انہیں دیکھنے کے لیے ls /usr/lib/systemd/ چلائیں۔ جو اعتراض اب بھی باقی ہے وہ binary size کے بجائے release coupling سے متعلق ہے۔ یہ programs ایک ساتھ release ہوتے ہیں اور private interfaces share کرتے ہیں۔ اس لیے distributions عموماً انہیں ایک set کے طور پر شامل کرتی ہیں، اور GNOME جیسے software نے خاص طور پر logind کی توقع کرنا شروع کر دی۔
کیا میں اب بھی systemd کے بغیر Linux چلا سکتا ہوں؟
ہاں۔ Devuan، sysvinit فراہم کرتا ہے؛ Gentoo میں OpenRC default ہے؛ Void، runit استعمال کرتا ہے؛ Alpine، OpenRC کے ساتھ busybox init استعمال کرتا ہے؛ اور Slackware BSD style scripts برقرار رکھتا ہے۔ اس کی لاگت compatibility work ہے۔ وہ desktop software جو logind کی توقع کرتا ہے، اسے elogind درکار ہوتا ہے۔ یہ systemd کا logind ہے جسے standalone package کے طور پر maintain کیا جاتا ہے۔ اس کے علاوہ اب server software کا بڑھتا ہوا حصہ صرف .service file فراہم کرتا ہے، اس لیے startup script خود لکھ کر maintain کرنا پڑتا ہے۔
journal plain text file کے بجائے binary کیوں ہے؟
کیونکہ journald structured fields کو index کے ساتھ محفوظ کرتا ہے۔ اس سے per-unit filtering، priority filtering اور ایسا metadata دستیاب ہوتا ہے جسے sending program forge نہیں کر سکتا۔ journald خود unit، cgroup اور اصل UID record کرتا ہے، log line پر اعتماد نہیں کرتا۔ اس کی قیمت یہ ہے کہ اسے پڑھنے کے لیے journalctl درکار ہوتا ہے، rescue system سے بھی۔ ایسی صورت میں mounted disk کی طرف اشارہ کرنے کے لیے journalctl --directory /mnt/var/log/journal استعمال کریں۔ اگر text format بھی چاہیے تو /etc/systemd/journald.conf میں ForwardToSyslog=yes set کریں۔
میری /etc/init.d script میں editing کے متبادل کے طور پر کیا استعمال ہوتا ہے؟
Drop-in files استعمال کریں۔ /usr/lib/systemd/system/ میں موجود unit کو edit نہ کریں، کیونکہ package upgrade اسے overwrite کر دے گا۔ sudo systemctl edit nginx.service چلائیں۔ systemd /etc/systemd/system/nginx.service.d/override.conf بنائے گا، جو packaged unit کے اوپر merge ہو جائے گی۔ systemctl cat nginx.service merged result دکھاتا ہے، جبکہ systemd-delta machine پر موجود ہر override کی فہرست دیتا ہے۔ ہاتھ سے کی گئی ہر edit کے بعد sudo systemctl daemon-reload چلائیں، ورنہ اگلی command Warning: The unit file, source configuration file or drop-ins of nginx.service changed on disk. دکھائے گی۔