SSD Nodes Learn 🎉 VPS $5.50/ماہ سے
تعلیمی Matt Connorتحریر: Matt Connor

systemd میں Type=simple، forking اور notify کا انتخاب

اگر unit active ہے مگر daemon ختم ہو چکا ہے، تو Type=simple، exec، forking، oneshot اور notify میں درست انتخاب کریں اور اصل main PID تلاش کریں۔

systemd کسی process کے ختم ہو جانے کے باوجود unit کو active کیوں رپورٹ کرتا ہے

systemd service unit اس وقت تک active رہتی ہے جب تک وہ واحد process زندہ رہتا ہے جسے systemd main process کہتا ہے، اور Type=، [Service] section میں، یہ طے کرتا ہے کہ وہ process کون سا ہے۔ غلط value منتخب کرنے پر systemd کسی shell wrapper یا مختصر مدت تک چلنے والے parent کو monitor کرتا رہتا ہے، جبکہ مطلوبہ daemon اسی unit کے اندر ختم ہو جاتا ہے۔ unit اس process کے بارے میں درست حالت بتا رہی ہوتی ہے جسے monitor کرنے کی ہدایت دی گئی تھی۔

Restart policy تبدیل کرنے سے اس مسئلے کا حل نہیں ہوگا۔ Restart= اس وقت کارروائی کرتا ہے جب main process ختم ہو، اس لیے Restart=always اس وقت تک کبھی فعال نہیں ہوگا جب تک main PID (process identifier) کسی ایسے process سے وابستہ ہے جو ابھی چل رہا ہے۔ پہلے Type= درست کریں۔ main process واقعی ختم ہونے کے بعد systemd کیا کرے گا، یہ ایک الگ فیصلہ ہے، جس کی وضاحت Restart= اور RestartSec= کی رہنما دستاویز میں کی گئی ہے۔

Type= اصل میں کیا متعین کرتا ہے

ہر Type= value بیک وقت دو سوالوں کا جواب دیتی ہے۔ systemd اس unit کو کب started سمجھ سکتا ہے، اور مرکزی process کون سا ہے۔

پہلا جواب ordering کو متعین کرتا ہے۔ جو unit اپنی After= میں آپ کی unit کا نام دیتی ہے، وہ اس وقت تک انتظار کرتی ہے جب تک systemd آپ کی unit کو started قرار نہ دے۔ اگر کوئی Type= بہت جلد "started" رپورٹ کرے تو dependent units اس سے پہلے چل سکتی ہیں کہ آپ کی service ان کی درخواستوں کا جواب دے سکے۔

دوسرا جواب supervision کو متعین کرتا ہے۔ systemd unit سے شروع ہونے والے ہر process کو ایک cgroup (control group) میں رکھتا ہے۔ یہ kernel feature processes کو اس طرح group کرتا ہے کہ انہیں ایک ساتھ محدود اور ختم کیا جا سکے۔ systemctl stop صفائی کے لیے اسی cgroup کو استعمال کرتا ہے: KillMode= پہلے سے control-group ہوتی ہے، اس لیے unit روکنے پر اس کے اندر موجود ہر process کو signal بھیجا جاتا ہے۔ main PID کا دائرہ اس سے محدود ہے۔ یہی وہ واحد process ہے جس کے exit ہونے سے unit ختم ہوتی ہے، اور جس کا exit status unit کا نتیجہ بن جاتا ہے۔ cgroup کو main PID سمجھ کر پڑھنا ہی اس الجھن کی ابتدا ہے۔

Type=simple رپورٹ کرتا ہے کہ بائنری چلنے سے پہلے ہی سروس شروع ہو گئی

Type=simple اس وقت default ہوتا ہے جب ExecStart= set ہو اور Type= یا BusName= میں سے کوئی بھی موجود نہ ہو۔ systemd process بناتا ہے، unit کو فوراً started سمجھتا ہے، اور اس process کو main PID تصور کرتا ہے۔ متعلقہ units فوراً شروع ہو جاتی ہیں، اس سے پہلے کہ service binary execute بھی ہو۔

