دیشب روی یکی از سرورهای پروداکشنمون یه مرتبه IO رفت بالا و زبیکس ایمیل اخطار داد. رفتم و لاگهای nginx و syslog رو خوندم و چیزی دستگیرم نشد. اما متریکهای زبیکس چیز دیگهای رو نشون میداد. مشخص بود که به مدت ۵ دقیقه بخش قابل توجهی از دیسک اشغال شد و دومرتبه آزاد شد… معمولاً این رفتار رو روی ذخیره لاگها و rotate شدنشون میدیدم… شروع کردم به خوندن سایر لاگها و چک کردن crontab و logrotateها… اما اونجا هم چیزی نبود…
به نظر میرسید چیزی غیر از لاگهای سیستم باعث به وجود اومدن این پدیده شده… شاید دامپ حافظه، شاید هر چیز دیگهای که تا این لحظه نتونستم پیداش کنم. (شاید هم جن بوده!) اما چیزی که مشخصه اینه که اگه حتی جن بوده باشه، این پدیده که رو سرور اتفاق افتاد، کار یه پروسه بوده! (به سبک خیابانی! ?)
از اونجایی که هیچ ردی از این اتفاق توی سیستم نداشتم به نظرم رسید که باید یه راهی باشه که بشه IO رو تو پروسهها مانیتور کرد و اون رو جایی ذخیره کرد که اگر دوباره این اتفاق افتاد، نپرم رو سرور سریع ssh بزنم و htop بزنم یا iotop بزنم و… که بفهمم کدوم پروسهها بیشترین منبع رو میگیرن و…
ها!؟ گفتم iotop؟؟ راستی! iotop این قابلیت رو نداره که از وضعیت پروسهها گزارش بگیریم و یه جایی ذخیره کنیم؟
…و این شروع ماجرا بود!
خب، iotop دستوریه که پروسههایی رو که بیشترین IO رو داره به صورت تعاملی نشون میده.
اما چطور میشه از این ابزار برای گرفتن لاگ استفاده کرد؟ رفتم man page خوندم و دیدم که از این راه میشه:
# iotop -oPtqqqbk > /var/log/iomonitor/status.log
من نیاز داشتم که مشخص بشه هر پروسه تو چه زمانی درخواست IO میده (t) همینطور نیاز داشتم که پروسههای اصلی و نه تردهای فرزند اون مانیتور بشن (o) و اینکه فقط پروسههایی که IO دارند لیست بشن، نه همه پروسهها (P) و نیاز نداشتم به ازای هر خط گزارش، بهم یادآوری بشه که کدوم ستون مربوط به read و یا write هست (qqq) و باید میزان IO با واحد یکسانی نمایش داده میشد (k) و اینکه من نیاز به محیط تعاملی نداشتم که با یک کلید از اون محیط خارج بشم یا خطوطی رو فیلتر کنم، من میخوام لاگ تولید کنم و جایی ذخیره کنم (b).
خیر! اینجا از ابزار logrotate استفاده میکنیم که لاگها رو خودش gzip میکنه و قدیمیها رو پاک میکنه. برای این کار کافیه یه فایل با این محتوا تو مسیر etc/logrotate.d/ ایجاد کنیم.
/var/log/iomonitor/status.log { daily missingok rotate 5 compress delaycompress }
خب، کافی که هست، هر زمان که اراده کنم میرم لاگها رو مرور میکنم… و خب، لاگهای قدیمیتر از ۵ روز هم اتوماتیک پاک میشن… اما وقتی لاگی تولید میشه چرا یه regex ننویسیم و داخل لاگ سرور ذخیرهش نکنیم؟ ?
^(?<TIME>[^\ ]*)\ *(?<PID>[\d]*)\ *(?<PRIO>[^\ ]*)\ (?<USER>[^\ ]*)[^\d]*(?<DISKREAD>[\d]*\.[\d]*)[^\d]*(?<DISKWRITE>[\d]*\.[\d]*)[^\d]*(?<SWAPIN>[\d]*\.[\d]*)[^\d]*(?<IO>[\d]*\.[\d]*)[\ \%]*(?<COMMAND>.*)$
اینم از regex. همین دیگه… این هم از داستان سیسادمینی ما تو فرانش. به سایت ما سر بزنید ?