প্রশ্নটা প্রায় সবসময় একই রকম: রাতে সাইট সাড়া দিতে কুড়ি সেকেন্ড নিচ্ছিল, আর সকাল নাগাদ সব নিজে থেকেই ঠিক হয়ে গেছে। দেখার আর কিছু বাকি নেই — top চলতি সেকেন্ডের উত্তর দেয়, অথচ প্রশ্নটা রাত তিনটে নিয়ে। নিচে রইল লোডের সংখ্যাগুলো আসলে কী বোঝায়, কোনগুলো জোড়ায় পড়তে হয়, আর কেন একবারের মাপজোখ সাহায্যের চেয়ে বেশি বিভ্রান্ত করে।

Load average: তিনটি সংখ্যা আর একটি প্রচলিত ভুল ধারণা

uptime
cat /proc/loadavg
nproc

তিনটি সংখ্যা এক, পাঁচ ও পনেরো মিনিটের গড়। এগুলো শূন্যের সঙ্গে নয়, nproc যে কোরসংখ্যা জানায় তার সঙ্গে মেলাতে হয়। আট কোরের মেশিনে 8 মান পূর্ণ কিন্তু সুস্থ লোড: কাজ ঠিক ততটাই যতটা সার্ভার সামলাতে পারে। এক কোরের VPS-এ 2 মান হলো ক্ষমতার দ্বিগুণ লম্বা সারি, আর প্রতিটি অনুরোধ নিজের পালার অপেক্ষা করে।

তিনটি সংখ্যার পারস্পরিক অনুপাত দিক দেখায়। এক মিনিটের মান পনেরো মিনিটের চেয়ে স্পষ্ট বেশি মানে লোড এখনই বাড়ছে। উল্টোটা মানে চূড়া পেরিয়ে গেছে, আপনি তার লেজ দেখছেন।

এবার সেই ভুল ধারণা, যার জন্য এই সংখ্যাগুলো সবচেয়ে বেশি ভুলভাবে পড়া হয়। Linux-এ load average মানে «প্রসেসরের ব্যবহার» নয়। অন্য Unix সিস্টেমের বিপরীতে Linux এতে কেবল চলমান বা চলার জন্য প্রস্তুত প্রসেসই গোনে না, D অবস্থায় থাকা প্রসেসগুলোকেও গোনে — বাধাহীন ঘুমে থাকা। অর্থাৎ যারা ডিস্ক বা নেটওয়ার্ক ফাইল সিস্টেমের অপেক্ষায়। এখান থেকেই আসে সেই সার্ভার, যার লোড 12 অথচ প্রসেসর প্রায় অলস: কাজ এগোচ্ছে না, সবাই সারিতে দাঁড়িয়ে।

প্রসেসর না ডিস্ক

এই দুটি ক্ষেত্র আলাদা করা প্রথম কাজ:

vmstat 1 5
iostat -x 1 3

vmstat-এর আউটপুটে তিনটি কলাম গুরুত্বপূর্ণ। r বলে কতগুলো প্রসেস প্রসেসরের সারিতে আছে, b বলে কতগুলো ইনপুট-আউটপুটের অপেক্ষায় আটকে আছে, আর wa হলো সময়ের সেই অংশ যা প্রসেসর অলস বসে ডিস্কের অপেক্ষায় কাটিয়েছে। ussy সামান্য থাকা সত্ত্বেও wa টানা 10–15 %-এর উপরে থাকলে বুঝতে হবে সার্ভার ডিস্কে আটকে আছে: কোর বাড়ানো অর্থহীন, যেগুলো আছে সেগুলোই খালি।

কোন প্রসেসগুলো অপেক্ষা করছে তা নাম ধরে দেখা যায়:

ps -eo state,pid,comm,wchan:30 | awk '$1 ~ /^D/'