یہ آخری نکتہ ایک عام حیرت کی وضاحت کرتا ہے۔ ExecStart= path میں typo کے باوجود start job کامیاب ہو جاتی ہے، اور failure کچھ ہی دیر بعد اس وقت ظاہر ہوتی ہے جب execution ناکام ہو جاتی ہے۔ systemd اس صورت کو exit code 203 کے ساتھ record کرتا ہے۔ اس کی اپنی table میں اسے EXEC کہا گیا ہے، اور اس کی تعریف service binary execute کرنے میں ناکامی ہے۔ لہٰذا systemctl start کا بغیر error واپس آنا اس بات کا ثبوت نہیں کہ آپ کی binary موجود ہے۔

ایسے program کے لیے simple استعمال کریں جو foreground میں برقرار رہتا ہو اور خود کو background میں منتقل نہ کرتا ہو۔ زیادہ تر جدید daemons اور تقریباً ہر وہ program اسی زمرے میں آتا ہے جو آپ خود لکھتے ہیں۔

Type=exec انتظار کرتا ہے کہ پروگرام واقعی شروع ہو جائے

Type=exec دراصل simple ہی ہے، لیکن اس میں ایک اضافی مرحلہ شامل ہے۔ systemd یونٹ کو اسی وقت شروع شدہ سمجھتا ہے جب fork اور binary کی execution دونوں کامیاب ہو جائیں۔ اگر binary موجود نہ ہو یا User= کو resolve نہ کیا جا سکے، تو start job خود ناکام ہو جاتی ہے۔ اس کے بجائے یہ کامیابی کی اطلاع دے کر کچھ دیر بعد خاموشی سے ناکام نہیں ہوتی۔

Type=exec systemd 240 میں شامل ہوا تھا، اس لیے ہر موجودہ server distribution میں یہ دستیاب ہے۔ اگست 2026 تک Ubuntu 24.04 میں systemd 255 اور Debian 13 میں systemd 257 شامل ہے۔ اپنا ورژن systemctl --version سے چیک کریں۔

اس کی قیمت start کے وقت synchronisation کا ایک اضافی مرحلہ ہے۔ فائدہ یہ ہے کہ systemctl start سے درست exit status ملتا ہے۔ foreground پروگرام کے لیے exec کو simple پر ترجیح دیں۔

Type=forking، اور main PID کیسے ضائع ہو جاتا ہے

Type=forking systemd کو بتاتا ہے کہ ExecStart= میں موجود process ایک child کو fork کرے گا اور پھر جان بوجھ کر exit ہو جائے گا۔ systemd اس پہلے process کے exit ہونے تک انتظار کرتا ہے، اور اس کے بعد ہی unit کو started تصور کرتا ہے۔ پیچھے رہ جانے والا child ہی daemon ہوتا ہے۔

مشکل process کی شناخت میں ہے۔ systemd کا شروع کیا ہوا process ختم ہو چکا ہوتا ہے، اس لیے systemd کو یہ معلوم کرنا پڑتا ہے کہ زندہ رہنے والے processes میں main process کون سا ہے۔ PIDFile= کو اس file پر set کریں جس میں daemon اپنا PID لکھتا ہے۔ عموماً یہ /run کے تحت موجود path ہوتا ہے۔ systemd اس file سے PID پڑھتا ہے۔ systemd یہ بھی جانچتا ہے کہ file میں موجود PID پہلے سے اسی service سے متعلق process کو ظاہر کرتا ہے۔ اس لیے کسی غیر متعلق process کا نام دینے والی stale file کو قابلِ اعتماد نہیں سمجھا جاتا بلکہ مسترد کر دیا جاتا ہے۔

PIDFile= کے بغیر GuessMainPID= نافذ ہوتا ہے، اور اس کی default قدر yes ہے۔ یہ اندازہ صرف اس وقت قابلِ اعتماد ہوتا ہے جب service ایک ہی process پر قائم ہو جائے۔ manual اس حد کو واضح طور پر بیان کرتا ہے: اگر daemon ایک سے زیادہ processes پر مشتمل ہو تو یہ اندازہ غلط ہو سکتا ہے، اور failure detection کام کرنا بند کر دیتی ہے۔ کسی unit کا main PID 0 بھی ہو سکتا ہے۔ اس کا مطلب ہے کہ systemd کے پاس supervise کرنے کے لیے کوئی process موجود نہیں۔

