Linux-এর লগ: journalctl, /var/log, rsyslog ও logrotate
আধুনিক Linux-এ লগ জমা করে journald, আর পড়া হয় journalctl দিয়ে: journalctl -u nginx একটি সার্ভিসের লগ দেখায়, -f রিয়েল টাইমে স্রোত দেখায়, --since ও -p সময় ও গুরুত্ব অনুযায়ী ছাঁকে। লেখা লগ ফাইল থাকে /var/log-এ, সেগুলো লেখে rsyslog বা অ্যাপ্লিকেশন নিজে, আর logrotate নিয়মিত পুরনো ফাইল সংকুচিত ও মুছে দেয়, যাতে ডিস্ক ভরে না যায়।
রাতে সার্ভিস পড়ে গেলে উত্তর প্রায় সবসময় লগে থাকে — প্রশ্ন শুধু কোথায় খুঁজবেন। আধুনিক Linux ডিস্ট্রিবিউশনে (Ubuntu, Debian, RHEL, Fedora, Arch) ঘটনাগুলো জমা করে journald সার্ভিস, আর পড়তে হয় journalctl কমান্ডে। সমান্তরালে অনেক প্রোগ্রাম সাধারণ টেক্সট ফাইল লেখে /var/log-এ, আর সেগুলোর আকার দেখে logrotate। নিচে ব্যবহারিকভাবে দেখানো হবে কীভাবে journalctl দিয়ে Linux-এর লগ পড়তে হয়, বাকি লগ কোথায় থাকে, এবং ঘূর্ণনের সময় কীভাবে গুরুত্বপূর্ণ কিছু না হারাতে হয়।
Linux-এ লগ কোথায় থাকে
উৎস তিনটি, এগুলোকে একটি মানচিত্রের মতো মাথায় রাখা ভালো:
- journald — systemd-র বাইনারি লগ। সব সার্ভিসের stdout ও stderr, কার্নেলের বার্তা ও syslog গ্রহণ করে। সংরক্ষিত হয়
/var/log/journal/-এ (স্থায়ী) বা/run/log/journal/-এ (রিবুট পর্যন্ত)। - /var/log — টেক্সট ফাইল। সেগুলো লেখে
rsyslog(যেমন/var/log/syslog,/var/log/auth.log) বা অ্যাপ্লিকেশন নিজে: nginx, PostgreSQL, MySQL। - কার্নেল রিং বাফার — ড্রাইভার ও হার্ডওয়্যারের বার্তা, যা দেখায়
dmesgবাjournalctl -k।
| ফাইল | এতে কী থাকে |
|---|---|
/var/log/syslog (Debian/Ubuntu) | সাধারণ সিস্টেম লগ |
/var/log/messages (RHEL/Fedora) | একই জিনিস Red Hat পরিবারে |
/var/log/auth.log বা /var/log/secure | লগইন, sudo, SSH |
/var/log/kern.log | কার্নেলের বার্তা |
/var/log/dpkg.log, /var/log/apt/ | প্যাকেজ ইনস্টল |
/var/log/nginx/ | ওয়েব সার্ভারের access.log ও error.log |
/var/log/wtmp, /var/log/btmp | বাইনারি লগইন রেকর্ড, পড়া হয় last ও lastb দিয়ে |
/var/log-এর বেশিরভাগ ফাইল শুধু root বা adm গ্রুপ পড়তে পারে, তাই পড়ার কমান্ড প্রায়ই sudo দিয়ে চালাতে হয়।
journalctl: মৌলিক কমান্ড
আর্গুমেন্ট ছাড়া journalctl পুরো লগ দেখায়, সবচেয়ে পুরনো থেকে, less পেজারে। এটি খুব কমই দরকার — সাধারণত আগে থেকেই পরিসর ছোট করা হয়।
journalctl # পুরো লগ, পুরনো থেকে নতুন
journalctl -e # সরাসরি শেষে খোলা
journalctl -n 50 # শেষ 50 লাইন
journalctl -r # উল্টো ক্রমে, নতুন উপরে
journalctl --no-pager # less ছাড়া, স্ক্রিপ্ট ও grep-এর জন্য সুবিধাজনক
পেজারের ভেতরে less-এর পরিচিত কী কাজ করে: / — খোঁজা, G — শেষে যাওয়া, q — বের হওয়া। লম্বা লাইন স্ক্রিনের প্রস্থে কাটা হয়; বাঁ ও ডান তীর দিয়ে সেগুলো সরানো যায়।
একটি সার্ভিসের লগ: journalctl -u
সবচেয়ে সাধারণ কাজ — একটি systemd ইউনিট কী লিখেছে তা দেখা। ফাইল খুঁজে গ্রেপ করার দরকার নেই:
$ sudo journalctl -u nginx -n 20
Oct 14 03:12:41 web1 systemd[1]: Starting nginx.service - A high performance web server...
Oct 14 03:12:41 web1 nginx[1834]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Failed with result 'exit-code'.
ফ্ল্যাগ -u একাধিকবার দেওয়া যায়: journalctl -u nginx -u php8.2-fpm দুটি সার্ভিসের লগ সময় অনুযায়ী মিশিয়ে দেখায়, যা ত্রুটি দুটির সংযোগস্থলে ঘটলে কাজে লাগে। ব্যবহারকারীর ইউনিটের (systemctl --user) জন্য journalctl --user -u নাম।
রিয়েল টাইমে লগ: journalctl -f
sudo journalctl -u nginx -f
এটি tail -f-এর মতো: শেষের 10 লাইন দেখায় এবং নতুন লাইনের অপেক্ষা করে। সার্ভিস রিস্টার্ট করার বা ত্রুটি পুনরায় ঘটানোর সময় এটি আলাদা টার্মিনালে চালিয়ে রাখা সুবিধাজনক। বের হতে Ctrl+C।
সময় ও বুট অনুযায়ী ফিল্টার
সমস্যা কখন হয়েছে জানা থাকলে --since ও --until ফ্ল্যাগে সময়সীমা দিন। এগুলো সঠিক তারিখ এবং আপেক্ষিক মান দুটোই বোঝে:
journalctl --since "2026-10-14 02:50" --until "2026-10-14 03:30"
journalctl --since "1 hour ago"
journalctl --since yesterday --until today
journalctl -u nginx --since "10 min ago"
আরেকটি কার্যকর ভাগ — সিস্টেমের বুট অনুযায়ী। সার্ভার নিজে রিবুট হলে কারণ খোঁজা হয় আগের সেশনের শেষে:
$ journalctl --list-boots
-2 8f1c... Sat 2026-10-12 09:01:12 UTC Sun 2026-10-13 22:47:03 UTC
-1 a7d2... Sun 2026-10-13 22:48:30 UTC Tue 2026-10-14 03:05:51 UTC
0 c3e9... Tue 2026-10-14 03:07:02 UTC Tue 2026-10-14 09:15:40 UTC
$ journalctl -b -1 -e # আগের বুটের শেষ অংশ
$ journalctl -b # শুধু বর্তমান বুট
বুটের তালিকা তখনই পাওয়া যায়, যখন লগ ডিস্কে সংরক্ষিত থাকে। কীভাবে তা চালু করা যায়, নিচে journald-এর কনফিগারেশন অংশে দেখানো হয়েছে।
গুরুত্ব অনুযায়ী ফিল্টার: journalctl -p
প্রতিটি রেকর্ডের একটি syslog অগ্রাধিকার আছে, 0 থেকে 7 পর্যন্ত। ফ্ল্যাগ -p দেওয়া স্তর এবং তার চেয়ে গুরুতর সবকিছু দেখায়:
| কোড | নাম | কখন ব্যবহার হয় |
|---|---|---|
| 0 | emerg | সিস্টেম অকার্যকর |
| 1 | alert | অবিলম্বে হস্তক্ষেপ দরকার |
| 2 | crit | গুরুতর ত্রুটি |
| 3 | err | ত্রুটি |
| 4 | warning | সতর্কবার্তা |
| 5 | notice | উল্লেখযোগ্য কিন্তু স্বাভাবিক ঘটনা |
| 6 | info | তথ্যমূলক বার্তা |
| 7 | debug | ডিবাগ |
journalctl -p err -b # বুট থেকে সব ত্রুটি
journalctl -p warning..err -u ssh # একটি সার্ভিসের জন্য স্তরের পরিসর
journalctl -p err -b রিবুট বা আপডেটের পরে একটি ভালো প্রথম পরীক্ষা: কয়েক সেকেন্ডে দেখায় কোথায় কী ভুল হলো।
খোঁজা ও অন্যান্য ফিল্টার
journald প্রতিটি রেকর্ডের সঙ্গে কাঠামোবদ্ধ ফিল্ড রাখে, আর সেগুলো দিয়ে grep ছাড়াই ফিল্টার করা যায়:
journalctl _PID=1834 # প্রসেস নম্বর দিয়ে
journalctl _COMM=sshd # প্রোগ্রামের নাম দিয়ে
journalctl _UID=1000 # ব্যবহারকারী দিয়ে
journalctl /usr/sbin/sshd # চালানো ফাইলের পথ দিয়ে
journalctl -k # শুধু কার্নেলের বার্তা (dmesg-এর মতো)
journalctl -t CRON # syslog শনাক্তকারী দিয়ে
journalctl -g "Out of memory" # লেখার ভেতরে খোঁজা, রেগুলার এক্সপ্রেশন
ফ্ল্যাগ -g (--grep) systemd 237-এ যোগ হয়েছে; পুরনো সিস্টেমে সাধারণ পাইপ journalctl --no-pager | grep ... ব্যবহার করুন। বিভিন্ন ফিল্ডের ফিল্টার “এবং” দিয়ে যুক্ত হয়, তাই journalctl -u nginx -p err --since today শুধু আজকের nginx ত্রুটি দেখাবে।
আউটপুটের ফরম্যাট
ফ্ল্যাগ -o ফরম্যাট বদলায়। সবচেয়ে কাজের বিকল্পগুলো:
-o short-iso— সময় ISO 8601 ফরম্যাটে, অ্যাপ্লিকেশনের লগের সঙ্গে তুলনার জন্য সুবিধাজনক।-o verbose— রেকর্ডের সব ফিল্ড, যেমন_SYSTEMD_UNIT,_PID,_BOOT_ID।-o jsonবাjson-pretty— স্ক্রিপ্ট বাjq-এ প্রসেসিংয়ের জন্য।-o cat— শুধু বার্তার টেক্সট, তারিখ ও হোস্ট ছাড়া।
journalctl -u myapp -o json --since today | jq -r '.MESSAGE'
journald কনফিগার করা: সংরক্ষণ ও আকার
সেটিংস থাকে /etc/systemd/journald.conf-এ (পরিবর্তন ভালো হয় /etc/systemd/journald.conf.d/*.conf-এ রেখে)। মূল প্যারামিটার — Storage:
persistent— লগ ডিস্কে/var/log/journal-এ লেখা হয় এবং রিবুটের পরেও টিকে থাকে।volatile— শুধু মেমরিতে,/run/log/journal-এ।auto(ডিফল্ট) —/var/log/journalডিরেক্টরি থাকলে ডিস্কে।
কিছু ন্যূনতম ইমেজে ওই ডিরেক্টরি থাকে না, ফলে রিবুটের পরে ইতিহাস হারিয়ে যায়। স্থায়ী সংরক্ষণ চালু করতে:
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
যাতে journal পুরো ডিস্ক না নেয়, সীমা দিন:
# /etc/systemd/journald.conf.d/size.conf
[Journal]
Storage=persistent
SystemMaxUse=500M
MaxRetentionSec=1month
ডিফল্টে SystemMaxUse হলো ফাইল সিস্টেমের আকারের 10%, তবে 4 GB-র বেশি নয়।
journalctl লগ কীভাবে পরিষ্কার করবেন
$ journalctl --disk-usage
Archived and active journals take up 1.8G in the file system.
sudo journalctl --vacuum-size=300M # সর্বোচ্চ 300 MB রাখা
sudo journalctl --vacuum-time=2weeks # দুই সপ্তাহের পুরনো রেকর্ড মোছা
sudo journalctl --rotate # সক্রিয় ফাইল বন্ধ করা, যাতে সেটিও মোছা যায়
/var/log/journal থেকে rm দিয়ে ফাইল মুছবেন না: vacuum একই কাজ নিরাপদে করে এবং সক্রিয় ফাইলে হাত দেয় না।
rsyslog: ঐতিহ্যবাহী টেক্সট লগ
rsyslog একটি ডেমন, যা syslog বার্তা গ্রহণ করে (journald থেকে ফরওয়ার্ড হওয়াগুলোও) এবং নিয়ম অনুযায়ী ফাইলে সাজায়। কনফিগারেশন — /etc/rsyslog.conf ও /etc/rsyslog.d/*.conf। একটি নিয়ম গঠিত হয় উৎস.স্তর সিলেক্টর ও একটি কাজ দিয়ে:
# /etc/rsyslog.d/50-default.conf (অংশ)
auth,authpriv.* /var/log/auth.log
*.*;auth,authpriv.none -/var/log/syslog
kern.* -/var/log/kern.log
পথের আগে বিয়োগ চিহ্ন (-) মানে প্রতিটি লাইনের পরে ডিস্কে সিঙ্ক না করে লেখা — দ্রুত, কিন্তু দুর্ঘটনায় শেষের কয়েকটি লাইন হারাতে পারে। কনফিগ বদলালে আগে সিনট্যাক্স যাচাই করে সার্ভিস রিস্টার্ট করুন:
sudo rsyslogd -N1
sudo systemctl restart rsyslog
rsyslog-কে journald-এর পাশে রাখার মূল কারণ — লগ কেন্দ্রীয় সার্ভারে পাঠানো। একটি লাইনে সব TCP-তে যাবে:
# /etc/rsyslog.d/90-remote.conf
*.* @@logs.example.com:514
একটি @ মানে UDP, দুটি @@ মানে TCP। পুরো সার্ভার নষ্ট হলেও লগের কপি অন্য মেশিনে থাকবে। স্ক্রিপ্ট থেকে সিস্টেম লগে নিজের বার্তা লিখতে logger ব্যবহার করুন:
logger -t backup -p user.err "ডেটাবেস ব্যাকআপ ব্যর্থ হয়েছে"
journalctl -t backup -n 5
logrotate: লগ ঘূর্ণন
টেক্সট লগ অনন্তকাল বাড়তে থাকে, যদি না কেউ ছাঁটে। এই কাজটি করে logrotate: প্রতিদিন (cron বা logrotate.timer দিয়ে) এটি বর্তমান ফাইলের নাম বদলায়, পুরনোগুলো সংকুচিত করে এবং সবচেয়ে পুরনোগুলো মুছে দেয়। সাধারণ সেটিংস — /etc/logrotate.conf, প্রোগ্রামের নিয়ম — /etc/logrotate.d/-এ।
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 myapp adm
postrotate
systemctl reload myapp > /dev/null 2>&1 || true
endscript
}
| নির্দেশ | অর্থ |
|---|---|
daily / weekly / size 100M | কখন ঘোরানো হবে |
rotate 14 | কতগুলো পুরনো ফাইল রাখা হবে |
compress, delaycompress | gzip-এ সংকোচন, তবে সবচেয়ে নতুন আর্কাইভ অসংকুচিত রাখা |
missingok, notifempty | ফাইল না থাকলে অভিযোগ না করা, খালি ফাইল না ঘোরানো |
create 0640 user group | নতুন ফাইল কী অধিকার নিয়ে তৈরি হবে |
copytruncate | ফাইল কপি করে তারপর খালি করা — যেসব প্রোগ্রাম লগ আবার খুলতে জানে না তাদের জন্য |
postrotate ... endscript | ঘূর্ণনের পরের কমান্ড, সাধারণত অ্যাপ্লিকেশনকে ফাইল পুনরায় খুলতে সংকেত |
নিয়ম কোনো পরিবর্তন ছাড়া যাচাই করতে এবং জোর করে ঘূর্ণন চালাতে:
sudo logrotate -d /etc/logrotate.d/myapp # ড্রাই রান, বিস্তারিত সহ
sudo logrotate -f /etc/logrotate.d/myapp # এখনই ঘোরানো
সাধারণ ভুল — postrotate বা copytruncate ভুলে যাওয়া। তখন অ্যাপ্লিকেশন পুরনো ডেসক্রিপ্টরে নামবদলানো app.log.1-এ লিখতে থাকে, আর নতুন app.log খালি পড়ে থাকে।
টেক্সট লগ পড়া
/var/log-এর ফাইলের জন্য সাধারণ ইউটিলিটিই যথেষ্ট:
sudo tail -n 100 /var/log/syslog # শেষের কয়েক লাইন
sudo tail -F /var/log/nginx/error.log # ঘূর্ণন টিকিয়ে অনুসরণ
sudo less +G /var/log/auth.log # শেষে খোলা
sudo zgrep "Failed password" /var/log/auth.log.*.gz # সংকুচিত আর্কাইভে খোঁজা
sudo grep -c " 500 " /var/log/nginx/access.log # কতগুলো 500 উত্তর
লক্ষ্য করুন tail -F-এ বড় হাতের F: -f-এর বিপরীতে এটি ফাইল আবার খোলে, যখন logrotate সেটি বদলে দেয়।
একটি দুর্ঘটনার ধাপে ধাপে বিশ্লেষণ
“রাতে সার্ভিস পড়ে গেছে” — এমন পরিস্থিতি একটি নির্দিষ্ট ক্রমে বিশ্লেষণ করা সুবিধাজনক:
systemctl status myapp— বর্তমান অবস্থা ও লগের শেষের কয়েক লাইন।journalctl -u myapp --since "03:00" --until "03:30"— পতনের মুহূর্তে সার্ভিস কী লিখেছিল।journalctl -p err -b— একই সময়ে সিস্টেমের অন্য কোনো ত্রুটি আছে কি না।journalctl -k --since "03:00" -g "Out of memory|Killed process"— কার্নেলের OOM killer প্রসেসটি বন্ধ করেছে কি না।- অ্যাপ্লিকেশনের নিজের লগ
/var/log/myapp/-এ,.gzআর্কাইভসহ। - সার্ভার রিবুট হয়ে থাকলে —
journalctl -b -1 -e।
সারসংক্ষেপ
প্রতিদিনের লগ-কাজের জন্য কয়েকটি কমান্ডই যথেষ্ট: সার্ভিসের জন্য journalctl -u, স্রোতের জন্য -f, পরিসর ছাঁটতে --since ও -p err, রিবুট বিশ্লেষণে -b -1। টেক্সট লগ থাকে /var/log-এ, rsyslog সেগুলো সাজায় ও পাঠায়, আর logrotate এবং journalctl --vacuum-* নিশ্চিত করে লগ যেন ডিস্ক না খেয়ে ফেলে। journalctl, ঘূর্ণন ও লোড-বিশ্লেষণ নিয়ে হাতে-কলমে কাজ হয়েছে Linux কোর্সের একটি লেকচারে।
সাধারণ প্রশ্ন
কেন journalctl শুধু শেষ বুটের রেকর্ড দেখায়?
লগ মেমরিতে (/run/log/journal) রাখা হয়েছে। /var/log/journal ডিরেক্টরি বানান, অথবা journald.conf-এ Storage=persistent দিয়ে systemd-journald রিস্টার্ট করুন।
সাধারণ ব্যবহারকারী sudo ছাড়া সিস্টেম লগ কীভাবে পড়বে?
তাকে systemd-journal গ্রুপে যোগ করুন (Debian ও Ubuntu-তে adm): sudo usermod -aG systemd-journal নাম, তারপর আবার লগইন করুন।
অন্য সিস্টেমের, যেমন সংযুক্ত ডিস্কের, journal কি দেখা যায়?
হ্যাঁ, -D ফ্ল্যাগে লগ ডিরেক্টরি দিন: journalctl -D /mnt/var/log/journal। --file ফ্ল্যাগ একটি আলাদা .journal ফাইল পড়ে।
journald থাকলে rsyslog কি লাগে?
বাধ্যতামূলক নয়। পুরনো টুলের জন্য টেক্সট ফাইল দরকার হলে, অথবা কেন্দ্রীয় সার্ভারে লগ পাঠাতে চাইলে এটি কাজে লাগে; অনেক ন্যূনতম ইমেজে এটি আর ইনস্টল করা হয় না।
কোনো সার্ভিসের লগ ফাইলে এক্সপোর্ট করে সহকর্মীকে পাঠাবেন কীভাবে?
journalctl -u নাম --since today --no-pager > service.log চালান — এতে একটি সাধারণ টেক্সট ফাইল তৈরি হবে।
“Linux: с нуля до уверенного администрирования” কোর্সে বিষয়টি অনুশীলনসহ বিস্তারিত শেখানো হয়েছে।
কোর্সে যান