এই পর্বে যা শিখবেন
- Server-এ একটি process-এর জীবন, PID 1 আর SIGTERM থেকে graceful shutdown
- নিজে একটি unit file লেখা এবং
systemctlআরjournalctlদিয়ে চালানো ও খোঁজা - Restart policy, crash loop আর start limit-এর হিসাব, সংখ্যা ধরে
- cgroup দিয়ে CPU ও memory সীমা, আর sandboxing-এর কয়েকটি setting
- Load average, memory pressure, OOM kill পড়া এবং USE method দিয়ে প্রথম তদন্ত
১ · Server-এ process-এর জীবন — PID 1, signal আর ভদ্রভাবে থামা
আগের পর্বগুলোতে আপনি Linux-এ ঘোরাফেরা, shell আর script শিখেছেন। এবার আসল কাজ: একটি কাল্পনিক অনলাইন বাজার অ্যাপের API, bazar-api, একটি server-এ দিনরাত চালানো। এর আগে এক লাইনে মনে করিয়ে দিই। Process হলো চলমান প্রোগ্রাম; ভেতরের তত্ত্ব আছে Operating Systems কোর্সের প্রসেস, fork, exec আর wait আর Signal পর্বে। এখানে শুধু operations-এর দিকটি দেখব।
Linux boot-এর শেষে kernel একটিমাত্র user-space process চালায়। তার নম্বর, মানে PID, হয় 1. আধুনিক বেশিরভাগ distribution-এ PID 1 হলো systemd. বাকি সব process এরই বংশধর। কোনো process-এর বাবা আগে মরে গেলে অনাথ সন্তানকেও PID 1 দত্তক নেয়, আর শেষে তার exit status তুলে নেয়। পুরো boot-এর গল্প আছে বুট প্রক্রিয়া পর্বে।
একটি service-এর জীবনে তিনটি মুহূর্ত গুরুত্বপূর্ণ: কে তাকে চালাল, কীভাবে সে মারা গেল, আর তারপর কী হলো। মৃত্যুর পথ দুটি: নিজে শেষ হওয়া (exit), অথবা signal পাওয়া। Server-এ দুটি signal প্রতিদিনের সঙ্গী।
রাত দশটায় একটি শপিং মলের দোকান বন্ধ হচ্ছে। ম্যানেজার বললেন, “নতুন ক্রেতা আর নয়। যাঁরা ভেতরে আছেন তাঁদের বিল শেষ করুন, ক্যাশ মিলিয়ে তালা দিন।” এটি SIGTERM. আর হঠাৎ মেইন সুইচ কেটে শাটার নামিয়ে দেওয়া হলো SIGKILL. দ্বিতীয়টিতে দোকান নিশ্চিতভাবে বন্ধ হয়, কিন্তু অর্ধেক লেখা রশিদ আর না মেলানো ক্যাশ পড়ে থাকে।
| দিক | SIGTERM (15) | SIGKILL (9) |
|---|---|---|
| Process কি ধরতে পারে? | হ্যাঁ, handler লেখা যায়, উপেক্ষাও করা যায় | না, ধরা বা উপেক্ষা কোনোটিই যায় না |
| গুছিয়ে নেওয়ার সুযোগ | আছে | নেই |
| Handler না থাকলে শেষ হওয়ার পর shell-এ status | 143 (128 + 15) | 137 (128 + 9) |
| কে সাধারণত পাঠায় | systemctl stop, kill, Kubernetes, reboot-এর সময় systemd | সময়সীমা শেষে systemd, OOM killer, হতাশ মানুষ |
Graceful shutdown মানে SIGTERM পাওয়ার পর একটি নির্দিষ্ট ক্রম: নতুন কাজ নেওয়া বন্ধ, হাতের কাজ শেষ, buffer-এর data লেখা, database connection বন্ধ, তারপর exit 0. আর systemd বা অন্য manager অনন্তকাল অপেক্ষা করে না: সময়সীমা পেরোলে SIGKILL পাঠায়। systemd-তে এই সীমা TimeoutStopSec, ডিফল্ট সাধারণত ৯০ সেকেন্ড।
নিচের Bash block সেই আচরণটি ছোট আকারে দেখায়। পেছনে চলা worker-এর সারিতে পাঁচটি কাজ আছে। stop_unit ফাংশন systemd-র ভূমিকায়: আগে SIGTERM, সময় পেরোলে SIGKILL. কাজ ১০৩ চলার সময় signal আসে। দ্বিতীয় ঘটনায় একটি জেদি process SIGTERM উপেক্ষা করে।
tmp=$(mktemp -d)
worker() { # a fake service with 5 queued jobs
local stop=0
trap 'stop=1; echo " worker: SIGTERM, no new job after this one"' TERM
for job in 101 102 103 104 105; do
[ "$stop" = 1 ] && break
echo " worker: start job $job"
if [ "$job" = 103 ]; then # the signal arrives during job 103
touch "$tmp/busy"
until [ -e "$tmp/sent" ]; do sleep 0.01; done
fi
echo " worker: done job $job"
done
echo " worker: state saved, exit 0"; exit 0
}
stubborn() { trap '' TERM; touch "$tmp/busy"; while :; do sleep 0.01; done; }
stop_unit() { # $1 = job pid, $2 = grace in 0.01 s ticks
until [ -e "$tmp/busy" ]; do sleep 0.01; done
echo "manager: send SIGTERM"
kill -TERM "$1"; touch "$tmp/sent"
for ((i = 0; i < $2; i++)); do
kill -0 "$1" 2>/dev/null || break
sleep 0.01
done
if kill -0 "$1" 2>/dev/null; then
echo "manager: grace over, send SIGKILL"; kill -KILL "$1"
fi
wait "$1" 2>/dev/null; echo "manager: exit status $?"
rm -f "$tmp/busy" "$tmp/sent"
}
echo "== case 1: handles SIGTERM =="; worker & stop_unit $! 500
echo "== case 2: ignores SIGTERM =="; stubborn & stop_unit $! 30
rm -rf "$tmp"আউটপুট:
== case 1: handles SIGTERM ==
worker: start job 101
worker: done job 101
worker: start job 102
worker: done job 102
worker: start job 103
manager: send SIGTERM
worker: SIGTERM, no new job after this one
worker: done job 103
worker: state saved, exit 0
manager: exit status 0
== case 2: ignores SIGTERM ==
manager: send SIGTERM
manager: grace over, send SIGKILL
manager: exit status 137
প্রথম ঘটনায় কাজ ১০৩ অর্ধেক অবস্থায় মরেনি, শেষ হয়েছে; ১০৪ আর ১০৫ সারিতেই রয়ে গেছে, পরের process নেবে। Status 0, মানে পরিষ্কার বিদায়। দ্বিতীয় ঘটনায় SIGTERM কোনো কাজে আসেনি, তাই সময় শেষে SIGKILL, আর status 137. Log-এ 137 দেখলেই ভাবুন: কেউ জোর করে মেরেছে। একই সংকেত memory সীমাতেও আসে, যা পরে দেখব। block-টি কোনো sleep-এর ভাগ্যে নির্ভর করে না, ফাইল দিয়ে দুই পক্ষ অপেক্ষা মেলায়, তাই আউটপুট প্রতিবার এক।
Container-এ একটি ফাঁদ আছে। Container-এর ভেতরে আপনার অ্যাপই প্রায়ই PID 1, আর kernel PID 1-কে এমন signal দেয় না যার handler সে লেখেনি। তাই handler ছাড়া অ্যাপ SIGTERM-এ থামে না, সময়সীমা শেষে SIGKILL খায়। বিস্তারিত পর্ব ৩৯ (Container চালানো) আর পর্ব ৪৩ (Pod).
২ · nohup বনাম service — কেন একজন ম্যানেজার দরকার
নতুন অনেকে SSH করে server-এ ঢুকে এভাবে অ্যাপ চালান। শব্দটি মনে রাখুন: nohup মানে “no hangup”. Terminal বন্ধ হলে process-কে SIGHUP পাঠানো হয়; nohup সেটি উপেক্ষা করতে বলে আর আউটপুট nohup.out-এ পাঠায়।
# works today, breaks on the first crash or reboot
nohup node server.js &এটি চলে। রাত তিনটায় একটি unhandled exception হলো, process শেষ। কেউ জানে না। সকালে ক্রেতারা অভিযোগ করবেন। Cloud provider server restart করলেও একই দশা। এই ভঙ্গুরতাই service-এর সংজ্ঞা তৈরি করে: terminal ছাড়া পেছনে দীর্ঘ সময় চলা process-কে বলে daemon, আর তাকে একজন manager-এর হাতে তুলে দেওয়া হলো service হিসেবে চালানো।
nohup হলো দোকান খোলা রেখে কর্মচারীকে বলে চলে যাওয়া। তিনি অসুস্থ হলে দোকান বন্ধ, মালিক জানেন না। systemd হলো একজন সার্বক্ষণিক ম্যানেজার, যাঁর হাতে প্রতিটি কর্মচারীর চুক্তিপত্র আছে: কে কখন আসবেন, অসুস্থ হলে কতবার বদলি ডাকা হবে, কতটুকু রসদ পাবেন, খাতায় কী লিখবেন।
| প্রশ্ন | nohup … & | systemd service |
|---|---|---|
| Crash হলে | শেষ, কেউ জানে না | Restart= অনুযায়ী আবার চলে |
| Reboot-এর পর | ফিরে আসে না | enable করা থাকলে নিজে চলে |
| Log | একটি বাড়তে থাকা ফাইল | journal-এ, সময় ও unit ধরে খোঁজা যায় |
| কোন user | যিনি কমান্ড দিলেন | নির্দিষ্ট, কম ক্ষমতার user |
| Resource সীমা | নেই | cgroup দিয়ে CPU, memory সীমা |
| থামানো | PID খুঁজে হাতে kill | systemctl stop, পুরো দলকে ক্রম মেনে |
systemd যা সামলায় তার প্রতিটিকে বলে unit. Unit-এর ধরন ফাইলের শেষাংশে লেখা থাকে: .service (process), .timer (সময়সূচি, পর্ব ১০-এ দেখেছেন), .socket, .mount, আর .target. Target হলো কয়েকটি unit-এর দল; multi-user.target মোটামুটি বলে “server সাধারণ কাজের জন্য তৈরি”।
একটি unit যেকোনো সময় কোনো একটি অবস্থায় থাকে। নিচের ছবিটি মাথায় গেঁথে নিন, কারণ systemctl status-এর Active: লাইনে ঠিক এই শব্দগুলোই আসে।
একটি service unit-এর অবস্থাচক্র
Unit lifecycle: inactive, activating, active, deactivating, failed
RestartSec অপেক্ষার সময় status-এ activating (auto-restart) দেখায়। Activating অবস্থা থেকেও failed হতে পারে। আর enabled বা disabled এই চক্রের অংশ নয়; সেটি আলাদা প্রশ্ন, boot-এ চলবে কি না।আগে Linux-এ service চলত SysV init-এর shell script দিয়ে, ক্রম ধরে একটির পর একটি। Ubuntu ২০০৬ সালে Upstart আনে। ২০১০ সালে Lennart Poettering আর Kay Sievers শুরু করেন systemd, যার ওপর Apple-এর launchd-এর প্রভাব ছিল বলে Poettering নিজেই লিখেছেন। RHEL 7 (২০১৪), Debian 8 আর Ubuntu 15.04 (২০১৫) একে ডিফল্ট করার পর এটি প্রধান ধারা হয়ে ওঠে। তবে Alpine-এর মতো কিছু distribution এখনো অন্য init ব্যবহার করে।
৩ · Unit file লেখা — service-এর চুক্তিপত্র
Unit file একটি ছোট লেখা ফাইল, রান্নাঘরের রেসিপি খাতার পাতার মতো: কী লাগবে, কোন ক্রমে, ব্যর্থ হলে কী। নিজের লেখা unit রাখা হয় /etc/systemd/system/-এ; package-এর দেওয়া unit থাকে সাধারণত /usr/lib/systemd/system/-এ, আর একই নাম হলে /etc-এরটি জেতে। নিচের নমুনাটি runner-এ চলবে না, কারণ runner-এ systemd নেই; এটি পড়ার জন্য।
# /etc/systemd/system/bazar-api.service
[Unit]
Description=Bazar API (fictional shop app)
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Type=simple
User=bazar
Group=bazar
WorkingDirectory=/opt/bazar-api
Environment=PORT=8080 NODE_ENV=production
EnvironmentFile=/etc/bazar-api/env
ExecStart=/usr/bin/node /opt/bazar-api/server.js
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target| Setting | কী করে | যা ভুল হয় |
|---|---|---|
ExecStart | যে কমান্ড চলবে। পুরো path লিখুন | এটি shell নয়, তাই &, > বা pipe কাজ করে না |
Type | কখন “চালু হয়েছে” ধরা হবে। simple মানে process শুরু হলেই; notify মানে অ্যাপ নিজে জানালে | নিজে background-এ যাওয়া অ্যাপ simple দিয়ে চালালে systemd তাকে মৃত ভাবে |
User, Group | কোন পরিচয়ে চলবে। না দিলে system service চলে root হিসেবে | অকারণে root রাখা; এটি least privilege-এর উল্টো |
Environment, EnvironmentFile | Environment variable বসায় | Unit file-এ password লেখা। ফাইলটি সবাই পড়তে পারে। Secret রাখুন কড়া অনুমতির আলাদা ফাইলে (পর্ব ৩৩) |
Restart, RestartSec | কখন আবার চলবে, কত পরে। ডিফল্ট Restart=no, RestartSec ১০০ মিলিসেকেন্ড | Restart না লিখলে crash-এ service পড়েই থাকে |
After | শুধু ক্রম: ওটি চালু হলে তার পরে শুরু হবে | ভাবা যে এটি ওটিকে চালুও করবে |
Wants | নির্ভরতা: ওটিকেও চালু করতে চাই, ব্যর্থ হলেও আমি চলব | Wants একা ক্রম ঠিক করে না, তাই সাধারণত After-সহ লেখা হয় |
WantedBy | [Install]-এর অংশ: enable করলে কোন target-এর সাথে boot-এ চলবে | এটি না থাকলে enable কিছুই করে না |
এবার দেখা যাক systemctl start দিলে ফাইল থেকে চলন্ত process পর্যন্ত আসলে কী কী ঘটে। “পরে” চাপুন।
- কমান্ড
systemctlPID 1-কে অনুরোধ - Job
limit, orderনিয়ম যাচাই - cgroup
memory.maxআলাদা ঘর - fork, exec
User=bazarনতুন process - Type
simpleকখন “চালু” - active
runningjournal-এ log
$ sudo systemctl start bazar-api
# systemctl নিজে অ্যাপ চালায় না; সে PID 1-কে বলে
unit : bazar-api.service (already loaded)
limit : 0 of 5 starts in window, allowed
Wants : network-online.target
After : wait until that target is done
job : start, queued
/sys/fs/cgroup/system.slice/bazar-api.service/ # সীমা লেখা থাকলে এখানে বসে (অংশ ৬ দেখুন) memory.max 536870912 cpu.max 150000 100000
fork() # systemd-র একটি কপি set cgroup, sandbox, env, cwd setuid(bazar) # root থেকে নেমে আসা exec /usr/bin/node /opt/bazar-api/server.js
simple : process শুরু হলেই # port খোলার আগেই! exec : exec সফল হলে notify : অ্যাপ READY=1 পাঠালে # সবচেয়ে সৎ
$ systemctl status bazar-api
Active: active (running) since Fri 2026-10-30 14:02:11 +06
Main PID: 2417 (node)
CGroup: /system.slice/bazar-api.service
└─2417 /usr/bin/node /opt/bazar-api/server.js
- অনুরোধ।
systemctlশুধু একটি দূত। সে D-Bus-এর মতো পথে PID 1-কে বলে “এই unit চালান”। তাই অ্যাপটি আপনার shell-এর সন্তান হয় না, আর SSH কেটে গেলেও এর কিছু হয় না। - Job আর যাচাই। systemd তার memory-তে লোড করা unit দেখে, ডিস্কের ফাইল নয়। এজন্যই ফাইল বদলে
daemon-reloadছাড়া পুরোনো নিয়ম চলে। Start limit আরAfter-এর ক্রমও এখানে দেখা হয়; ৫-এর মধ্যে ০ বার হয়েছে, তাই অনুমতি মিলল। - cgroup তৈরি। Service-এর নামে একটি cgroup হয়। এর পর থেকে অ্যাপের সব সন্তান process একই ঘরে থাকবে, তাই systemd কাউকে হারায় না। পাশের সংখ্যা দুটি অংশ ৬-এর
MemoryMax=512MআরCPUQuota=150%-এর ফল। - fork আর exec. systemd নিজের একটি কপি বানায়। কপিটি cgroup, sandbox, environment আর working directory ঠিক করে,
bazaruser হয়, তারপরexecকরে node হয়ে যায়। - Type সিদ্ধান্ত নেয়।
Type=simple-এ process শুরু হলেই systemd বলে “চালু”, যদিও অ্যাপ হয়তো তখনো port খোলেনি। অন্য service যদি এর ওপর নির্ভর করে, তার জন্যnotifyবেশি সৎ, তবে অ্যাপকে সেটি পাঠাতে হয়। - চলছে। অবস্থা
active (running), PID 2417. অ্যাপের stdout আর stderr নিজে থেকেই journal-এ যাচ্ছে। লক্ষ করুন, “active” মানে process বেঁচে আছে, অ্যাপ সুস্থ এমন প্রমাণ নয়। সেজন্য আলাদা health check লাগে।
৪ · systemctl আর journalctl — চালানো আর খোঁজা
systemd-কে কমান্ড দেওয়ার টুল হলো systemctl. প্রতিদিনের কমান্ড অল্প কয়েকটি। সবচেয়ে বেশি গুলিয়ে যায় তিনটি জোড়া: start বনাম enable, restart বনাম reload, আর reload বনাম daemon-reload.
| কমান্ড | যা বদলায় | যা বদলায় না |
|---|---|---|
start, stop | এখনকার অবস্থা | boot-এর সিদ্ধান্ত |
enable, disable | boot-এর সিদ্ধান্ত (multi-user.target.wants/-এ symlink) | এখনকার অবস্থা |
enable --now | দুটোই | — |
restart | process থামিয়ে আবার চালায়, নতুন PID | ডিস্কের unit file পড়ে না |
reload | অ্যাপকে config আবার পড়তে বলে (ExecReload থাকলে), PID একই | unit file পড়ে না |
daemon-reload | systemd unit file আবার পড়ে | চলন্ত service-এ কিছু হয় না |
reset-failed | failed অবস্থা আর start limit-এর হিসাব মোছে | মূল সমস্যা |
তাই unit file বদলানোর পর ক্রমটি হলো: ফাইল সম্পাদনা, daemon-reload, restart, যাচাই। অন্যের unit বদলাতে মূল ফাইলে হাত না দিয়ে systemctl edit ব্যবহার করুন; এটি একটি drop-in override বানায়, যা package আপডেটে হারায় না।
sudo systemctl daemon-reload # read the new file
sudo systemctl enable --now bazar-api # boot + right now
systemctl status bazar-api # read Loaded and Active
systemctl is-active bazar-api # prints: active
systemctl is-enabled bazar-api # prints: enabled
systemctl cat bazar-api # file plus drop-ins, as loadedstatus-এর এই দুটি লাইন আগে পড়ুন। Loaded বলে boot-এর সিদ্ধান্ত (enabled), Active বলে এই মুহূর্তের অবস্থা। নিচেরটি নমুনা আউটপুট, version-ভেদে আলাদা হতে পারে।
● bazar-api.service - Bazar API (fictional shop app)
Loaded: loaded (/etc/systemd/system/bazar-api.service; enabled; preset: enabled)
Active: active (running) since Fri 2026-10-30 14:02:11 +06; 3h 12min ago
Main PID: 2417 (node)
Tasks: 11 (limit: 512)
Memory: 186.4M (high: 450.0M max: 512.0M available: 263.6M)
CPU: 2min 41.302s
CGroup: /system.slice/bazar-api.service
└─2417 /usr/bin/node /opt/bazar-api/server.js
journal থেকে ঠিক লাইনটি বের করা
Service-এর stdout আর stderr journald-এ জমা হয়। journalctl হলো সেই খাতা পড়ার যন্ত্র। পর্ব ৯-এর grep-এর আগে এর নিজের ছাঁকনি ব্যবহার করুন; উত্তর দ্রুত আসে।
journalctl -u bazar-api -n 50 --no-pager # last 50 lines of one unit
journalctl -u bazar-api -f # follow live
journalctl -u bazar-api --since "2026-10-30 14:00" --until "2026-10-30 14:30"
journalctl -u bazar-api -b # this boot only
journalctl -b -1 -p err # previous boot, err and worse
journalctl -k -g "out of memory" # kernel log, search text
journalctl -u bazar-api -o json-pretty -n 1 # every field of one entry
journalctl --disk-usage # how much the journal holdsদুটি ফাঁদ। এক, -p err journal-এর priority দেখে, লেখার শব্দ নয়। অ্যাপ console.log("ERROR ...") লিখলে journal সেটিকে সাধারণত info ধরে, তাই -p err-এ আসে না; তখন -g ERROR লাগবে। দুই, -b -1 কাজ করতে journal ডিস্কে থাকা চাই। কিছু distribution-এ ডিফল্টে /run-এ থাকে এবং reboot-এ হারায়; /var/log/journal আছে কি না দেখে নিন।
৫ · Restart policy আর crash loop — কখন থামতে হবে
Restart policy বলে process থামলে কী হবে। Restart=-এর প্রধান মান:
| মান | কখন আবার চলে | কোথায় মানায় |
|---|---|---|
no (ডিফল্ট) | কখনো নয় | একবারের কাজ |
on-failure | non-zero exit, অপরিষ্কার signal, timeout, watchdog | বেশিরভাগ API, worker |
on-abnormal | signal, timeout, watchdog; non-zero exit-এ নয় | যে অ্যাপ ইচ্ছা করে non-zero দিয়ে থামে |
always | যেভাবেই থামুক (হাতে systemctl stop ছাড়া) | যা কখনোই থামার কথা নয়, যেমন agent |
এখানে “পরিষ্কার” মানে exit 0, অথবা SIGTERM, SIGHUP, SIGINT, SIGPIPE দিয়ে শেষ হওয়া। কিন্তু কোড যদি প্রতিবার ভেঙে পড়ে? ভুল config, ভাঙা database, ফুরিয়ে যাওয়া secret — এসবে restart কিছুই ঠিক করে না। এই চক্রের নাম crash loop.
গাড়ি স্টার্ট না নিলে চালক বারবার চাবি ঘোরান। দু-তিনবারে সাড়া দিলে ভালো। কিন্তু দশবার ঘোরালে ব্যাটারি শেষ, গাড়ি তবু চলে না। ভালো চালক একটা সীমায় থেমে মিস্ত্রি ডাকেন। Start limit ঠিক সেই সীমা।
নিয়মটি হলো: StartLimitIntervalSec সময়ের মধ্যে StartLimitBurst-এর বেশি start হবে না। ডিফল্ট সাধারণত ১০ সেকেন্ডে ৫ বার। দুটিই [Unit] section-এ বসে, এবং নিয়মটি হাতের systemctl start-কেও গোনে। এবার সবচেয়ে কাজের হিসাবটি। ধরুন process চালু হওয়ার u সেকেন্ড পরে ভেঙে পড়ে, আর r হলো RestartSec. তাহলে এক চক্র u + r. সীমা আটকাতে পারবে কেবল তখনই, যখন:
না হলে window ফুরিয়ে গণনা শূন্য হয়, crash loop চলতেই থাকে
নিচের simulator চারটি ঘটনা এক ঘণ্টার কাল্পনিক ঘড়িতে চালায়। সব সময় মিলিসেকেন্ডে, কোনো আসল ঘড়ি বা random নেই।
// systemd Restart= with a start limit, on a simulated clock (milliseconds).
// Fixed window, like systemd's rate limiter: the count resets once the
// window has passed. A crash happens "uptimeMs" after every start.
function run(c) {
let t = 0, begin = -1, num = 0, starts = 0, crashes = 0, last = 0;
while (t < c.horizonMs) {
if (begin < 0 || t > begin + c.intervalMs) { begin = t; num = 0; }
if (num >= c.burst) return [starts, crashes, 'failed (limit hit)', t];
num++; starts++; last = t;
if (crashes >= c.crashLimit) return [starts, crashes, 'active (healthy)', t];
t += c.uptimeMs; crashes++;
t += c.restartMs;
}
return [starts, crashes, 'still looping', last];
}
const hour = 3600000;
const cases = [ // name, restart, window, burst, uptime, crashes until fixed
['A default 100ms 10s/5', 100, 10000, 5, 200, 1e9],
['B slow 5s 10s/5', 5000, 10000, 5, 1000, 1e9],
['C tuned 5s 300s/5', 5000, 300000, 5, 1000, 1e9],
['D transient 5s 300s/5', 5000, 300000, 5, 1000, 2],
];
console.log('case starts crashes end state at');
for (const [label, restartMs, intervalMs, burst, uptimeMs, crashLimit] of cases) {
const [s, cr, end, at] = run({ restartMs, intervalMs, burst, uptimeMs, crashLimit, horizonMs: hour });
console.log(label.padEnd(25), String(s).padStart(6), String(cr).padStart(7),
' ' + end.padEnd(18), (at / 1000).toFixed(1) + 's');
}
// The limit can stop a loop only if burst full cycles fit inside the window.
for (const [label, r, i, b, u] of cases.slice(0, 3)) {
const need = (b * (r + u)) / 1000;
console.log(label[0], 'needs', need + 's', need < i / 1000 ? '< window: stops' : '>= window: never stops');
}আউটপুট:
case starts crashes end state at
A default 100ms 10s/5 5 5 failed (limit hit) 1.5s
B slow 5s 10s/5 600 600 still looping 3594.0s
C tuned 5s 300s/5 5 5 failed (limit hit) 30.0s
D transient 5s 300s/5 3 2 active (healthy) 12.0s
A needs 1.5s < window: stops
B needs 30s >= window: never stops
C needs 30s < window: stops
A: ডিফল্টে এক চক্র ০.৩ সেকেন্ড, ৫ বার পরে ১.৫ সেকেন্ডে ঠেকে যায়। সীমা কাজ করল, তবে এত দ্রুত যে ছোট database বিভ্রাটেও service হাল ছেড়ে দেয়। B সবচেয়ে বিপজ্জনক: কেউ ভালো ভেবে RestartSec=5 দিলেন, কিন্তু window বদলালেন না। ১০ সেকেন্ডে দুটির বেশি start হয়ই না, তাই এক ঘণ্টায় ৬০০ বার crash, অথচ status-এ কখনো failed আসে না। C: ৫ × ৬ = ৩০ সেকেন্ড, ৩০০-এর অনেক কম, তাই ৩০ সেকেন্ডে থামে। D: দুবার ভেঙে তৃতীয়বার সুস্থ, মানে ক্ষণস্থায়ী সমস্যা; restart ঠিক এই ঘটনার জন্যই। C আর D একই setting, তাই একটি ভালো policy দুটোই সামলায়।
এবার ছোট সংখ্যায় একটি crash loop ধাপে ধাপে দেখুন। ধরুন RestartSec=5, StartLimitIntervalSec=60, StartLimitBurst=3, আর ভুল database password-এর কারণে অ্যাপ প্রতিবার ১ সেকেন্ড পরে exit 1 দেয়।
| সময় | |
| Active | |
| window-এ start |
- t = ০. প্রথম start, window শুরু। গণনা ৩-এর মধ্যে ১। Status দেখলে সব ঠিক মনে হবে, কারণ
Type=simple-এ শুরু হওয়াই “active”. - t = ১. Password ভুল, exit 1.
Restart=on-failure-এর নিয়মে আবার চলবে, তবে ৫ সেকেন্ড পরে। এই অপেক্ষার সময় অবস্থাactivating (auto-restart). - t = ৬. দ্বিতীয় start, গণনা ২। Database ভাঙা থাকলে এখানে সুস্থ হওয়ার সুযোগ ছিল।
- t = ৭. আবার exit 1, কারণ password ভুলই আছে। Restart এই ভুল ঠিক করতে পারে না।
- t = ১২. তৃতীয় start. গণনা ৩, সীমায় পৌঁছে গেল, তবে এই start অনুমোদিত।
- t = ১৩. তৃতীয় crash. systemd পরের চেষ্টা ৫ সেকেন্ড পরের জন্য ঠিক করল।
- t = ১৮. ১৮ সেকেন্ড ৬০-এর ভেতরে, আর গণনা ৩ = burst, তাই চতুর্থ start নিষিদ্ধ। journal-এ আসে
Start request repeated too quickly, অবস্থাfailed. এখন এটি একটি স্পষ্ট alert-যোগ্য অবস্থা। হিসাব মিলছে: ৩ × ৬ = ১৮ < ৬০. - t = ৯০০. On-call প্রকৌশলী journal পড়ে password ঠিক করলেন।
reset-failedদিয়ে হিসাব মুছে আবারstart; গণনা নতুন করে ১। পুরো ঘটনার একটি লাইন runbook-এ যাবে।
৬ · Resource সীমা আর sandboxing — একজনের ভুলে সবাই যেন না ডোবে
একটি server-এ কয়েকটি service থাকে। একটির memory leak যেন পুরো machine না ডোবায়। মেসের কথা ভাবুন: এক সাব-মিটার ছাড়া একজনের হিটার সবার বিল বাড়ায়। সাব-মিটার বসালে প্রত্যেকের হিসাব ও সীমা আলাদা। সেই সাব-মিটার হলো cgroup. Linux এই সুবিধা দেয়, আর systemd প্রতিটি service-কে নিজের cgroup-এ রাখে; ভেতরের তত্ত্ব আছে Linux-এর scheduler পর্বে। Docker আর Kubernetes-ও একই kernel সুবিধা ব্যবহার করে (পর্ব ৩৯, ৪৮)।
# sudo systemctl edit bazar-api (saved as a drop-in override)
[Service]
MemoryHigh=450M
MemoryMax=512M
CPUQuota=150%
TasksMax=512
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/lib/bazar-api| Setting | মানে |
|---|---|
MemoryMax | কঠিন সীমা। এখানে পৌঁছালে kernel আগে memory ফেরানোর চেষ্টা করে, না পারলে এই cgroup-এর ভেতরেই OOM kill |
MemoryHigh | নরম সীমা। Kill করে না, process-কে ধীর করে আর memory ফিরিয়ে নেয়। এটি একটি আগাম সতর্ক রেখা |
CPUQuota | একটি core-এর শতাংশ। 150% মানে প্রতি ১০০ মিলিসেকেন্ডে সর্বোচ্চ ১৫০ মিলিসেকেন্ড CPU সময় |
TasksMax | process ও thread সংখ্যার সীমা, যাতে নিয়ন্ত্রণহীন fork না চলে |
NoNewPrivileges | setuid প্রোগ্রাম চালিয়েও এই process আর বেশি ক্ষমতা পাবে না |
ProtectSystem=strict | পুরো filesystem এই service-এর চোখে read-only; শুধু ReadWritePaths লেখা যাবে |
ProtectHome | /home, /root তার কাছে অদৃশ্য |
PrivateTmp | নিজের আলাদা /tmp; অন্য service-এর ফাইল দেখে না |
হিসাবের দুটি ফাঁদ। এক, CPUQuota=50% চার core-এর machine-এর অর্ধেক নয়, একটি core-এর অর্ধেক; মানে পুরো machine-এর ১২.৫%. চার core-এর পুরোটা হলো 400%. দুই, systemd-র M হলো 1024 ভিত্তিক: 512M = 512 × 1024 × 1024 = 536,870,912 byte, যা এই পর্বের stepper-এর memory.max-এর সাথে মেলে।
Sandboxing বাগ ঠিক করে না, ক্ষতির blast radius ছোট করে। অ্যাপ দখল হলেও সে সিস্টেম ফাইল বদলাতে পারে না, আর /tmp দিয়ে অন্য service-এর গোপন ফাইল দেখতে পারে না। ভেতরে এগুলো namespace ও অন্যান্য kernel সুবিধা; তত্ত্ব আছে Sandboxing পর্বে। systemd-analyze security bazar-api একটি service-এর উন্মুক্ততার মোটামুটি নম্বর দেয়, যা হিসেবে ভালো তবে নিরাপত্তার প্রমাণ নয়। নতুন setting একটি একটি করে যোগ করুন, কারণ ProtectSystem=strict অ্যাপের লেখার পথ বন্ধ করে ভেঙে দিতে পারে।
৭ · Load average, memory pressure আর OOM killer
এবার পুরো machine-এর স্বাস্থ্য। uptime বা top-এর প্রথম লাইনে তিনটি সংখ্যা থাকে: load average ১, ৫ আর ১৫ মিনিটের। এটি CPU-র শতাংশ নয়। এটি বলে গড়ে কতটি task চলছে বা চলার অপেক্ষায় আছে।
ব্যাংকে ৪টি কাউন্টার। Load ৪ মানে গড়ে প্রতিটি কাউন্টারে একজন, কোনো লাইন নেই। Load ৮ মানে ৪ জন সেবা পাচ্ছেন, আরও ৪ জন দাঁড়িয়ে। আর একই load ৮ যদি ১৬ কাউন্টারের শাখায় হয়, তাহলে অর্ধেক কাউন্টার ফাঁকা। তাই load একা অর্থহীন; সবসময় core সংখ্যা দিয়ে ভাগ করুন।
Linux-এ একটি বিশেষ কথা আছে: এই গণনায় CPU-র অপেক্ষায় থাকা task-এর সাথে D state-এর task-ও পড়ে, মানে যারা সাধারণত disk I/O-র জন্য আটকে আছে। তাই load উঁচু আর CPU প্রায় ফাঁকা হলে সমস্যা CPU নয়, খুব সম্ভবত disk. Kernel প্রতি ৫ সেকেন্ডে একটি সূচকীয় গড় হিসাব করে: load = load × e + n × (1 − e), যেখানে এক মিনিটের জন্য e = exp(−5/60). নিচের simulator ৪ core-এর machine-এ এক মিনিটের spike দেখায়, আর তারপর একই load ৮.০ চার রকম machine-এ মাপে।
// Linux load average: every 5 s, load = load*e + n*(1-e), with
// e = exp(-5/60), exp(-5/300), exp(-5/900) for the 1, 5, 15 minute figures.
// n = tasks runnable or in uninterruptible sleep. Machine has 4 cores.
const cores = 4;
const decay = [60, 300, 900].map(w => Math.exp(-5 / w));
let load = [2, 2, 2]; // steady n = 2 before spike
const nAt = s => (s >= 60 && s < 120 ? 16 : 2); // 1-minute spike of 16 tasks
const verdict = l => l / cores < 0.7 ? 'ok' : l / cores <= 1 ? 'busy' : 'QUEUE';
console.log('min n load1 load5 load15 load1/core trend verdict');
for (let s = 0; s <= 600; s += 5) {
if (s % 60 === 0 && (s <= 240 || s === 600)) {
const [a, b, c] = load;
console.log(String(s / 60).padStart(3), String(nAt(s)).padStart(2),
a.toFixed(2).padStart(7), b.toFixed(2).padStart(6), c.toFixed(2).padStart(6),
(a / cores).toFixed(2).padStart(11),
(a > c + 0.5 ? 'rising' : a < c - 0.5 ? 'falling' : 'steady').padEnd(8), verdict(a));
}
const n = nAt(s);
load = load.map((l, i) => l * decay[i] + n * (1 - decay[i]));
}
console.log('\nsame load 8.0 on different machines');
for (const c of [2, 4, 8, 16]) {
const r = 8 / c;
console.log(String(c).padStart(3) + ' cores per core ' + r.toFixed(2).padStart(4) + ' ' +
(r > 1 ? (8 - c) + ' tasks waiting on average' : r === 1 ? 'exactly full' : (c - 8) + ' cores free on average'));
}আউটপুট:
min n load1 load5 load15 load1/core trend verdict
0 2 2.00 2.00 2.00 0.50 steady ok
1 16 2.00 2.00 2.00 0.50 steady ok
2 2 10.85 4.54 2.90 2.71 rising QUEUE
3 2 5.26 4.08 2.84 1.31 rising QUEUE
4 2 3.20 3.70 2.79 0.80 steady busy
10 2 2.00 2.51 2.53 0.50 falling ok
same load 8.0 on different machines
2 cores per core 4.00 6 tasks waiting on average
4 cores per core 2.00 4 tasks waiting on average
8 cores per core 1.00 exactly full
16 cores per core 0.50 8 cores free on average
মিনিট ২-এ spike-এর আসল মান ১৬, কিন্তু load1 মাত্র ১০.৮৫: 2 + 14 × (1 − e−1) = 10.85. গড় পিছিয়ে থাকে। তাই তিনটি সংখ্যার ঢাল পড়ুন: load1 > load15 মানে চাপ বাড়ছে, উল্টো হলে কমছে। মিনিট ১০-এ load1 স্বাভাবিক, কিন্তু load15 তখনো ২.৫৩, অর্থাৎ ঘটনার ছাপ রয়ে গেছে। নিচের অংশ ব্যাংকের উদাহরণটিই সংখ্যায়: load ৮.০ দুই core-এ ভয়ংকর, ১৬ core-এ আরামদায়ক।
Memory: free কম মানেই বিপদ নয়
Linux ফাঁকা RAM ফেলে রাখে না; disk-এর data রেখে দেয় page cache-এ। দরকার হলে এই জায়গা ছেড়ে দেয়। তাই দেখার সংখ্যা available, free নয়। আসল চাপ শুরু হয় যখন kernel-কে কষ্ট করে memory ফেরাতে হয়: swap-এ ঘন ঘন লেখা-পড়া, ধীর হয়ে যাওয়া। এই memory pressure সরাসরি মাপে PSI (/proc/pressure/memory, Linux 4.20 থেকে)। আরও তত্ত্ব আছে Linux-এ মেমরি পর্বে।
শেষ পর্যন্ত জায়গা না মিললে OOM killer নামে। Linux সাধারণত চাওয়া memory-র প্রতিশ্রুতি আগে দিয়ে দেয়, এই overcommit-এর দাম এখানেই শোধ হয়। Kernel একটি process বেছে SIGKILL পাঠায়, সাধারণত যার oom_score বেশি, মানে সাধারণত যে বেশি memory ধরে আছে। OOMScoreAdjust= দিয়ে এই পছন্দ প্রভাবিত করা যায়। দুটি ধরন আলাদা করুন: MemoryMax-এর কারণে হলে শুধু সেই cgroup-এর ভেতরে kill, journal-এ Memory cgroup out of memory; পুরো machine ফুরালে Out of memory: Killed process, আর শিকার যে কেউ হতে পারে। নিচের ঘটনাটি প্রথম ধরনের।
| Memory | |
| Active | |
| আপনার কাজ |
Memory: 186.4M (max: 512.0M)
Memory: 498.0M (max: 512.0M) # kernel page cache ছেড়ে দিচ্ছে, অ্যাপ ধীর হচ্ছে
limit : 512 MiB = 524288 kB
used : anon-rss 519844 kB + file-rss 1204 kB + kernel
reclaim failed, OOM killer in this cgroup
handler চলার সুযোগ নেই
চলমান request ভেঙে গেল
exit status 137, মানে 128 + 9
Restart=on-failure: 5 সেকেন্ড পরে আবার
$ systemctl status bazar-api Active: activating (auto-restart) (Result: oom-kill) Process: 2417 ExecStart=... (code=killed, signal=KILL)
$ journalctl -k -g "out of memory" --since "16:30"
kernel: Memory cgroup out of memory: Killed
process 2417 (node) total-vm:1834212kB,
anon-rss:519844kB, file-rss:1204kB, UID:998
$ journalctl -u bazar-api --since "16:30"
systemd[1]: bazar-api.service: A process of this
unit has been killed by the OOM killer.
systemd[1]: bazar-api.service: Failed with result
'oom-kill'.
ধীরে ধীরে সিঁড়ির মতো বাড়ে, নামে না → leak: কোড ঠিক
ট্রাফিকের সাথে বাড়ে, পরে নামে → সীমা ছোট: load test
করে MemoryMax বাড়ান
- দুপুর ২টা। Service চালু, memory ১৮৬ MiB, সীমা ৫১২ MiB. কোনো সমস্যা নেই। কিন্তু একটি ছোট leak চুপচাপ জমছে।
- ২ ঘণ্টা ৩৬ মিনিট পরে। Memory ৪৯৮ MiB. Kernel এই cgroup-এর page cache ফেরত নিয়ে জায়গা করছে, ফলে অ্যাপ ধীর হচ্ছে। এখনো কেউ alert পাননি।
- সীমায় পৌঁছাল। ৫১২ MiB = ৫,২৪,২৮৮ kB. Anon memory একাই প্রায় ৫,১৯,৮৪৪ kB, যা ফেরত নেওয়ার মতো নয়। Reclaim ব্যর্থ, তাই এই cgroup-এর ভেতরেই OOM killer নামল। পাশের service-গুলোর গায়ে হাত পড়েনি।
- SIGKILL. এখানে handler নেই, graceful shutdown নেই। চলমান request ভেঙে গেল। Status 137.
Restart=on-failure৫ সেকেন্ড পরের জন্য নতুন start ঠিক করল, আর alert গেল আপনার কাছে। - প্রথম প্রশ্ন: কীভাবে মরল?
systemctl status-এResult: oom-killআরsignal=KILL. কেউ হাতেkillকরেনি, অ্যাপ নিজে থেকেও থামেনি। - দ্বিতীয় প্রশ্ন: কোন ধরনের OOM? Service এর মধ্যে আবার চলছে। Kernel-এর log বলে
Memory cgroup out of memory, তাই সীমা ছুঁয়েছে, machine ফুরায়নি।anon-rssমিলছে আগের হিসাবের সাথে, আর systemd-র লাইন একই ঘটনা নিশ্চিত করছে। - সিদ্ধান্ত। সুস্থ হওয়াটা ভুল ভরসা দেয়, কারণ leak থাকলে ঘটনাটি আবার হবে। Memory graph দেখুন: না নামা সিঁড়ি মানে leak, তাই কোড ঠিক করুন; ট্রাফিকের সাথে ওঠানামা মানে সীমা ছোট, তাই মেপে বাড়ান। অন্ধভাবে সীমা তুলে দিলে পরের বার পুরো machine ডুবতে পারে।
৮ · top, free, vmstat, iostat, df, du আর USE method
সমস্যার সময় অনুমান নয়, ক্রম দরকার। ২০১২ সালে Brendan Gregg ACM Queue-তে যে পদ্ধতি লেখেন, তার নাম USE method: প্রতিটি resource-এর জন্য তিনটি প্রশ্ন। Utilization: কত সময় ব্যস্ত? Saturation: কত কাজ সারিতে? Errors: ভুল হচ্ছে কি? Utilization একা ঠকায়, কারণ ৯০% ব্যস্ত কাউন্টারে লাইন নাও থাকতে পারে; লাইন দেখায় saturation. Metric-এর দিক থেকে USE আবার আসবে পর্ব ৬৩-তে, আর গভীর performance তদন্ত আছে পারফরম্যান্স আর observability পর্বে।
| Resource | Utilization | Saturation | Errors |
|---|---|---|---|
| CPU | top: us + sy | load ÷ core, vmstat-এর r | journal-এ MCE ধরনের বার্তা |
| Memory | free: available | vmstat-এর si, so; PSI | OOM kill, journalctl -k |
| Disk | iostat -xz: %util | aqu-sz, await, vmstat-এর b | journalctl -k-এ I/O error |
| জায়গা | df -h, df -i | ৯০% পেরোনো | No space left on device |
| Network | পর্ব ১৩-র টুল | drop, retransmit | interface error |
নিচের সবগুলো নমুনা আউটপুট, শেখার জন্য বানানো এবং version-ভেদে column আলাদা হতে পারে। একই ঘটনার ছবি: ২ vCPU, ৮ GB-র একটি server ধীর হয়ে গেছে।
$ top -bn1 | head -3 # sample
top - 14:32:07 up 12 days, 3:11, 1 user, load average: 6.42, 5.10, 3.87
Tasks: 142 total, 3 running, 139 sleeping, 0 stopped, 0 zombie
%Cpu(s): 38.2 us, 7.1 sy, 0.0 ni, 12.4 id, 41.0 wa, 0.0 hi, 1.3 si, 0.0 st
$ free -m # sample
total used free shared buff/cache available
Mem: 7820 7050 180 64 590 420
Swap: 2047 1460 587
$ vmstat 1 3 # sample; line 1 is average since boot
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 1 1458000 188000 12000 580000 3 5 40 60 300 600 12 3 83 2 0
2 6 1460200 181000 12000 578000 820 640 9120 1530 2210 4310 38 7 12 41 0
3 5 1461100 180000 12000 577000 790 710 8840 1660 2180 4250 37 8 13 40 0
$ iostat -xz 1 # sample; some columns removed
Device r/s w/s r_await w_await aqu-sz %util
vda 412.0 88.0 18.40 41.20 9.80 98.7
$ df -h # sample
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 37G 1.1G 97% /
/dev/vdb1 100G 61G 34G 65% /data
$ du -xsh /var/log/* | sort -h | tail -2 # sample
1.2G /var/log/journal
19G /var/log/bazar-api
| টুল | কীভাবে পড়বেন | এই নমুনায় |
|---|---|---|
top | us আপনার কোড, sy kernel, id ফাঁকা, wa disk-এর অপেক্ষা, st hypervisor নিয়ে গেছে। Shared VM-এ st বেশি হলে পাশের কারও চাপ (পর্ব ১৫) | wa ৪১%: CPU-র হাতে কাজ নেই, task-গুলো disk-এর জন্য আটকে আছে |
free | available দেখুন; free আর buff/cache মিলিয়ে ভুল সিদ্ধান্ত নেবেন না | ৪২০ MiB, মাত্র ৫.৪% |
vmstat | প্রথম লাইন boot থেকে গড়, বাদ দিন। r সারিতে task, b আটকে থাকা task, si/so swap-এ আসা-যাওয়া | so ৬৪০: এখনই swap চলছে |
iostat | await প্রতি I/O-তে সময়, aqu-sz গড় সারি। %util SSD ও cloud disk-এ ঠকাতে পারে, কারণ এরা একসাথে অনেক কাজ করে | সারি ৯.৮, %util ৯৮.৭ |
df | Use% সাধারণ ব্যবহারকারীর জন্য জায়গার হিসাব; root-এর জন্য জায়গা সংরক্ষিত থাকে, তাই Size ≠ Used + Avail. df -i দেখায় inode | / ৯৭% |
du | কোন ফোল্ডার খাচ্ছে। df ভরা অথচ du কম হলে মুছে ফেলা ফাইল কোনো process এখনো ধরে আছে; সেই service restart করলে জায়গা ফেরে | app log ১৯ GB |
এবার এই সব নমুনার মূল অংশ একটি heredoc-এ রেখে ছোট একটি triage script চালাই। এটি সত্যিকারের সিস্টেমের কোনো কিছু পড়ে না, শুধু নিজের ভেতরের লেখা।
cat > snapshot.txt <<'EOF'
top - 14:32:07 up 12 days, 3:11, 1 user, load average: 6.42, 5.10, 3.87
%Cpu(s): 38.2 us, 7.1 sy, 0.0 ni, 12.4 id, 41.0 wa, 0.0 hi, 1.3 si, 0.0 st
total used free shared buff/cache available
Mem: 7820 7050 180 64 590 420
Swap: 2047 1460 587
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 37G 1.1G 97% /
/dev/vdb1 100G 61G 34G 65% /data
tmpfs 3.9G 0 3.9G 0% /dev/shm
EOF
cores=2; warns=0
alert() { echo "WARN $1"; warns=$((warns + 1)); }
over() { awk -v a="$1" -v b="$2" 'BEGIN { exit !(a > b) }'; }
load1=$(sed -n 's/.*load average: \([0-9.]*\),.*/\1/p' snapshot.txt)
per=$(awk -v l="$load1" -v c="$cores" 'BEGIN { printf "%.2f", l / c }')
echo "load1=$load1 cores=$cores per-core=$per"
over "$per" 1 && alert "tasks are queueing"
wa=$(awk -F'[ ,]+' '/^%Cpu/ { print $10 }' snapshot.txt)
echo "iowait=$wa%"
over "$wa" 20 && alert "much time lost waiting for disk"
read -r avail pct < <(awk '/^Mem:/ { printf "%d %.1f\n", $7, 100 * $7 / $2 }' snapshot.txt)
echo "available=$avail MiB ($pct%)"
over 10 "$pct" && alert "less than 10% memory available"
read -r used swp < <(awk '/^Swap:/ { print $3, int(100 * $3 / $2) }' snapshot.txt)
echo "swap used=$used MiB ($swp%)"
over "$swp" 50 && alert "more than half of swap used"
while read -r mnt use; do alert "disk $mnt at $use%"; done < <(
awk '$5 ~ /^[0-9]+%$/ && $5 + 0 >= 90 { print $6, $5 + 0 }' snapshot.txt)
echo "summary: $warns warnings"আউটপুট:
load1=6.42 cores=2 per-core=3.21
WARN tasks are queueing
iowait=41.0%
WARN much time lost waiting for disk
available=420 MiB (5.4%)
WARN less than 10% memory available
swap used=1460 MiB (71%)
WARN more than half of swap used
WARN disk / at 97%
summary: 5 warnings
পাঁচটি সতর্কতা, কিন্তু পাঁচটি আলাদা সমস্যা নয়। গল্পটি এক সুতোয় বাঁধুন: memory প্রায় শেষ, তাই kernel swap করছে; swap হলো disk-এ যাওয়া, তাই wa ৪১% আর task-গুলো D state-এ; সেই task-গুলোই প্রতি core-এ load ৩.২১-এ তুলেছে। CPU আসল সমস্যা নয়, তাই core বাড়ালে তেমন লাভ নেই। আগে memory-র মালিক খুঁজুন। Disk ৯৭% আলাদা, স্বাধীন আগুন: du বলে দোষী app log, তাই log rotation লাগবে। Script শুধু সতর্ক করে; সিদ্ধান্ত মানুষের। এই সীমাগুলো উদাহরণ মাত্র, প্রতিটি service-এর স্বাভাবিক মান নিজের মতো মেপে নিতে হয়।
আরও গভীরে: Linux-এর load-এ D state ঢোকে ১৯৯৩ সালের একটি পরিবর্তনে, আর এর ইতিহাস Brendan Gregg ২০১৭ সালের “Linux Load Averages: Solving the Mystery” লেখায় খুঁড়ে বের করেন। তাঁর ২০১৫ সালের “Linux Performance Analysis in 60,000 Milliseconds” লেখার প্রথম-মিনিটের কমান্ড তালিকা অনেক দলের runbook-এর বীজ। systemd-র v254 থেকে RestartSteps= আর RestartMaxDelaySec= দিয়ে restart-এর অপেক্ষা ধাপে ধাপে বাড়ানো যায়, যা exponential backoff-এর ধারণা। আর systemd-oomd PSI দেখে kernel-এর OOM-এর আগেই ব্যবস্থা নিতে পারে, distribution-ভেদে চালু থাকে বা থাকে না।
পরীক্ষা ও ইন্টারভিউতে:
systemctl startআরenable-এর পার্থক্য? Start এখন চালায়; enable boot-এ চলার symlink বানায়।- Exit status 137 মানে? 128 + 9, SIGKILL; প্রায়ই OOM kill বা stop-এর সময়সীমা শেষ।
- ৪ core, load 8 — ভালো না খারাপ? প্রতি core-এ ২, সারি জমছে; তবে Linux-এ D state-ও গোনে, তাই
waদেখে CPU না disk ঠিক করুন। freeপ্রায় শূন্য, সমস্যা? একা নয়।availableআর swap activity দেখুন; page cache ফেরত পাওয়া যায়।- Disk ভরা,
du-তে কিছু নেই? মুছে ফেলা কিন্তু খোলা ফাইল;lsof +L1দিয়ে খুঁজে সেই process restart করুন।
৯ · AI-এর যুগে service চালানো
AI কয়েক সেকেন্ডে unit file লিখে দেয়, আর ফাইলটি দেখতে ঠিকঠাকই লাগে। কিন্তু ফাইলটি production-এ root হিসেবে চলবে। তাই এখানে “চলছে” যথেষ্ট প্রমাণ নয়। AI সাধারণত যে ভুলগুলো করে:
| AI যা দেয় | কেন ক্ষতিকর | যাচাই |
|---|---|---|
User=root বা User-ই নেই | অ্যাপ দখল হলে পুরো server | systemd-analyze security, least privilege |
Restart=always + RestartSec=0 | অদৃশ্য crash loop, log ভরে, CPU খায় | উপরের সূত্রে হিসাব করুন |
| Unit file-এ password | secret ফাঁস, git-এ ওঠার ঝুঁকি | কড়া অনুমতির আলাদা ফাইল (পর্ব ৩৩) |
বানানো setting, যেমন MaxMemory= | systemd অচেনা setting উপেক্ষা করে, সীমা বসেই না | systemd-analyze verify, man systemd.resource-control |
“Disk ভরা? rm -rf /var/log/*” | তদন্তের প্রমাণ শেষ, খোলা ফাইলে জায়গাও ফেরে না | আগে du, তারপর rotation বা --vacuum-time |
“Service আটকে? kill -9” | graceful shutdown বাদ, data ভাঙার ঝুঁকি | আগে systemctl stop আর journal |
“Memory কম? drop_caches” | কারণ ঠিক হয় না, cache হারিয়ে disk আরও ব্যস্ত | USE ধরে memory-র মালিক খোঁজা |
AI-কে শুধু “একটি service file লিখে দিন” না বলে পরিবেশ, সীমা আর যাচাই একসাথে চান। Log পেস্ট করার আগে hostname, IP, token মুছে নিন।
AI-এর দেওয়া unit বা কমান্ড হাতে পেলে
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।
প্র ০১Shell script দিয়েই তো দশকের পর দশক service চলছিল। তাহলে systemd নিয়ে এত বিতর্ক কেন, আর এটি কেন জিতল?
SysV init-এর দুনিয়ায় প্রতিটি service-এর একটি shell script থাকত। ক্রম ঠিক হতো ফাইলের নামের সংখ্যায়, আর সব একে একে চলত, তাই boot ছিল ধীর। প্রতিটি script নিজেই PID ফাইল লিখত, আর process সন্তান তৈরি করে পালালে তাকে আর খুঁজে পাওয়া যেত না। Restart বা resource সীমা নিজে থেকে ছিল না।
২০১০ সালে systemd তিনটি বড় চিন্তা আনে। প্রথমত, script-এর বদলে ঘোষণামূলক ফাইল: কী চাই লিখুন, কীভাবে তা systemd জানে। দ্বিতীয়ত, cgroup দিয়ে process ট্র্যাক করা, তাই fork করে পালানো সম্ভব নয়। তৃতীয়ত, নির্ভরতা ধরে একসাথে অনেক service চালানো।
বিতর্ক হয় পরিসর নিয়ে। সমালোচকদের মত ছিল, systemd শুধু init নয়, logging, login, network, DNS-এর দিকেও ছড়িয়ে গেছে, যা Unix-এর “একটি কাজ ভালোভাবে” দর্শনের উল্টো, আর PID 1 বড় হলে ঝুঁকিও বড়। ২০১৪ সালে Debian-এর technical committee-তে এ নিয়ে তিক্ত তর্ক ও ভোট হয়, এবং systemd ডিফল্ট হয়; কেউ কেউ এর জেরে Devuan নামে আলাদা distribution শুরু করেন। সমর্থকদের যুক্তি ছিল, আলাদা আলাদা অংশ একসাথে ভালোভাবে জুড়ে না থাকলে distribution-গুলোকে সেই আঠা নিজেরা লিখতে হয়।
এটি জিতেছে মূলত ব্যবহারিক কারণে: distribution-গুলোর জন্য একই unit ফাইল সব জায়গায় চলে, আর operator-রা একই কমান্ড পান। তবে এটিকে নিখুঁত বলা ঠিক নয়। Container-এ অনেকেই systemd ছাড়াই চলেন, আর Alpine-এর মতো distribution অন্য পথ বেছে নিয়েছে।
মূল উপলব্ধি: প্রকৌশলের বড় লড়াইগুলো প্রায়ই প্রযুক্তির নয়, মূল্যবোধের: ছোট স্বাধীন অংশ, না একসাথে জোড়া ব্যবস্থা। উভয় পক্ষের যুক্তি বুঝলে আপনি শুধু কমান্ড নয়, নকশার দাম বোঝেন।
প্র ০২৪ core-এর server-এ load ২০, অথচ top-এ CPU ৭০% ফাঁকা। এটি কীভাবে সম্ভব, আর Linux এমন “অদ্ভুত” গণনা করে কেন?
ব্যাখ্যাটি Linux-এর সংজ্ঞায়। অনেক Unix-এ load শুধু CPU-র সারি গোনে। Linux গোনে চলার যোগ্য task আর uninterruptible sleep-এ, মানে D state-এ থাকা task, দুটোই। তাই ২০টি task যদি একটি ধীর disk বা আটকে যাওয়া network storage-এর উত্তরের অপেক্ষায় থাকে, load ২০ হবে, অথচ CPU-তে তাদের কোনো কাজই নেই। CPU তখন ফাঁকা বা wa দেখায়।
কেন এমন? Brendan Gregg ২০১৭ সালে পুরোনো mailing list খুঁড়ে ১৯৯৩ সালের একটি patch খুঁজে পান, যার বার্তায় বলা ছিল: শুধু CPU গুনলে machine swap করে ধীর হওয়ার সময় load কমে যেতে দেখা যায়, যা বিভ্রান্তিকর। Swap-এ আটকে থাকা task তো কাজের চাহিদাই, শুধু CPU চায় না। তাই সংখ্যাটি হলো “system-এর চাহিদা”, শুধু “CPU-র চাহিদা” নয়।
এর একটি পরোক্ষ ফল আছে। Kernel-এর কিছু lock-এর অপেক্ষাও D state-এ পড়ে, তাই disk নীরব থাকলেও load উঠতে পারে। Network filesystem আটকে গেলে এমন task signal-এও সাড়া দেয় না, এমনকি kill -9-এও সঙ্গে সঙ্গে যায় না, কারণ signal তখনই কাজ করে যখন task kernel থেকে ফেরে।
তদন্তের ক্রম তাই এমন: আগে wa আর vmstat-এর b দেখুন, তারপর iostat -xz-এ সারি, আর দরকারে কোন task D state-এ তা খুঁজুন। আধুনিক সিস্টেমে PSI আলাদা করে CPU, memory আর I/O-র চাপ জানায়, যা একটি মিশ্র সংখ্যার চেয়ে অনেক পরিষ্কার। তাই auto-scaling-এর সিদ্ধান্ত load দিয়ে নিলে সাবধান: disk সমস্যায় নতুন CPU কেনা অর্থহীন।
মূল উপলব্ধি: প্রতিটি metric-এর একটি সংজ্ঞা আর একটি ইতিহাস আছে। সংখ্যাটি কী গোনে তা না জেনে সিদ্ধান্ত নিলে ভুল জায়গায় টাকা ঢালবেন।
প্র ০৩একটি process-কে মেরে ফেলাই কি kernel-এর সেরা সমাধান? OOM killer বন্ধ করে দিলে কী হয়?
OOM killer জন্মেছে overcommit থেকে। fork() করলে সন্তান বাবার memory “পায়”, কিন্তু আসল কপি হয় কেবল লিখলে। অ্যাপ বড় জায়গা চায়, ব্যবহার করে সামান্য। সব প্রতিশ্রুতি RAM-এ মেলাতে গেলে সিস্টেম অনেক অপচয় করত। তাই Linux ডিফল্টে বিমান কোম্পানির মতো কিছুটা বেশি টিকিট বিক্রি করে। সবাই একসাথে এলে কাউকে নামাতে হয়।
২০০৪ সালের দিকে kernel আলোচনায় Andries Brouwer-এর একটি বিখ্যাত উপমা ছিল: বিমান কোম্পানি জ্বালানি বাঁচাতে কম তেল নিল, আর তেল ফুরালে যাত্রী বেছে জানালা দিয়ে ফেলে দিতে লাগল। কৌতুকটির মর্ম হলো, kernel ঠিক কাকে মারবে তা নিখুঁতভাবে জানা অসম্ভব।
বিকল্প আছে। vm.overcommit_memory=2 দিলে kernel হিসাব রেখে অতিরিক্ত চাওয়া অস্বীকার করে; তখন malloc ব্যর্থ হয় এবং বড় fork()-ও ব্যর্থ হতে পারে। কিছু database দল এটি বিবেচনা করে, কিন্তু বেশিরভাগ অ্যাপ malloc-এর ব্যর্থতা ভালোভাবে সামলায় না, তাই crash তো থামেই না, আসে আরও অদ্ভুত জায়গায়। oom_score_adj-কে −1000 দিলে একটি process সুরক্ষিত থাকে, কিন্তু সব জরুরি process এমন করলে শিকার হবে অন্য কেউ, অথবা machine জমে যাবে।
বাস্তব সমস্যা হলো kernel-এর OOM অনেক দেরিতে আসে: তার আগে machine মিনিটের পর মিনিট swap আর reclaim-এ প্রায় অচল হতে পারে। এজন্য Facebook oomd বানায় ও প্রকাশ করে, যা PSI দেখে আগেই ব্যবস্থা নেয়; তার ধারণা থেকে এসেছে systemd-oomd. বড় সিস্টেমে আসল প্রতিরক্ষা হলো প্রতিটি service-এ cgroup সীমা, যাতে ক্ষতি এক ঘরে থাকে, আর memory বাড়ার trend-এ আগেই alert.
মূল উপলব্ধি: OOM kill কোনো বাগ নয়, ব্যবস্থা ডুবে যাওয়ার আগের শেষ উপায়। লক্ষ্য তাকে বন্ধ করা নয়, এমনভাবে নকশা করা যাতে তাকে কম ডাকতে হয় আর ডাকলেও ক্ষতি ছোট থাকে।
প্র ০৪Restart=always দিলেই কি reliability বাড়ে? “Restart করে দিন” সংস্কৃতির ঝুঁকি কী?
Restart সত্যিই শক্তিশালী হাতিয়ার। Telecom সিস্টেমের জন্য তৈরি Erlang-এর জগতে Joe Armstrong-এর দল “let it crash” দর্শন জনপ্রিয় করেন: ভুল পরিস্থিতি সব আগে থেকে ধরার চেষ্টার বদলে process মরতে দিন, আর একটি supervisor পরিষ্কার অবস্থায় আবার চালাক। অনেক বাগ বিরল সময়ের কারণে ঘটে, তাই নতুন শুরুতে এড়িয়ে যায়।
লক্ষণীয় হলো Erlang/OTP-র supervisor-এও একটি restart intensity আছে: নির্দিষ্ট সময়ে বেশি restart হলে supervisor নিজে হাল ছেড়ে উপরে জানায়। এটি systemd-র StartLimitBurst-এর হুবহু ধারণা। Kubernetes-ও CrashLoopBackOff-এ অপেক্ষা ক্রমশ বাড়ায়। সবার একই শিক্ষা: সীমাহীন restart ভালো নয়।
ঝুঁকি কয়েকটি। এক, লুকিয়ে যাওয়া: প্রতি ঘণ্টায় OOM হলে service দিব্যি “চলছে” দেখায়, অথচ প্রতিবার চলমান request হারায়, আর দল leak-টি জানতেই পারে না। দুই, ক্ষতি বাড়ানো: database ধীর হলে সবাই একসাথে restart করে, প্রত্যেকে নতুন connection খোলে, cache ঠান্ডা থাকে, আর চাপ আরও বাড়ে। এটি thundering herd-এর এক রূপ; প্রতিকার jitter আর backoff. তিন, data ভাঙা: অর্ধেক লেখা অবস্থায় বারবার মরলে state খারাপ হতে পারে। চার, log আর disk ভরে যাওয়া।
তাই ভালো অভ্যাস হলো restart-এর সংখ্যাকেই একটি metric বানানো। প্রতিটি অপ্রত্যাশিত restart একটি ছোট ঘটনা, যা journal-এ কারণসহ দেখা উচিত। একবার restart ঠিক আছে; সপ্তাহে একশোবার হলে সেটি একটি খোলা বাগ। Resilience pattern পর্বে এ ধরনের নকশা দেখা যাবে।
মূল উপলব্ধি: Restart হলো ব্যথানাশক, রোগের ওষুধ নয়। এটি সময় কেনে, কিন্তু সেই সময়ে কারণ খোঁজা আপনারই কাজ।
প্র ০৫সবাই যখন Kubernetes-এ যাচ্ছে, তখন systemd আর এসব টুল শেখার দরকার কী? Graceful shutdown-এর হিসাবই বা সেখানে কেমন?
Kubernetes server-কে উধাও করে না, শুধু আড়াল করে। প্রতিটি node একটি Linux machine, আর সেখানে kubelet ও container runtime সাধারণত systemd service হিসেবেই চলে। Node খারাপ হলে প্রথম কমান্ড প্রায়ই journalctl -u kubelet. Kubernetes-এর resource limit নিচে সেই একই cgroup, আর OOMKilled মানে সেই একই kernel OOM, exit code 137. শেখা ধারণাগুলো নাম বদলে ফিরে আসে: Restart= হয় restartPolicy, StartLimit হয় CrashLoopBackOff, TimeoutStopSec হয় terminationGracePeriodSeconds, লেখার সময়ে যার ডিফল্ট ৩০ সেকেন্ড।
Graceful shutdown-এ একটি সূক্ষ্মতা আছে, যা অনেকে ধরেন না। ধরুন একটি API load balancer-এর পেছনে আছে। SIGTERM পেলেই সে বন্ধ করলে load balancer কয়েক সেকেন্ড ধরে তখনো নতুন request পাঠায়, কারণ খবরটি ছড়াতে সময় লাগে। ফল: deployment-এর সময় ছোট ছোট 502. সঠিক ক্রম হলো: আগে load balancer থেকে নিজেকে সরানো, মানে health check ব্যর্থ বলা বা deregister, কিছুক্ষণ অপেক্ষা, তারপর হাতের request শেষ, তারপর বের হওয়া। Connection draining নামে এটি পর্ব ১৮-তে আসবে।
আর সময়সীমা হিসাব করে রাখতে হয়। সবচেয়ে ধীর request ২০ সেকেন্ড নিলে TimeoutStopSec বা grace period তার চেয়ে বেশি হতেই হবে। না হলে SIGKILL ঠিক সেই কাজটি নষ্ট করবে যা বাঁচানোর চেষ্টা করছিলেন। Deployment ও release পর্বে এর নকশার দিকটি পাবেন।
আরও একটি বাস্তব কথা: সব কিছু Kubernetes-এ চলে না। ছোট প্রতিষ্ঠানের একটি VM, database server, bastion, monitoring agent, build runner — এগুলোর অনেকই সরাসরি systemd-তে চলে। আর আপনি যে আলোচনাই করুন, ইন্টারভিউ আর on-call-এ এই মৌলিক টুলগুলো দিয়েই সত্য যাচাই হয়।
মূল উপলব্ধি: বিমূর্ততার প্রতিটি স্তর নিচের স্তরকে আড়াল করে, মুছে দেয় না। যখন ওপরের স্তর ভেঙে পড়ে, যিনি নিচের স্তর বোঝেন তিনিই ঘর ঠিক করতে পারেন।
অনুশীলন
নিজের কম্পিউটারে Linux না থাকলেও সবগুলো কাগজে করা যায়। Cloud-এর server-এ পরীক্ষা করলে খরচ হতে পারে; শেষে server মুছে ফেলুন।
-
হিসাব করুন: (ক) অ্যাপ start-এর ১ সেকেন্ড পরে ভেঙে পড়ে।
RestartSec=10,StartLimitIntervalSec=60,StartLimitBurst=5. কখন থামবে? (খ)RestartSec=12করলে কী হবে? (গ) ৮ vCPU-র VM-এ load1 = ১২.০ হলে প্রতি core-এ কত? (ঘ)CPUQuota=250%মানে পুরো VM-এর কত শতাংশ, আরcpu.max-এ কী লেখা হবে?(ক) চক্র = ১ + ১০ = ১১ সেকেন্ড। Start হয় ০, ১১, ২২, ৩৩, ৪৪ সেকেন্ডে, মোট ৫টি। ষষ্ঠ চেষ্টা ৫৫ সেকেন্ডে, যা ৬০-এর ভেতরে, তাই নিষিদ্ধ; unit failed. সূত্র: ৫ × ১১ = ৫৫ < ৬০.
(খ) চক্র ১৩, তাই ৫ × ১৩ = ৬৫, যা ৬০-এর চেয়ে বড়। Start হয় ০, ১৩, ২৬, ৩৯, ৫২ সেকেন্ডে। ষষ্ঠ চেষ্টা t = ৬৫-এ আসে, তখন window শেষ, গণনা নতুন করে শুরু। Crash loop কখনো থামবে না। দুই সেকেন্ডের পার্থক্যে আচরণ উল্টে গেল; তাই window যথেষ্ট বড় রাখুন, যেমন ৩০০।
(গ) ১২ ÷ ৮ = ১.৫. গড়ে ৪টি task অপেক্ষায় (ধরে নিচ্ছি সব CPU চায়;
waদেখে নিশ্চিত হোন)।(ঘ) ২.৫ core ÷ ৮ = ৩১.২৫%.
cpu.max-এ250000 100000: প্রতি ১,০০,০০০ মাইক্রোসেকেন্ডে ২,৫০,০০০ মাইক্রোসেকেন্ড। -
ফলাফল অনুমান করুন:
bazar-apiথেমে আছে এবং disabled. পরপর চলল: (১)systemctl enable bazar-api(২) unit file-এRestartSec৫ থেকে ৩০ করা (৩)systemctl start bazar-api(৪)systemctl daemon-reload(৫)systemctl stop bazar-api(৬) server reboot. প্রতিটি ধাপের পর চলছে কি না, boot-এ চলবে কি না, আর শেষে কোনRestartSecকার্যকর?(১) থেমে আছে, enabled:
enableএখন চালায় না। (২) কিছুই বদলায়নি, systemd পুরোনো ৫-ই মনে রেখেছে। (৩) চলছে, কিন্তু ৫ সেকেন্ডের নিয়মে; নতুন systemd versionstatus-এ ফাইল বদলের সতর্কবার্তাও দেখাতে পারে। (৪) systemd ৩০ জেনে গেল, process-এর গায়ে হাত পড়েনি, এখনো চলছে। (৫) থেমে গেল, তবে enabled রইল:stopboot-এর সিদ্ধান্ত বদলায় না। (৬) Boot-এ নিজে থেকে চলবে, কারণ enabled, আরRestartSec=30কার্যকর। -
সমালোচনা করুন: একজন AI থেকে এই unit নিলেন। অন্তত পাঁচটি সমস্যা বের করে ঠিক করুন:
[Service]-এUser=root,Environment=DB_PASS=example-secret,ExecStart=nohup node /opt/app/server.js &,Restart=always,RestartSec=0; আর কোনো[Install]section নেই।- root: নিজস্ব কম ক্ষমতার user বানিয়ে
User=app. - Secret: ফাইলটি প্রায়ই সবার পড়ার যোগ্য, আর
systemctl show-এও দেখা যায়।0600অনুমতিরEnvironmentFile-এ সরান, এবং এই মানটি আগে ফাঁস হয়ে থাকলে বদলান। - ExecStart:
nohupআর&এখানে অর্থহীন; এটি shell নয়। পুরো path দিন:/usr/bin/node /opt/app/server.js. - Restart:
on-failureআরRestartSec=5; সাথেStartLimitIntervalSec=300,StartLimitBurst=5, যা ৫ × (uptime + ৫) < ৩০০ রাখে, যদি crash ৫৫ সেকেন্ডের কমে হয়। - [Install] নেই:
WantedBy=multi-user.targetছাড়াenableকাজ করে না, reboot-এ service ফিরবে না। - বাড়তি:
MemoryMax,NoNewPrivileges,ProtectSystem=strict,PrivateTmpযোগ করুন;AfterআরWantsদিয়ে network-এর অপেক্ষা লিখুন।
- root: নিজস্ব কম ক্ষমতার user বানিয়ে
-
Triage: একটি কাল্পনিক ৪ core-এর server ধীর। নমুনা মান: load ৯.১, ৭.৪, ৩.২;
top-এus৮,sy৪,id২৬,wa৬২;free-এ available ৬২%;vmstat-এr১,b৯,si০,so০;iostat-এaqu-sz৩২,r_await৪৮০ ms;df-এ ৪১%. USE ধরে বলুন সমস্যা কোথায়, কোথায় নয়, আর পরের দুটি কমান্ড কী হবে।CPU:
us+syমাত্র ১২%,r১, তাই সমস্যা নয়, যদিও load ÷ core = ২.২৮. Memory: available ৬২%, swap activity শূন্য, তাই নয়। Disk জায়গা: ৪১%, নয়। Disk I/O:wa৬২,b৯, সারি ৩২, await ৪৮০ ms: saturation স্পষ্ট। Load বাড়ছে, কারণ load1 > load15.পরের ধাপ:
journalctl -k -p errদিয়ে disk error খোঁজা, আরiotopবাpidstat -d 1দিয়ে কে পড়ছে তা বের করা। হতে পারে index ছাড়া একটি ভারী query, backup job, বা cloud disk-এর IOPS সীমা। Core বাড়ালে কোনো লাভ হবে না।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি নতুন systemd service চালু করার ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
/etc/systemd/system/-এ unit file লেখাsystemd-analyze verifyদিয়ে ফাইল পরীক্ষাsystemctl daemon-reloadদিয়ে systemd-কে ফাইল পড়ানোsystemctl enable --nowদিয়ে boot-এ ও এখনই চালানোsystemctl statusআরjournalctl -uদিয়ে যাচাই
systemctl stop দিলে একটি সাধারণ service-এর ক্ষেত্রে ডিফল্টে কী ঘটে?
- সরাসরি SIGKILL পাঠানো হয়
- প্রথমে SIGTERM, সময়সীমা পেরোলে SIGKILL
- SIGHUP পাঠিয়ে অনন্তকাল অপেক্ষা করা হয়
- Unit file মুছে দেওয়া হয়
একটি service বর্তমানে থেমে আছে এবং disabled. systemctl enable bazar-api চালানোর পর অবস্থা কী?
- চলছে, এবং boot-এ চলবে
- থেমে আছে, এবং boot-এ চলবে না
- থেমে আছে, কিন্তু boot-এ চলবে
- failed অবস্থায় চলে যায়
একটি অ্যাপ start-এর ১ সেকেন্ড পরে সবসময় ভেঙে পড়ে। Unit-এ Restart=on-failure, RestartSec=5, StartLimitIntervalSec=10, StartLimitBurst=5. কী ঘটবে?
- ৩০ সেকেন্ডে unit failed হয়ে থামবে
- একবার ভেঙেই থেমে যাবে
- কিছুক্ষণ পরে নিজে থেকে সুস্থ হবে
- সীমা কখনো ছোঁবে না, crash loop চলতেই থাকবে
৪ core-এর Linux server-এ load average ৮.০, কিন্তু top-এ us ৫% আর wa ৭০%. সবচেয়ে সম্ভাব্য ব্যাখ্যা কোনটি?
- Task-গুলো I/O-র অপেক্ষায় আটকে আছে; load-এ তারাও গোনা হয়
- CPU কম, core বাড়ানো দরকার
- Load ৮.০ মানে CPU ৮০০% ব্যবহার হচ্ছে
- Server ফাঁকা, এই সংখ্যা উপেক্ষা করা যায়
৪ core-এর machine-এ একটি service-এ CPUQuota=50% বসানো হলো। Service সর্বোচ্চ কতটা CPU সময় পাবে?
- দুটি core-এর সমান সময়
- একটি core-এর অর্ধেক সময়
- একটি নির্দিষ্ট core-এর পুরোটা
- অন্য service না চাইলে সীমা ছাড়াই যত খুশি
journal-এ Memory cgroup out of memory: Killed process আর unit-এর Result: oom-kill দেখা গেল। এ থেকে কী বোঝা যায়?
- Disk-এর জায়গা ফুরিয়ে গেছে
- একজন operator হাতে kill -9 দিয়েছেন
- Service তার cgroup-এর memory সীমায় পৌঁছেছিল, kernel তার ভেতরের process মেরেছে
- Service SIGTERM পেয়ে গুছিয়ে বের হয়েছে
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- SIGTERM ধরে গুছিয়ে থামুন; SIGKILL ধরা যায় না, status 137.
- Service মানে manager-এর হাতে দেওয়া process: unit file হলো চুক্তি,
startএখন,enableboot-এ, ফাইল বদলালেdaemon-reload. - Crash loop থামে কেবল যখন burst × (uptime + RestartSec) < window; restart-এর সংখ্যাকেও alert করুন।
- cgroup ক্ষতি এক ঘরে রাখে:
CPUQuotaএক core-এর শতাংশ,MemoryMaxপেরোলে OOM kill; sandbox setting ক্ষতির পরিধি ছোট করে। - Load ÷ core,
available,wa, journal; অনুমান নয়, USE method ধরে এগোন।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ১২ · SSH আর দূরের server — key, config, tunnel আর bastionপরবর্তী পর্বদূরের server-এ নিরাপদে ঢোকা।
- ক্লাউড কম্পিউটিং ও DevOps · কোর্স হোম৮১টি পর্বপুরো কোর্সের রোডম্যাপ।
- Signal — প্রসেসকে বার্তা পাঠানো আর সামলানোগভীরে যানSignal-এর তত্ত্ব আর handler লেখার নিয়ম।
- Linux-এ মেমরিগভীরে যানmalloc, reclaim আর OOM killer-এর ভেতরের ব্যবস্থা।
- পারফরম্যান্স আর observabilityপাশের ট্র্যাকtop, vmstat, perf দিয়ে তদন্তের পদ্ধতি।