زیادہ تر وہ daemons جو fork کرتے ہیں، ان میں foreground میں رہنے کا switch بھی ہوتا ہے۔ اس switch کو Type=exec کے ساتھ استعمال کریں اور PIDFile= کی line حذف کر دیں۔ کم اجزا ہوں تو PID ضائع ہونے کے امکانات بھی کم ہوتے ہیں۔

oneshot ایسی کارروائی کے لیے ہے جو مکمل ہو کر ختم ہو جاتی ہے

Type=oneshot میں عمل کے چلنے اور ختم ہونے کی توقع ہوتی ہے۔ systemd یونٹ کو تبھی started سمجھتا ہے جب عمل ختم ہو جائے، اس لیے oneshot اس کام کے لیے موزوں قسم ہے جس کے مکمل ہونے تک کسی دوسرے یونٹ کو انتظار کرنا ہو۔ جب کوئی یونٹ Type= یا ExecStart= میں سے کسی کو بھی متعین نہیں کرتا، تو یہی اس کی مفروضہ قسم ہوتی ہے۔

oneshot کے ساتھ دو رویے مخصوص ہیں۔ یہ واحد قسم ہے جو ایک سے زیادہ ExecStart= لائن قبول کرتی ہے، اور یہ لائنیں ترتیب وار چلتی ہیں۔ اس کا start timeout بھی بطور ڈیفالٹ غیر فعال ہوتا ہے، اس لیے اگر کوئی oneshot رک جائے تو وہ ہمیشہ انتظار کرتا رہے گا، جب تک کہ آپ خود TimeoutStartSec= متعین نہ کریں۔

عمل ختم ہونے کے بعد یونٹ inactive حالت میں واپس آ جاتا ہے۔ RemainAfterExit=yes اسے active رکھتا ہے، جبکہ کوئی عمل بالکل نہیں چل رہا ہوتا۔ یہ اس صفحے کے آغاز میں بیان کردہ علامت کا دانستہ اور درست ورژن ہے، جب یونٹ کا کام کسی چیز کو چلتا رکھنے کے بجائے اپنی حالت برقرار چھوڑنا ہو، مثلاً firewall ruleset لوڈ کرنا یا container stack شروع کرنا۔ یہی طریقہ ایسا Docker Compose stack جو reboot کے بعد دوبارہ آ جائے کے پیچھے بھی ہے: یونٹ compose command چلاتا ہے، ختم ہو جاتا ہے، اور active رہتا ہے کیونکہ اس کے شروع کیے ہوئے containers اس کے بعد بھی چلتے رہتے ہیں۔ oneshot یونٹ ہی وہ یونٹ بھی ہے جسے schedule trigger کرتا ہے؛ یہ cron کے بجائے systemd timer پر job چلانے کے طریقے کا دوسرا حصہ ہے۔

Type=notify سروس کو یہ بتانے دیتا ہے کہ وہ کب تیار ہے

Type=notify فیصلہ سروس کے سپرد کرتا ہے۔ systemd اس وقت تک start job کو زیر التوا رکھتا ہے جب تک process کسی Unix socket کے ذریعے READY=1 نہ بھیج دے۔ اس socket کا path اسے NOTIFY_SOCKET environment variable میں ملتا ہے۔ C interface sd_notify(3) ہے، اور بہت سے servers پہلے ہی اسے support کرتے ہیں۔

یہ سوال کہ "کیا سروس start ہو چکی ہے؟" کا درست جواب ہے۔ simple اور exec سروس کے اپنی configuration پڑھنے یا listening socket کھولنے سے پہلے ہی started رپورٹ کر دیتے ہیں۔ اس لیے dependent unit بہت جلد start ہو سکتی ہے اور اپنی پہلی connection پر fail ہو سکتی ہے۔ notify اسی وقت started رپورٹ کرتا ہے جب سروس خود کہتی ہے کہ وہ تیار ہے۔