নিজেদের অভিজ্ঞতা থেকে একটি উদাহরণ। ডিফল্ট কনফিগারেশনে Suricata প্রায় ত্রিশ ধরনের ইভেন্ট লেখে এবং সেগুলোর জন্য কোনো রোটেশন ঠিক করে না — একটি চালু সার্ভারে এতে দুই দিনে 15 GB লগ জমেছিল। লোড তখন ব্যস্ত প্রসেসর হিসেবে নয়, ঠিক I/O wait হিসেবেই দেখা দিয়েছিল: সিস্টেম অবিরাম লিখছিল আর বাকি সবকিছু তার পেছনে সারিতে দাঁড়িয়ে ছিল। এর সমাধান বড় প্যাকেজ নয়, ইভেন্টের সংক্ষিপ্ত তালিকা আর ঠিক করা রোটেশন।

উল্টো ঘটনা, বিশুদ্ধভাবে প্রসেসরের এবং অনেক কম স্পষ্ট। একটি ওয়েব পেজ apt ডাকছিল সেই ব্যবহারকারীর নামে, যার অধীনে PHP-FPM চলে। রুট একটি বাইনারি ক্যাশ রাখে /var/cache/apt/pkgcache.bin ফাইলে — ডজনখানেক রিপোজিটরিওয়ালা হোস্টে সেটি 70 MB — এবং বিনা খরচে তা মেমরিতে ম্যাপ করে নেয়। সাধারণ ব্যবহারকারী সেই ডিরেক্টরিতে লিখতে পারে না, তাই প্রতিবার ডাকার সময় ক্যাশ নতুন করে বানায়। একই মেশিনে মাপা: রুট হিসেবে 0.01 সেকেন্ড প্রসেসর সময়, আর অধিকারহীন ব্যবহারকারী হিসেবে 4.2 সেকেন্ড। একই কমান্ড, চারশো গুণ পার্থক্য, আর সেটি পেজের প্রতিটি খোলার সঙ্গে গুণ হচ্ছিল।

দুই ক্ষেত্রেরই উপসংহার এক: লোড মাপতে হয়, আন্দাজ করতে হয় না। প্রতিটি সন্দেহজনক কমান্ডের সময় আলাদা করে নেওয়ায় আধ ঘণ্টা লাগে এবং সাধারণত সেটি অন্য দিকে ইঙ্গিত করে, যেদিক থেকে সন্দেহ শুরু হয়েছিল সেদিকে নয়।

মেমরি: free যা দেখায় বলে মনে হয়, তা নয়

free -h

used কলাম নিজে থেকে খুব কমই বলে, আর free কলাম সরাসরি বিভ্রান্ত করে: Linux অব্যবহৃত মেমরি পেজ ক্যাশকে দিয়ে দেয় এবং প্রথম চাওয়াতেই অ্যাপ্লিকেশনকে ফিরিয়ে দেয়। পড়ার কলাম হলো available — swap-এ না গিয়ে কতটা দখল করা যায়। বড় buff/cache সমস্যা নয়, বরং সিস্টেম ঠিকভাবে চলার লক্ষণ।

swap-এ বর্তমান মান নয়, আকৃতিই গুরুত্বপূর্ণ। উঠে শূন্যে ফিরে এসেছে: স্বল্পস্থায়ী চূড়া ছিল। একবার উঠে সেখানেই থেকে গেছে: চূড়া আগেই ঘটে গেছে, পাতা সরিয়ে দেওয়া হয়েছে আর কেউ সেগুলো ফেরত আনছে না — সার্ভার শান্ত দেখায়, যদিও কোনো এক মুহূর্তে তার মেমরি কম পড়েছিল। বিনিময় এই মুহূর্তে চলছে কি না তা vmstat-এর siso কলাম দেখায়; সেখানে শূন্য নয় এমন মান ধীরগতির সেই রূপ যা ব্যবহারকারীরা সবচেয়ে বেশি টের পান।

রাতের ধসের সময় কোনো প্রসেস যদি নিছক উধাও হয়ে যায়, ব্যাখ্যা সাধারণত এখানেই:

