systemd میں Type=: simple، forking یا notify؟
unit active دکھائے مگر daemon ختم ہو چکا ہو؟ simple، exec، forking، oneshot اور notify کا درست Type= چنیں، اور حقیقی main PID تلاش کریں۔
systemd کسی unit کو اس وقت active کیوں دکھاتا ہے جب process ختم ہو چکا ہو
systemd service unit اس وقت active رہتی ہے جب تک وہ واحد process زندہ ہو جسے systemd main process کہتا ہے، اور Type=، [Service] section میں، یہ طے کرتا ہے کہ وہ process کون سا ہے۔ غلط value منتخب کرنے پر systemd کسی shell wrapper یا مختصر مدت تک چلنے والے parent process کی نگرانی کرتا رہتا ہے، جبکہ مطلوبہ daemon اسی unit کے اندر ختم ہو جاتا ہے۔ unit اس process کے بارے میں درست حالت بتا رہی ہوتی ہے جس کی نگرانی کرنے کی اسے ہدایت دی گئی تھی۔
Restart policy تبدیل کرنے سے یہاں مدد نہیں ملے گی۔ Restart= اس وقت عمل میں آتی ہے جب main process ختم ہوتا ہے، اس لیے Restart=always اس وقت تک کبھی فعال نہیں ہوگی جب تک main PID (process identifier) ایسے process سے وابستہ ہے جو ابھی چل رہا ہے۔ پہلے Type= درست کریں۔ main process کے واقعی ختم ہونے کے بعد systemd کیا کرتا ہے، یہ ایک الگ فیصلہ ہے، جس کی وضاحت Restart= اور RestartSec= کی رہنما دستاویز میں کی گئی ہے۔
Type= اصل میں کیا طے کرتا ہے
ہر Type= قدر بیک وقت دو سوالوں کا جواب دیتی ہے۔ systemd اس unit کو کب started سمجھ سکتا ہے، اور بنیادی process کون سا ہے۔
پہلا جواب ordering کو کنٹرول کرتا ہے۔ جو unit After= میں آپ کی unit کا نام دیتی ہے، وہ اس وقت تک انتظار کرتی ہے جب تک systemd آپ کی unit کو started نہ کہہ دے۔ ایسی Type= جو بہت جلد "started" رپورٹ کرے، dependent units کو اس وقت چلنے دیتی ہے جب آپ کی service ابھی ان کی درخواستوں کا جواب دینے کے قابل نہیں ہوتی۔
دوسرا جواب supervision کو کنٹرول کرتا ہے۔ systemd unit کے شروع کردہ ہر process کو cgroup (control group) میں رکھتا ہے۔ یہ kernel کی ایسی خصوصیت ہے جو processes کو ایک گروپ میں رکھتی ہے، تاکہ ان پر مشترکہ limits عائد کی جا سکیں اور انہیں ایک ساتھ ختم کیا جا سکے۔ systemctl stop صفائی اسی cgroup کے ذریعے کرتا ہے: KillMode= کی default قدر control-group ہوتی ہے، اس لیے کسی unit کو روکنے پر اس کے اندر موجود ہر process کو signal بھیجا جاتا ہے۔ بنیادی PID کا دائرہ اس سے محدود ہوتا ہے۔ یہی وہ واحد process ہے جس کے ختم ہونے سے unit ختم ہوتی ہے، اور اس کا exit status unit کا نتیجہ بن جاتا ہے۔ cgroup کو بنیادی PID سمجھ کر پڑھنا ہی اس الجھن کی ابتدا ہے۔
Type=simple binary کے چلنے سے پہلے ہی start ہونے کی اطلاع دیتا ہے
جب ExecStart= سیٹ ہو اور Type= یا BusName= میں سے کوئی بھی موجود نہ ہو تو Type=simple default ہوتا ہے۔ 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 نہ کر پانے کی failure کے طور پر کی گئی ہے۔ اس لیے systemctl start کا error کے بغیر return ہونا اس بات کا ثبوت نہیں کہ آپ کی binary موجود ہے۔
ایسے program کے لیے simple استعمال کریں جو foreground میں برقرار رہتا ہو اور خود کو background میں منتقل نہ کرتا ہو۔ زیادہ تر جدید daemons اور تقریباً ہر وہ program اسی زمرے میں آتا ہے جو آپ خود لکھتے ہیں۔
Type=exec پروگرام کے واقعی شروع ہونے تک انتظار کرتا ہے
Type=exec، simple کی ایک اضافی تکمیل کے ساتھ شکل ہے۔ systemd یونٹ کو صرف اس وقت started سمجھتا ہے جب fork اور binary کی execution دونوں کامیاب ہو جائیں۔ Missing binary یا ایسا User= جسے resolve نہ کیا جا سکے، اب start job کو خود fail کرتا ہے، بجائے اس کے کہ کامیابی رپورٹ ہو اور چند لمحوں بعد خاموشی سے failure واقع ہو۔
Type=exec systemd 240 میں شامل ہوا، اس لیے ہر موجودہ server distribution میں دستیاب ہے۔ August 2026 تک Ubuntu 24.04 میں systemd 255 اور Debian 13 میں systemd 257 شامل ہے۔ اپنا ورژن systemctl --version سے چیک کریں۔
اس کی قیمت start کے وقت synchronization کا ایک اضافی مرحلہ ہے۔ فائدہ systemctl start سے ملنے والا درست exit status ہے۔ Foreground program کے لیے simple کے بجائے exec استعمال کریں۔
Type=forking، اور main PID کیسے ضائع ہو جاتا ہے
Type=forking systemd کو بتاتا ہے کہ ExecStart= میں موجود process ایک child کو fork کرے گا اور پھر جان بوجھ کر exit ہو جائے گا۔ systemd اس پہلے process کے exit ہونے کا انتظار کرتا ہے، اور اس کے بعد ہی unit کو started قرار دیتا ہے۔ پیچھے رہ جانے والا child daemon ہوتا ہے۔ یہ طریقہ SysV دور سے چلا آ رہا ہے، جب init script کے واپس آنے کے بعد daemon کی نگرانی کرنے والا کوئی نظام موجود نہیں تھا اور PID file ہی چلنے والے process کا واحد ریکارڈ ہوتی تھی۔ یہی limitation systemd نے init scripts کی جگہ کیوں لی کی بنیادی وجوہات میں شامل ہے۔
مشکل process کی شناخت میں ہے۔ systemd نے جس process کو launch کیا تھا وہ ختم ہو چکا ہوتا ہے، اس لیے systemd کو معلوم کرنا پڑتا ہے کہ باقی رہنے والے processes میں main process کون سا ہے۔ PIDFile= کو اس file پر set کریں جو daemon لکھتا ہے۔ عموماً یہ path /run کے تحت ہوتا ہے۔ systemd اس file سے PID پڑھتا ہے۔ systemd یہ بھی جانچتا ہے کہ اس file میں موجود PID اسی service سے وابستہ process کا ہے۔ اس لیے کسی غیر متعلق process کی طرف اشارہ کرنے والی stale file کو trusted نہیں سمجھا جاتا بلکہ reject کر دیا جاتا ہے۔
PIDFile= کے بغیر GuessMainPID= نافذ ہوتا ہے، اور اس کی default value yes ہے۔ یہ اندازہ صرف اس وقت قابل اعتماد ہوتا ہے جب service ایک ہی process پر مستحکم ہو جائے۔ manual اس limitation کو واضح طور پر بیان کرتا ہے: اگر daemon ایک سے زیادہ processes پر مشتمل ہو تو اندازہ غلط ہو سکتا ہے، اور failure detection کام کرنا بند کر دیتی ہے۔ unit کا main PID 0 بھی ہو سکتا ہے۔ اس کا مطلب ہے کہ systemd کے پاس supervise کرنے کے لیے کوئی process موجود نہیں۔
زیادہ تر وہ daemons جو fork کرتے ہیں، انہیں foreground میں رکھنے کے لیے ایک switch بھی فراہم کرتے ہیں۔ یہ switch Type=exec کے ساتھ استعمال کریں اور PIDFile= والی line حذف کر دیں۔ کم اجزا ہونے سے PID ضائع ہونے کے امکانات بھی کم ہو جاتے ہیں۔
ایسے کام کے لیے Type=oneshot جو مکمل ہو کر ختم ہو جائیں
`Type=oneshot سے مراد ایسا process ہے جو چلنے کے بعد exit ہو جائے۔ systemd unit کو صرف process کے exit ہونے کے بعد started قرار دیتا ہے، اس لیے oneshot ایسی ہر چیز کے لیے موزوں ہے جس کے مکمل ہونے تک کسی دوسری unit کو انتظار کرنا ہو۔ اگر unit میں نہ Type= ہو اور نہ ExecStart=`، تو یہی اس کی مفروضہ default قسم بھی ہوتی ہے۔
`oneshot کے لیے دو رویے مخصوص ہیں۔ یہ واحد type ہے جو ایک سے زیادہ ExecStart= lines قبول کرتی ہے، اور یہ lines ترتیب وار چلتی ہیں۔ اس کا start timeout بھی default طور پر disabled ہوتا ہے، اس لیے اگر کوئی oneshot hang ہو جائے تو وہ ہمیشہ انتظار کرتا رہے گا، جب تک آپ خود TimeoutStartSec=` مقرر نہ کریں۔
process کے exit ہونے کے بعد unit دوبارہ inactive ہو جاتی ہے۔ `RemainAfterExit=yes اسے کسی process کے چلنے کے بغیر بھی active رکھتا ہے۔ یہ اس صفحے کے آغاز میں بیان کردہ symptom کی دانستہ صورت ہے، اور اس وقت درست ہے جب unit کا کام کسی چیز کو چلتا رکھنے کے بجائے state چھوڑنا ہو، مثلاً firewall ruleset load کرنا یا container stack شروع کرنا۔ یہی pattern [[docker-compose-auto-start-on-boot|ایسے Docker Compose stack کے پیچھے ہے جو reboot کے بعد دوبارہ شروع ہو جاتا ہے]]، جہاں unit compose command چلا کر exit ہو جاتی ہے اور active رہتی ہے، کیونکہ اس کے شروع کیے ہوئے containers اس سے زیادہ دیر تک چلتے رہتے ہیں۔ schedule جس unit کو trigger کرتا ہے، وہ بھی oneshot` unit ہوتی ہے۔ یہ 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 کرتے ہیں۔
یہ سوال "is it started" کا درست جواب فراہم کرتا ہے۔ simple اور exec سروس کے اپنی configuration پڑھنے یا listening socket کھولنے سے پہلے ہی started کی اطلاع دیتے ہیں۔ اس لیے dependent unit بہت جلد start ہو سکتی ہے اور اس کا پہلا connection ناکام ہو سکتا ہے۔ notify اس وقت started کی اطلاع دیتا ہے جب سروس خود کہتی ہے کہ وہ تیار ہے۔
systemd یہ message صرف main process سے قبول کرتا ہے۔ یہی بات NotifyAccess=main کا مطلب ہے، اور Type=notify اسے ظاہر کرتا ہے۔ اگر message کسی child یا helper سے آئے تو NotifyAccess=all set کریں۔ shell script systemd-notify --ready چلا سکتی ہے، لیکن یہ الگ short-lived process کے طور پر چلتا ہے۔ اس لیے اسے NotifyAccess=all درکار ہوتا ہے، اور systemd ممکن ہے ایسے message کو درست process سے منسوب نہ کر سکے جس کا sender پہلے ہی exit ہو چکا ہو۔ جو سروس خود یہ protocol استعمال کرتی ہو، وہ زیادہ قابلِ اعتماد ہے۔
دو متعلقہ settings بھی جاننا مفید ہے۔ Type=notify-reload، جو systemd 253 سے دستیاب ہے، اسی handshake کو reloads تک بڑھاتا ہے۔ اس لیے systemctl reload اس وقت return ہوتا ہے جب سروس reload مکمل ہونے کی اطلاع دیتی ہے، نہ کہ اس وقت جب signal بھیجا گیا ہو۔ WatchdogSec= notifying service سے کہتا ہے کہ وہ مقررہ وقفے پر keep-alive message بھیجے۔ systemd deadline miss ہونے کو failure سمجھتا ہے۔
Type=dbus اور Type=idle
Type=dbus اس وقت تک انتظار کرتا ہے جب تک service D-Bus پر اپنا نام حاصل نہ کر لے۔ 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 9101systemd shell کو main PID کے طور پر ریکارڈ کرتا ہے۔ shell اس وقت تک چلتی رہتی ہے جب تک exporter foreground میں چلتا رہتا ہے۔ اگر server بند ہو جائے تو shell کو اس کا علم نہیں ہوتا۔ اس لیے main PID اب بھی زندہ رہتا ہے، unit اب بھی active ہوتی ہے، اور Restart= کے پاس کارروائی کرنے کے لیے کچھ نہیں ہوتا۔ دونوں processes پورے وقت unit کے cgroup میں رہتے ہیں، اس لیے systemctl stop اب بھی cleanup درست طور پر کرتا ہے۔ خرابی supervision میں آئی ہے، cleanup میں نہیں۔
حل کا انحصار اس بات پر ہے کہ unit میں حقیقتاً کتنے long-running processes ہیں۔
اگر ایک process ہے تو shell کی جگہ وہی process چلائیں۔
#!/bin/bash
export APP_ENV=production
exec /opt/app/bin/server --config /etc/app.yamlexec shell کی جگہ نامزد program چلاتا ہے اور وہی 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 اچھی طرح supervision کرتی ہے، اور یہی واحد طریقہ ہے جس سے ہر 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 ہونے کا تاثر دے گا، اور باقی processes کو ختم کر دے گا۔ ExitType=cgroup کے ساتھ unit اس کے بجائے پورے process group کی پیروی کرتی ہے۔
یہ بات واضح رہنی چاہیے کہ یہ کیا حل نہیں کرتا۔ ExitType=cgroup unit کو اس وقت تک active رکھتا ہے جب تک کم از کم ایک process زندہ ہو۔ اس لیے دو daemons رکھنے والی unit، ان میں سے ایک کے ختم ہونے کے بعد بھی active رہتی ہے۔ یہ launcher والا مسئلہ حل کرتا ہے۔ یہ ایک unit کو متعدد آزاد processes کا supervisor نہیں بناتا۔ ExitType= کو Type=oneshot کے ساتھ بھی استعمال نہیں کیا جا سکتا۔
cgroup میں resource accounting بھی ہوتی ہے۔ اس لیے MemoryMax= اور CPUQuota= جیسی limits unit کے شروع کیے ہوئے ہر process پر لاگو ہوتی ہیں، خواہ Type= main PID کے بارے میں کچھ بھی کہے۔ اس پہلو کی مزید وضاحت systemd کے ذریعے service کی memory اور CPU محدود کرنا میں ہے۔
معلوم کریں کہ systemd حقیقت میں کس process کی نگرانی کر رہا ہے
جس unit کی debugging کر رہے ہیں، اسی پر یہ کام ترتیب سے کریں۔ پہلے دیکھیں کہ systemd نے کیا load کیا، پھر دیکھیں کہ وہ کس چیز کو track کر رہا ہے، اور آخر میں اس کا process table سے موازنہ کریں۔
systemctl cat app.service
systemctl show -p Type,ExitType,GuessMainPID,PIDFile,MainPID,RemainAfterExit app.servicesystemctl 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 پر resolve ہو، جبکہ cgroup میں آپ کا daemon بھی موجود ہو، تو یہ اوپر بیان کیا گیا wrapper case ہے۔ اگر cgroup میں آپ کی توقع سے زیادہ processes ہوں تو اس کا مطلب ہے کہ کوئی launcher یا forking daemon شامل ہے۔
systemctl status app.service
journalctl -u app.service -bsystemctl status state line اور cgroup tree کو ایک ساتھ دکھاتا ہے، اس لیے یہ اکثر دونوں سوالوں کا جواب دے دیتا ہے۔ journalctl -u کو -b کے ساتھ صرف موجودہ boot تک محدود کرنے سے systemd کی unit کے لیے record کیے گئے start اور stop events، نیز اس کے دیکھے ہوئے exit codes دکھائی دیتے ہیں۔ اگر daemon journal کے بجائے اپنی log file میں لکھتا ہے تو وہ file بھی پڑھیں، کیونکہ systemd صرف وہی record کر سکتا ہے جو اس تک پہنچے۔
جب آپ Type= تبدیل کریں تو reload اور restart کریں۔
systemd-analyze verify /etc/systemd/system/app.service
sudo systemctl daemon-reload
sudo systemctl restart app.servicesystemd-analyze verify file کو parse کرتا ہے اور ایسی settings کی رپورٹ دیتا ہے جنہیں وہ قبول نہیں کر سکتا۔ daemon-reload systemd کو disk سے unit files دوبارہ پڑھنے پر مجبور کرتا ہے۔ تبدیل شدہ Type= پہلے سے چل رہی unit پر لاگو نہیں ہوتا، اس لیے restart ضروری ہے، اختیاری نہیں۔
اس کے بعد تبدیلی test کریں۔ جس process کی آپ کو واقعی ضرورت ہے، اس کا PID systemd-cgls سے لیں اور اسے kill کریں۔ فوراً اس کے بعد systemctl is-active app.service چلائیں۔ اگر Type= درست ہے تو unit active state سے نکل جائے گی۔ اگر یہ active رہے تو systemd اب بھی کسی اور چیز کی نگرانی کر رہا ہے۔
کون سی systemd سروس Type= استعمال کرنی چاہیے
- ایسا پروگرام جو foreground میں چلتا رہے:
Type=exec۔ - ایسا پروگرام جو 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 چلانے سے وہ Type= ظاہر ہوتا ہے جسے upstream نے منتخب کیا تھا، اور اس انتخاب کی آپ کے انتخاب کے مقابلے میں زیادہ لوگوں نے جانچ کی ہے۔
FAQ
میری systemd unit process ختم ہونے کے باوجود active کیوں رہتی ہے؟
کیونکہ systemd جس process کو main process سمجھتا ہے، وہ اب بھی زندہ ہے۔ systemd unit کے cgroup میں موجود ہر process کے بجائے ہر service کے لیے صرف ایک PID کو monitor کرتا ہے، جس کا انتخاب Type= کے مطابق ہوتا ہے۔ Type=simple سے شروع کی گئی wrapper script اس کی عام وجہ ہے: shell، main PID ہوتا ہے، اس لیے جب shell کے background میں شروع کیا گیا daemon ختم ہو جائے تو بھی unit active رہتی ہے۔ systemctl show -p MainPID app.service چلائیں، پھر systemd-cgls --unit=app.service سے unit کا cgroup دکھائیں اور دونوں کا موازنہ کریں۔
Type=simple اور Type=exec میں کیا فرق ہے؟
Type=simple unit کو اسی وقت started تصور کرتا ہے جب systemd نے process بنا دیا ہو، یعنی binary execute ہونے سے پہلے۔ اس لیے ExecStart= میں غلط path ہونے کے باوجود start job کامیاب دکھائی دیتی ہے، جس کے بعد failure آتا ہے۔ Type=exec اس وقت تک انتظار کرتا ہے جب تک execution کامیاب نہ ہو جائے، اس لیے failure خود start job میں رپورٹ ہوتی ہے۔ دونوں ایک ہی process کو main PID سمجھتے ہیں۔ Type=exec کے لیے systemd 240 یا اس کے بعد کا ورژن درکار ہے۔
کیا Type=forking کے ساتھ بھی PIDFile= درکار ہے؟
ہاں، جب daemon یہ file لکھتا ہو۔ اس کے بغیر systemd GuessMainPID= پر واپس آتا ہے، جو ایک اندازہ ہے اور صرف ایسی service کے لیے قابلِ اعتماد ہوتا ہے جو ایک ہی process پر مستحکم ہو جائے۔ جب یہ اندازہ غلط یا ناممکن ہو تو اس unit کے لیے failure detection اور automatic restarting کام کرنا بند کر دیتے ہیں۔ PIDFile= کو اس درست path پر مقرر کریں جس پر daemon file لکھتا ہے، جو عموماً /run کے تحت ہوتا ہے۔
RemainAfterExit=yes کب استعمال کرنا چاہیے؟
جب unit کا مقصد کسی process کو چلتا رکھنا نہیں بلکہ system state تبدیل کرنا ہو۔ ایک Type=oneshot unit جو firewall rules load کرے یا container stack شروع کرے، اپنا کام مکمل ہوتے ہی ختم ہو جاتی ہے۔ RemainAfterExit=yes کے بغیر unit inactive ہو جاتی ہے، جس کے نتیجے میں systemctl stop کے پاس روکنے کے لیے کچھ نہیں رہتا اور ExecStop= cleanup چلانے کا بھی کوئی طریقہ نہیں ہوتا۔ اس setting کے ساتھ 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 کر رہے ہوں گے۔