systemd یہ message صرف main process سے قبول کرتا ہے۔ یہی بات NotifyAccess=main ظاہر کرتی ہے، اور Type=notify اسے implicitly فعال کرتا ہے۔ اگر message کسی child یا helper سے آتا ہے تو NotifyAccess=all set کریں۔ shell script systemd-notify --ready کو call کر سکتی ہے، لیکن یہ الگ مختصر مدتی process کے طور پر چلتا ہے۔ اس لیے اسے NotifyAccess=all درکار ہوتا ہے، اور systemd ممکن ہے ایسے message کو سروس سے منسوب نہ کر سکے جس کا sender پہلے ہی exit ہو چکا ہو۔ جو سروس خود اس protocol کے مطابق message بھیجے، وہ زیادہ قابل اعتماد ہوتی ہے۔

دو متعلقہ settings بھی جاننا مفید ہے۔ systemd 253 سے دستیاب Type=notify-reload اسی handshake کو reloads تک توسیع دیتا ہے۔ اس کے ساتھ systemctl reload signal بھیجے جانے کے وقت واپس آنے کے بجائے اس وقت واپس آتا ہے جب سروس reload مکمل ہونے کی اطلاع دیتی ہے۔ WatchdogSec= notifying سروس سے کہتا ہے کہ وہ مقررہ وقفے پر keep-alive message بھیجے۔ systemd deadline miss ہونے کو failure سمجھتا ہے۔

Type=dbus اور Type=idle

Type=dbus اس وقت تک انتظار کرتا ہے جب تک service D-Bus پر اپنا نام register نہ کر لے۔ D-Bus وہ message bus ہے جسے system اور desktop services ایک دوسرے سے رابطے کے لیے استعمال کرتی ہیں۔ اس کے لیے BusName= درکار ہے، اور جیسے ہی BusName= set ہو، یہ default بن جاتا ہے۔ اسے صرف ایسی service کے لیے استعمال کریں جو واقعی bus name register کرتی ہو۔

Type=idle، simple کی طرح کام کرتا ہے، لیکن program چلانے میں اس وقت تک تاخیر کرتا ہے جب تک queued jobs dispatch نہ ہو جائیں۔ یہ تاخیر زیادہ سے زیادہ پانچ seconds تک ہوتی ہے۔ یہ اس لیے موجود ہے کہ boot کے وقت console output، status messages کے ساتھ نہ ملے۔ یہ ordering tool نہیں ہے، اور اسے عام service میں شامل نہیں کرنا چاہیے۔

wrapper script کی وجہ سے systemd غلط PID کی نگرانی کیوں کرتا ہے

یہ وہ ساخت ہے جو اصل مسئلہ پیدا کرتی ہے۔

[Service]
Type=simple
ExecStart=/opt/app/run.sh
#!/bin/bash
export APP_ENV=production
/opt/app/bin/server --config /etc/app.yaml &
/opt/app/bin/exporter --port 9101

systemd shell کو main PID کے طور پر ریکارڈ کرتا ہے۔ shell اس وقت تک چلتی رہتی ہے جب exporter foreground میں چلتا ہے۔ اگر server ختم ہو جائے تو shell کو اس کا علم نہیں ہوتا۔ اس لیے main PID ابھی زندہ رہتا ہے، unit بدستور active رہتی ہے، اور Restart= کے پاس کارروائی کرنے کے لیے کچھ نہیں ہوتا۔ دونوں processes پورے وقت unit کے cgroup میں رہتے ہیں، اس لیے systemctl stop پھر بھی cleanup درست طور پر کرتا ہے۔ خرابی supervision میں ہوئی، cleanup میں نہیں۔

حل کا انحصار اس بات پر ہے کہ unit میں واقعی کتنے طویل عرصے تک چلنے والے processes ہیں۔

اگر ایک process ہے تو shell کو اسی process سے replace کریں۔

#!/bin/bash
export APP_ENV=production
exec /opt/app/bin/server --config /etc/app.yaml