journalctl -k --since yesterday | grep -i "out of memory"
dmesg -T | grep -i "killed process"

Out of memory: Killed process 1234 (mysqld) ধরনের একটি লাইন যেকোনো গ্রাফের চেয়ে ভালোভাবে বিষয়টি মীমাংসা করে: ডেটাবেস «নিজে থেকে পড়ে যায়নি», কার্নেল তাকে থামিয়েছে কারণ মেমরি ফুরিয়ে গিয়েছিল।

এটি কে করছে

ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10

একটি সতর্কতা: ps-এর %CPU প্রসেসের পুরো জীবনকালের গড়, তাই স্বল্প সময়ের ঝলক ওই তালিকায় হারিয়ে যায়। তার জন্য দরকার top বা pidstat 1 5, যেগুলো একটি ব্যবধানে মাপে।

লোড কখন নিরাপত্তার প্রশ্ন হয়ে ওঠে

রাতভর প্রসেসরের সমান 100 %, সঙ্গে অর্থহীন নামের একটি প্রসেস যার কাজের ডিরেক্টরি /tmp বা /dev/shm-এ — এটি মাইনারের চিরচেনা ছবি, বেড়ে ওঠা সাইটের নয়। আগত ট্র্যাফিকের লাফ আর লগে লেখার বৃদ্ধি একসঙ্গে মানে চলমান পাসওয়ার্ড আক্রমণ। লগের পরিমাণ হঠাৎ লাফিয়ে বাড়া সাধারণত কোনো ফিল্টারের মিথ্যা সতর্কতার ঝড়।

সুরক্ষার সরঞ্জামগুলো নিজেরাই আলাদা শ্রেণি। আমাদের এক সার্ভারে একজন দর্শকও না থাকা সত্ত্বেও লোড তিনের আশপাশে ছিল, আর জমা হওয়া প্রসেসর সময় অনুযায়ী ps-এর শীর্ষে ছিল না সাইট, না ডেটাবেস — ছিল CrowdSec, fail2ban, Falco আর Suricata। এটি বিকল হওয়া নয়, এগুলো বন্ধ করার কারণও নয়, তবে সুরক্ষার দাম সংখ্যায় জানা কাজে লাগে: ছোট VPS-এ তা টের পাওয়া যায়।

পর্যবেক্ষণ কেন

উপরের সবকিছু «এখন কী ঘটছে» প্রশ্নের উত্তর দেয়। সকালের প্রশ্ন — রাত তিনটেয় কী হয়েছিল — এই কমান্ডগুলো ঢাকে না: গত রাতের কোনো তথ্য থাকে না, যদি কেউ তা লিখে না রাখে। আর একটিমাত্র VPS-এর জন্য Prometheus আর Grafana দাঁড় করানো সন্দেহজনক, কারণ পর্যবেক্ষণকারী স্ট্যাক পর্যবেক্ষিত সার্ভারের চেয়ে ভারী হয়ে যায়।

প্রতি পাঁচ মিনিটে ডেটাবেসে একটি সারি আর একটি পাতা, যা তা থেকে শেষ চব্বিশ ঘণ্টা আঁকে — এটুকুই যথেষ্ট: load average, প্রসেসরের ব্যবহার ও আলাদা করে I/O wait, মেমরি ও swap, ডিস্কের পড়া ও লেখা, পার্টিশনের ভরাট, inode, ফাইল ডেসক্রিপ্টর, সংযোগ। একই সময়-অক্ষে জোড়াগুলো খালি চোখেই পড়া যায়: শান্ত প্রসেসরের সঙ্গে উঁচু wa, শূন্যে কখনও না ফেরা swap, সীমার কাছে পৌঁছানো ডেসক্রিপ্টর — আসন্ন too many open files ত্রুটি ঘটার কয়েক ঘণ্টা আগেই দেখা যায়। সবকিছু একসঙ্গে কেমন দেখায় তা নিচের ডেমো পাতায় আছে।