চালু না হওয়া একটি systemd service প্রায় কখনোই রহস্যময় নয়। systemctl status <unit> চালান, তারপর journalctl -u <unit> -n 50 --no-pager দিয়ে ওই unit-এর শেষ 50টি journal লাইন পড়ুন — এই দুটোর মাঝেই পাঁচটি কারণের একটি সাধারণত সরাসরি ধরা পড়ে: ভুল path, হারিয়ে যাওয়া binary, ভুল permission, SELinux/AppArmor denial, বা unit ফাইলের syntax error। ব্যর্থতার কারণ লগেই লেখা আছে; নিচের সমাধানগুলো কেবল সেটার সঙ্গে pattern matching।
systemd service কেন ব্যর্থ হলো তা দেখবেন কীভাবে?
প্রথমে status, তারপর journal:
systemctl status myapp.service
journalctl -u myapp.service -n 50 --no-pager status আপনাকে state দেখায় (inactive (dead), failed (exit-code), activating (auto-restart)) এবং শেষ কয়েকটি লগ লাইন। journal দেয় পুরো গল্প: stdout, stderr, আর unit সম্পর্কে systemd-এর নিজের অভিযোগ।
unit আগে একবার ব্যর্থ হয়েছিল এবং সেই run-এর রেকর্ড চাইলে বর্তমান boot-এর জন্য -b, বা --since today যোগ করুন:
journalctl -u myapp.service -b --no-pager পুরো টুলকিট — boot, priority, লাইভ output ফলো করা — দেখুন journalctl cheat sheet-এ। একই অভ্যাস এখানেও কাজ করে।
আরেক জোড়া কমান্ড জেনে রাখা ভালো:
systemctl list-units --failed
systemctl reset-failed myapp.service প্রথমটি মেশিনের প্রতিটি লাল unit দেখায়। দ্বিতীয়টি ঠিক করার পরে failed state পরিষ্কার করে — নান্দনিকতা মাত্র, কিন্তু status পেজে বৃথা সতর্কবার্তা আটকায়।
সবচেয়ে সাধারণ কারণগুলো কী কী?
লগ লক্ষণটা বলে দিলে, কারণ প্রায় সবসময় এই পাঁচটির একটি:
| লগ কী বলে | সম্ভাব্য কারণ | সমাধান |
|---|---|---|
status=203/EXEC | ভুল ExecStart= path বা interpreter নেই | Absolute path, chmod +x, shebang দেখুন |
স্ক্রিপ্টে status=203/EXEC | স্ক্রিপ্টে CRLF line ending বা ভুল shebang | dos2unix script.sh, প্রথম লাইন ঠিক করুন |
status=1/FAILURE, app-এর লগ নেই | Working directory বা environment variable অনুপস্থিত | WorkingDirectory= সেট করুন, Environment= যোগ করুন |
Permission denied | ব্যবহারকারী ফাইল পড়তে বা port bind করতে পারছে না | মালিকানা ঠিক করুন; 1024-এর নিচের port-এ AmbientCapabilities=CAP_NET_BIND_SERVICE বা root দরকার |
Unit is masked | কেউ systemctl mask চালিয়েছে | systemctl unmask myapp.service |
| unit ফাইল সম্পাদনা “কিছুই করছে না” | daemon reload করা হয়নি | systemctl daemon-reload |
203/EXEC পরিবারের আলাদা উল্লেখ দরকার, কারণ অর্ধেক দিন খেয়ে ফেলে এটাই। systemd আপনার শেল ব্যবহার করে না ExecStart= চালু করতে। অর্থাৎ:
# ভুল — শেল নেই, ~ কখনো expand হয় না, PATH lookup নেই
ExecStart=~/app/run.sh
# সঠিক
ExecStart=/opt/app/run.sh আর স্ক্রিপ্টটা নিজে executable হতে হবে এবং সত্যিকারের shebang দিয়ে শুরু হতে হবে (#!/bin/bash বা #!/usr/bin/env bash)। টার্মিনালে চমৎকার চলা কিন্তু systemd-এর অধীনে 203 দিয়ে ব্যর্থ হওয়া স্ক্রিপ্ট প্রায় প্রতিবার এর যেকোনো একটি: executable নয়, CRLF ending, অচল shebang, বা relative path।
হাতে চালু হয় কিন্তু boot-এ হয় না কেন?
চিরাচরিত ordering bug। লগ boot-এর পরপরই ব্যর্থতা দেখায়, কিন্তু হাতে systemctl start করলে unit ঠিকঠাক চালু হয় — বুঝবেন আপনার service race-এ হারছে: network, mounted disk, বা database আসার আগেই সেটার জন্য হাত বাড়াচ্ছে।
সমাধান: আশা নয়, dependency ঘোষণা করুন:
[Unit]
After=network-online.target postgresql.service
Wants=network-online.target
[Service]
ExecStartPre=/usr/bin/test -f /opt/app/config.toml After= start-এর ক্রম ঠিক করে; Wants= systemd-কে সত্যিই dependency তুলতে বাধ্য করে। network-online.target কাজ করে তখনই যখন আপনার distro-তে network-wait service সক্রিয় — তাই systemctl is-enabled NetworkManager-wait-online.service দেখে নিন (বা systemd-networkd-এর সমতুল্যটি)। ExecStartPre= guard হলো সস্তা, সৎ একটা উপায় — stack trace-এর বদলে পাঠযোগ্য বার্তায় জোরে ব্যর্থ হওয়ার।
দ্বিতীয় রূপ: service boot-এ চালু হয় কিন্তু সঙ্গে সঙ্গে মারা যায়। খুঁজুন এমন জিনিস যা আপনার interactive environment-এ ছিল কিন্তু boot-এ নেই — PATH-এর পার্থক্য, virtualenv, বা HOME। দরকারি জিনিস স্পষ্টভাবে সেট করুন:
[Service]
Environment="PATH=/opt/app/venv/bin:/usr/bin"
User=appuser
WorkingDirectory=/opt/app আমার service journal-এ লগ করছে না কেন?
journalctl -u কিছুই না দেখালে, ক্রমে তিনটি জিনিস দেখুন:
- unit-এর
StandardOutput=ওStandardError=— হতে হবেjournal(ডিফল্ট) বাjournal+console। কেউ সেগুলোnullকরে রেখে থাকতে পারে। - app stdout-এর বদলে ফাইলে লেখে। systemd কেবল stdout/stderr ধরে; ফাইলে লেখা লগ journal-কে পুরোপুরি বাইপাস করে। হয় app-কে stdout-এর দিকে ফেরান, নয়তো ফাইলটাই পড়ুন।
- Storage limit পুরনো লাইন ফেলে দিয়েছে:
journalctl --disk-usageদেখুন, আর journal দমবন্ধ হলে/etc/systemd/journald.conf-এSystemMaxUse=।
start-টাই ডিবাগ করতে চাইলে boot-time context-এ শেল ঢোকানোর চেয়ে ভালো কিছু নেই:
[Service]
ExecStart=/bin/bash -c 'exec /opt/app/bin/server 2>&1' আর সত্যিকারের রহস্য হলে, unit-এর user হয়ে হুবহু ExecStart= কমান্ডটি শেলে চালান — বেশিরভাগ environment পার্থক্য প্রথম দশ সেকেন্ডেই ধরা পড়ে।
crash-এর পরে স্বয়ংক্রিয়ভাবে restart হবে কীভাবে?
ডিফল্ট নীতি Restart=no: crash করা service মৃতই থাকে, আর আপনি জানতে পারেন একজন user-এর মাধ্যমে। প্রতি service-এ সেটা ঠিক করুন:
[Service]
Restart=on-failure
RestartSec=5 | সেটিং | কখন restart হয় |
|---|---|
no (ডিফল্ট) | কখনোই না |
on-failure | শূন্যেতর exit, signal, timeout |
always | যেকোনো exit, পরিচ্ছন্ন হলেও |
on-watchdog | শুধু watchdog timeout |
Restart=on-failure-এর সঙ্গে start-rate guard জুড়ে দিন, যাতে crash-এর লুপ মেশিন পিটিয়ে না যায়: [Unit] সেকশনে StartLimitIntervalSec= ও StartLimitBurst=। ষাট সেকেন্ডে পাঁচবার ব্যর্থতা মানুষকে জাগানোর কথা, CPU ঘুরিয়ে রাখার নয়।
daemon-এর বদলে scheduled job হিসেবে বানাচ্ছেন? তাহলে আগে cron vs systemd timer মাপুন — timer journal লগিং ও dependency ordering বিনামূল্যে দেয়, এই নিবন্ধ যার জন্য বারবার হাত বাড়ায়।
60 সেকেন্ডের চেকলিস্ট
systemctl status <unit>— state ও শেষ লাইনগুলো পড়ুন।journalctl -u <unit> -n 50 --no-pager— আসল error খুঁজুন।203/EXEC? path, shebang, permission ঠিক করুন।Permission denied? user ও ফাইলের মালিকানা ঠিক করুন।- শুধু boot-এ ব্যর্থ?
After=/Wants=network-online.targetএবং একটিExecStartPre=guard যোগ করুন। - unit ফাইল বদলেছেন?
systemctl daemon-reload && systemctl restart <unit>। Restart=on-failureযোগ করুন, যাতে পরের crash লুকিয়ে না থেকে নিজেই ঘোষণা করে।
বেশিরভাগ “systemd জটিল” মুহূর্ত নেমে আসে এক জায়গায়: error টা শুরু থেকেই journal-এ ছিল। unit ফাইল সম্পাদনার আগে সেটা পড়ুন, পরে নয়।
— mrsaynothing
— mrsaynothing
AI, Linux ও self-hosting নিয়ে ফিল্ড নোটস।
পোস্টটি নিয়ে dev.to-তে আলোচনা করুন dev.to ↗
পরের হাউ-টু ইমেইলে পান
প্রতি পোস্টে একটি ইমেইল। সমাধান করুন, এগিয়ে যান।
এটা কী?GGUF quantization: কোন level ব্যবহার করবেন?
লেখাগুলো ভালো লাগছে? এমন জিনিস বানানোই আমার পেশা। আমাকে নিন