exec shell کو نامزد program سے replace کرتا ہے اور وہی PID برقرار رکھتا ہے۔ اس طرح systemd کا ریکارڈ کردہ PID اب daemon سے متعلق ہوتا ہے۔ اس سے بھی بہتر طریقہ wrapper کو ختم کرنا ہے۔ Environment= اور EnvironmentFile= variables فراہم کرتے ہیں، جبکہ ExecStartPre= setup step فراہم کرتا ہے۔ اس طرح systemd daemon کو براہِ راست launch کر سکتا ہے اور شروع ہی سے اس کا PID جانتا ہے۔

اگر دو processes ہیں تو کوئی ایک PID پوری unit کی نمائندگی نہیں کرتا۔ انہیں دو units میں تقسیم کریں اور After= اور Wants= کے ذریعے ان کی ترتیب مقرر کریں۔ ہر process کے لیے ایک unit وہ arrangement ہے جس کی systemd اچھی طرح نگرانی کرتا ہے، اور یہی واحد طریقہ ہے جس سے ہر process کو اپنا restart behaviour ملتا ہے۔

ExitType=cgroup میں تبدیلیاں

ExitType= کو systemd 250 میں شامل کیا گیا تھا۔ پہلے سے طے شدہ قدر main ہے: main process ختم ہوتے ہی unit کو stopped سمجھا جاتا ہے۔ ExitType=cgroup کے ساتھ unit اس وقت تک running سمجھی جاتی ہے جب تک اس کے cgroup میں کوئی بھی process فعال ہو۔

[Service]
Type=simple
ExitType=cgroup
ExecStart=/opt/app/launcher

اس سے ایک مخصوص مسئلہ حل ہوتا ہے۔ ایسا launcher جو اصل کام شروع کرنے کے بعد خود ختم ہو جائے، ExitType=main کے تحت systemd کو unit کے stopped ہونے کا احساس دلاتا اور باقی process ختم کر دیتا۔ ExitType=cgroup کے ساتھ unit پورے process group کی پیروی کرتی ہے۔

یہ واضح رہنا چاہیے کہ یہ کیا حل نہیں کرتا۔ ExitType=cgroup unit کو اس وقت تک active رکھتا ہے جب تک کم از کم ایک process موجود ہو۔ اس لیے دو daemons رکھنے والی unit، ان میں سے ایک کے ختم ہونے کے بعد بھی active رہتی ہے۔ یہ launcher والے معاملے کو حل کرتا ہے۔ یہ ایک unit کو متعدد آزاد process کے supervisor میں تبدیل نہیں کرتا۔ ExitType= کو Type=oneshot کے ساتھ بھی استعمال نہیں کیا جا سکتا۔

cgroup میں resource accounting بھی ہوتی ہے، اس لیے MemoryMax= اور CPUQuota= جیسی limits unit کے شروع کیے ہوئے ہر process پر لاگو ہوتی ہیں، چاہے main PID کے بارے میں Type= کچھ بھی کہے۔ اس پہلو کی وضاحت systemd کے ذریعے service کی memory اور CPU محدود کرنا میں موجود ہے۔

وہ عمل کیسے معلوم کریں جس کی systemd واقعی نگرانی کر رہا ہے

جس unit کی آپ debugging کر رہے ہیں، اس پر یہ کام اسی ترتیب سے کریں۔ پہلے دیکھیں کہ systemd نے کیا load کیا، پھر دیکھیں کہ وہ کس چیز کو track کر رہا ہے، اور آخر میں اس کا موازنہ process table سے کریں۔

systemctl cat app.service
systemctl show -p Type,ExitType,GuessMainPID,PIDFile,MainPID,RemainAfterExit app.service

systemctl cat unit file کو اس پر لاگو ہونے والے تمام drop-in کے ساتھ دکھاتا ہے۔ اس طرح آپ وہ configuration پڑھتے ہیں جو systemd نے load کی ہے، نہ کہ وہ file جس میں آپ کو ترمیم کرنا یاد ہے۔ systemctl show مؤثر values دکھاتا ہے، جن میں وہ defaults بھی شامل ہیں جو آپ نے کہیں درج نہیں کیے۔ آگے بڑھنے سے پہلے MainPID کی value نوٹ کریں۔

