بازگشت به وبلاگ

چیت‌شیت journalctl: دنبال کردن، فیلتر کردن و پایش لاگ‌های Linux

۱۱ شهریور ۱۴۰۵

journalctl در یک خط: journalctl -u <service> -f لاگ زنده یک سرویس را دنبال می‌کند، journalctl -u <service> -n 100 صد خط آخر را نشان می‌دهد و journalctl --since "1 hour ago" همه رویدادهای اخیر را. همین‌ها 90 درصد لحظه‌های «چرا این سرویس پایین است» را پوشش می‌دهد. باقی این چیت‌شیت همان الگوهای آماده کپی است که شما را از بازخوانی صفحه man در ساعت 2 نیمه‌شب نجات می‌دهد — فیلتر بر اساس unit، زمان، اولویت و بوت، به‌علاوه دستورهای پاک‌سازی‌ای که جلوی خوردن دیسک توسط ژورنال را می‌گیرند. هر دستوری که در ادامه می‌بینید روی هر توزیع systemd‌دار (Ubuntu، Debian، Fedora، Arch) عیناً اجرا می‌شود.

journalctl چیست و چرا مستقیم سراغ /var/log/syslog نمی‌رویم؟

لاگ‌گیری به سبک قدیم در Linux، فایل‌های متنی ساده زیر /var/log می‌نوشت — syslog، auth.log، messages. systemd جای آن را با journal عوض کرد: یک لاگ باینری و ایندکس‌شده که systemd-journald مدیریتش می‌کند. grep ساده نمی‌تواند آن را بخواند؛ journalctl تنها درِ ورودی است و در عوض، فیلتر بر اساس سرویس، زمان، بوت و شدت را بدون ورزیدگی با regex می‌گیرید.

مدل ذهنی ساده است: journal همه‌چیز را ذخیره می‌کند و journalctl ابزار پرس‌وجوست. یک سرویس به فایل لاگ مخصوص خودش نیاز ندارد — هرچه زیر systemd روی stdout/stderr بنویسد، خودکار وارد journal می‌شود. به همین دلیل journalctl -u nginx حتی وقتی نمی‌دانید nginx لاگ خطایش را کجا تنظیم کرده کار می‌کند.

یک نکته: در بعضی نصب‌های مینیمال، journal فرّار است (در /run ذخیره می‌شود و با ریبوت پاک می‌شود) چون /var/log/journal وجود ندارد. یک بار درستش کنید:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal

چگونه 100 خط آخر یک لاگ را ببینم؟

-n خروجی را به N خطِ جدیدتر محدود می‌کند (پیش‌فرض 10 است):

journalctl -n 100                      # last 100 lines of everything
journalctl -u nginx -n 100             # last 100 lines from one unit
journalctl -n 100 --no-pager           # print and exit — perfect for piping

--no-pager بیش از ظاهرش مهم است: بدون آن journalctl باز می‌شود less و اسکریپت، پایپ یا one-liner شما روی ssh منتظر فشردن کلید می‌ماند. هر دستوری که خروجی‌اش را پایپ می‌کنید باید این فلگ را داشته باشد.

چگونه لاگ‌ها را زنده دنبال کنم، مثل tail -f؟

فلگ -f همان tail -f در journalctl است — ورودی‌های جدید را همان لحظه استریم می‌کند:

journalctl -f                    # everything, live
journalctl -u sshd -f            # just the SSH daemon, live
journalctl -u ollama -f -n 50    # live, but start with the last 50 lines

این همان دستوری است که در ترمینال دوم اجرا می‌کنید، در حالی که در ترمینال اول سرویس را ری‌استارت می‌کنید: systemctl restart nginx در یک پنجره، journalctl -u nginx -f در پنجره دیگر، و علت crash معمولاً ظرف چند ثانیه خودش را معرفی می‌کند. من همین چرخه را روی homelab خودم هر بار که کانتینر یا سرویسی اذیت می‌کند اجرا می‌کنم.

چگونه لاگ‌های یک سرویس مشخص را نشان دهم؟

-u بر اساس unit مربوط به systemd فیلتر می‌کند:

journalctl -u nginx                    # one unit, all history
journalctl -u nginx -u redis           # several units at once
journalctl _SYSTEMD_UNIT=nginx.service # the exact-match alternative

unitها می‌توانند unitهای کمکی راه بیندازند که خروجی جالب در همان‌جا می‌ماند — گاهی یک وب‌اپ خراب، خطای واقعی را زیر unit دیگری لاگ می‌کند. اگر -u <service> هیچ‌چیز نشان نداد ولی سرویس واضحاً اجرا می‌شود، اول نام واقعی unit را پیدا کنید:

systemctl list-units --type=service | grep -i <guess>

همین الگوی -u برای timerها هم کار می‌کند (systemctl list-timers نام‌ها را نشان می‌دهد) و برای سرویس‌های کاربری — برای هر چیزی که زیر systemd --user اجرا می‌شود، --user را اضافه کنید:

journalctl --user -u pipewire -n 50

چگونه لاگ‌ها را بر اساس زمان فیلتر کنم؟

--since و --until timestamp می‌گیرند، اما عبارت‌های نسبیِ بخشنده هم قبول می‌کنند:

journalctl --since "1 hour ago"
journalctl --since "2026-09-01 09:00" --until "2026-09-01 12:00"
journalctl --since today
journalctl --since yesterday --until now -u cron

یک بازه زمانی را با یک unit جفت کنید و triage حادثه در یک خط انجام می‌شود: «API بین ساعت 09:00 تا لحظه سقوط چه لاگ کرده؟» برای یک ماشین تکی، این از هر log aggregator سریع‌تر است.