systemd-cgls --unit=app.service
ps -o pid,ppid,stat,etime,args -p "$(systemctl show -p MainPID --value app.service)"

systemd-cgls unit کے cgroup میں موجود ہر process کی فہرست دکھاتا ہے۔ ps line اس واحد process کی تفصیل دیتی ہے جس کی systemd نگرانی کرتی ہے۔ دونوں کو ساتھ پڑھیں۔ MainPID کی value 0 کا مطلب ہے کہ systemd کے پاس نگرانی کے لیے کوئی process نہیں ہے۔ اگر MainPID کسی shell process کی طرف resolve ہو، جبکہ cgroup میں آپ کا daemon بھی موجود ہو، تو یہ اوپر بیان کردہ wrapper case ہے۔ اگر cgroup میں آپ کی توقع سے زیادہ processes ہوں تو launcher یا forking daemon شامل ہے۔

systemctl status app.service
journalctl -u app.service -b

systemctl status state line اور cgroup tree کو ایک ساتھ دکھاتا ہے، اس لیے اکثر دونوں سوالوں کا جواب ایک ہی جگہ مل جاتا ہے۔ journalctl -u کو -b کے ساتھ صرف موجودہ boot تک محدود کرنے سے systemd کی unit کے لیے record کردہ start اور stop events، نیز اس کے دیکھے ہوئے exit codes دکھائی دیتے ہیں۔ اگر daemon اپنی log file میں لکھتا ہے، journal کے بجائے وہ file بھی پڑھیں، کیونکہ systemd صرف وہی record کر سکتا ہے جو اس تک پہنچے۔

جب آپ Type= تبدیل کریں تو reload اور restart کریں۔

systemd-analyze verify /etc/systemd/system/app.service
sudo systemctl daemon-reload
sudo systemctl restart app.service

systemd-analyze verify file کو parse کرتا ہے اور ایسی settings کی اطلاع دیتا ہے جنہیں وہ قبول نہیں کر سکتا۔ daemon-reload systemd کو disk سے unit files دوبارہ پڑھنے پر مجبور کرتا ہے۔ تبدیل شدہ Type= پہلے سے چل رہی unit پر لاگو نہیں ہوتا، اس لیے restart ضروری ہے، اختیاری نہیں۔

پھر تبدیلی کی جانچ کریں۔ جس process کی آپ کو واقعی ضرورت ہے، اس کا PID systemd-cgls سے حاصل کریں اور اسے kill کریں۔ فوراً بعد systemctl is-active app.service چلائیں۔ اگر Type= درست ہے تو unit active state سے نکل جائے گی۔ اگر یہ active رہے تو systemd اب بھی کسی اور چیز کی نگرانی کر رہا ہے۔

آپ کو کون سا systemd service Type= استعمال کرنا چاہیے

  • وہ program جو foreground میں چلتا رہتا ہے: Type=exec۔
  • وہ program جو readiness notification کو support کرتا ہے: Type=notify، اور اگر وہ reloads کی بھی تصدیق کرتا ہو تو notify-reload۔
  • وہ daemon جو لازماً background میں منتقل ہوتا ہے: Type=forking کو PIDFile= کے ساتھ استعمال کریں، یا اس کا foreground switch Type=exec استعمال کریں۔
  • وہ script جو کام مکمل کرکے exit ہو جاتی ہے: Type=oneshot؛ اور جب مقصد state باقی چھوڑنا ہو تو RemainAfterExit=yes بھی شامل کریں۔
  • وہ launcher جو exit ہو جاتا ہے جبکہ اس کے child processes چلتے رہتے ہیں: Type=simple کو ExitType=cgroup کے ساتھ استعمال کریں۔

اگر آپ کو یقین نہ ہو کہ کسی third-party daemon کے لیے کون سا option درکار ہے تو پہلے اس کی packaged unit file پڑھیں۔ distribution کی فراہم کردہ unit پر systemctl cat چلانے سے معلوم ہوتا ہے کہ upstream نے Type= منتخب کیا تھا، اور اس انتخاب کی آپ کے انتخاب کے مقابلے میں زیادہ لوگوں نے جانچ کی ہے۔