چگونه فقط خطاها (یا هشدارها) را نشان دهم؟

-p بر اساس priority فیلتر می‌کند و از نام‌های شدت syslog استفاده می‌کند:

journalctl -p err -b              # errors only, since this boot
journalctl -p warning..alert -u nginx   # a range of severities

اولویت‌ها به ترتیب نزولی: emerg، alert، crit، err، warning، notice، info، debug. وقتی یک ماشین «رفتار عجیب می‌کند»، journalctl -p err -b --since today سریع‌ترین بررسی سلامت است — بدون نویز خطوط عادی info به سؤال «آیا واقعاً چیزی در حال خطا خوردن است؟» جواب می‌دهد.

چگونه لاگ‌های بوت قبلی را ببینم؟

سرویس‌هایی که موقع استارت crash می‌کنند، خطوط لاگ را قبل از بوت فعلی تولید می‌کنند و journalctl بی‌سروصدا فقط بوت فعلی را نشان می‌دهد. -b بوت‌ها را انتخاب می‌کند:

journalctl -b                 # current boot only
journalctl -b -1              # previous boot
journalctl -b -1 -u sshd      # why SSH died last time
journalctl --list-boots       # index of stored boots

این مفیدترین فلگ برای سناریوی «خراب شد، ریبوتش کردم و حالا خطا را نمی‌بینم» است — خطا سر جایش است، یک بوت عقب‌تر.

مرجع سریع: فلگ‌هایی که حفظ کردنشان می‌ارزد

هدفدستور
دنبال کردن زنده یک سرویسjournalctl -u <svc> -f
100 خط آخرjournalctl -n 100
از یک ساعت پیشjournalctl --since "1 hour ago"
خطاهای این بوتjournalctl -p err -b
بوت قبلیjournalctl -b -1
مصرف دیسک ژورنالjournalctl --disk-usage
خروجی قابل پردازش توسط ماشینjournalctl -o json-pretty
فقط پیام‌های کرنلjournalctl -k

چگونه جلوی پر شدن دیسک به‌خاطر ژورنال را بگیرم؟

اول ببینید چقدر هزینه دارد، بعد سقف بگذارید:

journalctl --disk-usage
sudo journalctl --vacuum-size=500M     # keep newest 500 MB
sudo journalctl --vacuum-time=30d      # keep newest 30 days

برای دائمی کردن سقف، SystemMaxUse=500M را زیر بخش [Journal] در /etc/systemd/journald.conf بگذارید و بعد sudo systemctl restart systemd-journald را اجرا کنید. با این سقف حجم و فیلتر بوتِ بالا، ژورنال یک ابزار می‌ماند، نه یک نشت آرام دیسک.

journalctl در مقابل dmesg در مقابل /var/log — اول کدام را بررسی کنیم؟

  • journalctl — رفتار اپلیکیشن‌ها و سرویس‌ها. هرچه systemd مدیریت می‌کند اینجاست؛ ایندکس‌شده و قابل فیلتر. توقف اولِ پیش‌فرض.
  • journalctl -k / dmesg — کرنل و سخت‌افزار: killهای OOM، ریست‌های USB، خطاهای دیسک. اگر پروسه‌ای بی‌دلیل مُرد، قبل از مقصر دانستن اپ، دنبال OOM killer اینجا بگردید.
  • /var/log/<app>/ — فقط برای اپ‌هایی که خودشان فایل لاگ می‌نویسند (لاگ‌های access در nginx، PostgreSQL). حتی آنجا هم خطاهای استارت معمولاً به ژورنال می‌ریزند.

همین گردش‌کار برای سرویس‌های هوش مصنوعی محلی هم جواب می‌دهد — وقتی unit مربوط به ollama serve گیر می‌کند، journalctl -u ollama -n 100 خطای بارگذاری مدل را بلافاصله نشان می‌دهد؛ همان‌طور که در مقایسه Ollama و LM Studio آمده است.

کل چیت‌شیت همین بود: -u برای unit، -f برای دنبال کردن، -n برای تعداد خطوط، --since برای زمان، -p برای شدت، -b برای بوت‌ها. شش فلگ تقریباً به هر سؤال لاگی جواب می‌دهد که یک باکس Linux از شما خواهد پرسید.

FAQ

چگونه با journalctl لاگ‌ها را زنده دنبال کنم؟

دستور journalctl -f مانند tail -f از ژورنال سیستم tail می‌گیرد؛ با -u <unit> دامنه‌اش را به یک سرویس محدود کنید.

لاگ‌های بوت قبلی را چگونه ببینم؟

دستور journalctl -b -1 بوت آخر و -b بوت فعلی را نشان می‌دهد. اول باید ذخیره‌سازی دائمی فعال باشد (پوشه /var/log/journal).

چگونه journalctl را بر اساس زمان فیلتر کنم؟

از --since و --until با timestamp ساده یا عبارت 1 hour ago استفاده کنید و با -p err ترکیبش کنید تا فقط خطاها بمانند.

— mrsaynothing

— mrsaynothing

یادداشت‌های میدانی درباره AI، لینوکس و self-hosting.

این نوشته را در dev.to بحث کنید dev.to ↗

آموزش بعدی با ایمیل

هر نوشته یک ایمیل. درستش کن، برو سراغ بعدی.

self-hosted · بدون واسطه‌های ثالث · لغو اشتراک با یک کلیک

این چیست؟

Ollama یا LM Studio: کدام ابزار LLM محلی را انتخاب کنید؟

این نوشته‌ها را می‌پسندید؟ این همان کاری است که برای زندگی از آن درمی‌آورم. استخدامم کنید