FAQ

میری systemd unit عمل ختم ہونے کے بعد بھی active کیوں رہتی ہے؟

کیونکہ وہ process ابھی زندہ ہے جسے systemd مرکزی process سمجھتا ہے۔ systemd یونٹ کے cgroup میں موجود ہر process کے بجائے، Type= کے مطابق منتخب کردہ ایک PID کو monitor کرتا ہے۔ Type=simple سے شروع کی گئی wrapper script اس کی عام وجہ ہے: shell مرکزی PID ہوتی ہے، اس لیے جب shell کے پس منظر میں شروع کیا گیا daemon ختم ہو جائے تو بھی unit active رہتی ہے۔ systemctl show -p MainPID app.service چلائیں، پھر systemd-cgls --unit=app.service کے ذریعے unit کا cgroup دکھائیں، اور دونوں کا موازنہ کریں۔

Type=simple اور Type=exec میں کیا فرق ہے؟

Type=simple یونٹ کو اسی وقت started سمجھتا ہے جب systemd نے process بنا دیا ہو، یعنی binary کے execute ہونے سے پہلے۔ اس لیے ExecStart= میں غلط path کے باوجود start job کامیاب دکھائی دے سکتی ہے، جس کے بعد failure ظاہر ہوتا ہے۔ Type=exec اس وقت تک انتظار کرتا ہے جب تک execution کامیاب نہ ہو جائے، اس لیے یہ failure خود start job میں رپورٹ ہوتی ہے۔ دونوں صورتوں میں ایک ہی process کو مرکزی PID سمجھا جاتا ہے۔ Type=exec کے لیے systemd 240 یا اس کے بعد کا ورژن درکار ہے۔

کیا Type=forking کے ساتھ بھی PIDFile= درکار ہے؟

ہاں، جب daemon یہ file لکھتا ہو۔ اس کے بغیر systemd GuessMainPID= پر واپس چلا جاتا ہے، جو ایک اندازہ ہے اور صرف اس service کے لیے قابلِ اعتماد ہوتا ہے جو بالآخر ایک ہی process پر مستحکم ہو جائے۔ جب یہ اندازہ غلط ہو یا ممکن نہ ہو تو اس unit کے لیے failure detection اور automatic restarting کام کرنا بند کر دیتے ہیں۔ PIDFile= کو اس exact path پر set کریں جہاں daemon file لکھتا ہے، جو عموماً /run کے تحت ہوتا ہے۔

RemainAfterExit=yes کب استعمال کرنا چاہیے؟

جب unit کا مقصد کسی process کو چلتا رکھنا نہیں بلکہ system state تبدیل کرنا ہو۔ Type=oneshot unit جو firewall rules load کرتی ہے یا container stack شروع کرتی ہے، اپنا کام مکمل ہوتے ہی exit ہو جاتی ہے۔ RemainAfterExit=yes کے بغیر unit inactive ہو جاتی ہے، جس کے باعث systemctl stop کے پاس stop کرنے کے لیے کچھ نہیں رہتا اور ExecStop= cleanup چلانے کا کوئی طریقہ نہیں رہتا۔ اس option کے ساتھ unit کسی process کے بغیر active رہتی ہے، اور یہاں یہی مطلوبہ رویہ ہے۔

کیا Type= تبدیل کرنے کے لیے daemon-reload درکار ہے؟

ہاں، اور unit کو restart کرنا بھی ضروری ہے۔ systemctl daemon-reload systemd کو disk پر موجود unit files دوبارہ پڑھنے پر مجبور کرتا ہے، لیکن چلتا ہوا instance وہی Type= استعمال کرتا رہتا ہے جس کے ساتھ وہ شروع ہوا تھا۔ testing سے پہلے sudo systemctl daemon-reload اور پھر sudo systemctl restart app.service چلائیں، ورنہ آپ اب بھی پرانے supervision behaviour کو monitor کر رہے ہوں گے۔