تحلیلگر لاگ (Log Analyzer)

مینی‌پروژهٔ آزمایشگاه سیستم‌عامل با Bash — آفلاین، بدون sudo، آماده برای ارائهٔ ۹ دقیقه‌ای

بخش اول: معرفی پروژه

این پروژه یک اسکریپت Bash با منوی ساده است که یک فایل لاگ را می‌خواند، خطاها را می‌شمرد و یک گزارش متنی می‌سازد. کد روی Bash 5.2 اجرا و هر سه سناریو تست شده است.

۱. نام پروژه: تحلیلگر لاگ سیستم — Log Analyzer

۲. مسئله: سرورها و سیستم‌های Linux هر اتفاقی را در فایل‌های لاگ ثبت می‌کنند. این فایل‌ها صدها خط دارند و پیدا کردن خطاهای مهم با چشم سخت است. مدیر سیستم باید سریع بفهمد چند خطا رخ داده و کدام خطا بیشتر تکرار شده.

۳. هدف: ساختن ابزاری کوچک که با چند انتخاب از منو، خلاصهٔ وضعیت لاگ را نشان دهد و نتیجه را در یک فایل گزارش ذخیره کند.

۴. قابلیت‌های اصلی:

  1. نمایش خلاصه: تعداد کل خطوط و تعداد INFO، WARNING و ERROR
  2. نمایش فقط خطوط ERROR
  3. جست‌وجوی یک کلمه که کاربر تایپ می‌کند
  4. نمایش ۳ خطای پرتکرار
  5. ذخیرهٔ گزارش در پوشهٔ reports
  6. مدیریت خطا: نبودن آرگومان، نبودن فایل، فایل خالی، انتخاب نامعتبر از منو

۵. دستورات و مفاهیم استفاده‌شده:

نوع موارد
دستورات آشنا echo، grep، cut، sort، head، wc، mkdir، chmod، ls، cat
دستورات جدید uniq -c، date، read -p
مفاهیم جدید Bash shebang، متغیر، آرگومان $1 و $#، شرط if و تست فایل، کد خروج و exit، تابع و local، $( )، هدایت > و >> و <، pipe، حلقهٔ while، دستور case

۶. مفاهیم جدیدی که یاد می‌گیری: نوشتن اسکریپت قابل اجرا، گرفتن آرگومان، بررسی وجود فایل، تابع، منوی تکرارشونده با while و case، ترکیب چند دستور با pipe برای شمارش تکرارها، و ذخیرهٔ خروجی در فایل.

۷. زمان تقریبی آماده‌سازی:

کار زمان
ساخت محیط و تایپ کد ۳۰ دقیقه
خواندن آموزش دستورات جدید ۴۵ دقیقه
اجرای سناریوها و فهم کد ۴۵ دقیقه
تمرین ارائه و سؤالات ۶۰ دقیقه
جمع حدود ۳ ساعت

بخش دوم: پیش‌نیازها و ساخت محیط آزمایش

پیش‌نیاز فقط یک ترمینال Ubuntu است. همهٔ دستورات پیش‌فرض نصب هستند، اینترنت و sudo لازم نیست. ساختار نهایی پوشه این می‌شود:

~/log_project/
├── log_analyzer.sh      ← اسکریپت اصلی
├── logs/
│   ├── server.log       ← لاگ نمونه (۱۶ خط)
│   └── empty.log        ← فایل خالی برای تست خطا
└── reports/             ← خود اسکریپت می‌سازد

گام ۱ — ساخت پوشه‌ها (در هر مسیری اجرا کنی، چون ~ یعنی پوشهٔ خانه):

mkdir -p ~/log_project/logs
cd ~/log_project
pwd

خروجی pwd چیزی شبیه /home/amin/log_project است. از اینجا به بعد همهٔ دستورات را داخل ~/log_project اجرا کن.

گام ۲ — ساخت لاگ نمونه. کل این بلوک را یکجا کپی و در ترمینال Paste کن. ساختار << 'EOF' اسمش here-document است: همهٔ خطوط تا EOF را به cat می‌دهد و > آن‌ها را در فایل می‌نویسد.

cat > logs/server.log << 'EOF'
2026-11-01 08:00:01 INFO System boot completed
2026-11-01 08:00:15 INFO User ali logged in
2026-11-01 08:05:42 WARNING CPU usage above 80%
2026-11-01 08:10:03 ERROR Disk space low on /home
2026-11-01 08:12:27 INFO User sara logged in
2026-11-01 08:15:10 ERROR Failed login for user root
2026-11-01 08:15:45 ERROR Failed login for user root
2026-11-01 08:20:00 INFO Backup started
2026-11-01 08:25:33 WARNING Memory usage above 70%
2026-11-01 08:30:12 ERROR Disk space low on /home
2026-11-01 08:31:08 INFO Backup finished
2026-11-01 08:40:19 ERROR Failed login for user root
2026-11-01 08:45:00 WARNING CPU usage above 80%
2026-11-01 08:50:21 INFO User ali logged out
2026-11-01 08:55:37 ERROR Service nginx stopped unexpectedly
2026-11-01 09:00:00 INFO System health check passed
EOF

گام ۳ — ساخت فایل خالی و بررسی:

touch logs/empty.log
ls logs
wc -l logs/server.log

خروجی مورد انتظار:

empty.log  server.log
16 logs/server.log

گام ۴ — ساخت اسکریپت. با nano log_analyzer.sh فایل را باز کن، کد بخش چهارم را Paste کن و با Ctrl+O، Enter، Ctrl+X ذخیره کن. بعد:

chmod +x log_analyzer.sh
ls -l log_analyzer.sh

در خروجی باید -rwxr-xr-x ببینی؛ حرف x یعنی فایل اجرایی شده.

نکته: چون آزمایشگاه اینترنت ندارد، کل پوشهٔ log_project را روی فلش ببر. اگر فایل از فلش کپی شد، یک بار دیگر chmod +x را اجرا کن.

بخش سوم: آموزش دستورات و مفاهیم جدید

۱۱ مفهوم جدید در این پروژه است. همهٔ مثال‌ها اجرا شده‌اند و خروجی‌ها واقعی هستند. مثال‌ها را داخل ~/log_project اجرا کن.

۱. Shebang (#!/bin/bash)

۲. متغیر و جایگذاری خروجی دستور $( )

name="Amin"
echo "Hello $name"
today=$(date +%Y-%m-%d)
echo "Today is $today"
Hello Amin
Today is 2026-11-01

۳. آرگومان‌های اسکریپت ($0، $1، $#)

#!/bin/bash
echo "Script name: $0"
echo "First arg  : $1"
echo "Arg count  : $#"
Script name: args.sh
First arg  : logs/server.log
Arg count  : 1

۴. شرط if و تست‌های [ ]

if [ condition ]; then
    commands
else
    commands
fi
تست معنی
-f file فایل وجود دارد
-s file فایل خالی نیست
-z "$var" متغیر خالی است
a -ne b عدد a با b برابر نیست (not equal)
! برعکس کردن شرط
if [ -f logs/server.log ]; then
    echo "File exists"
else
    echo "File not found"
fi

۵. کد خروج (exit و $?)

ls logs/nothing.log
echo "Exit code: $?"
ls: cannot access 'logs/nothing.log': No such file or directory
Exit code: 2

۶. تابع (Function) و local

function_name() {
    commands
}
function_name arg1
greet() {
    local person="$1"
    echo "Hi $person"
}
greet Sara

۷. دریافت ورودی با read -p

۸. حلقهٔ while true و دستور case

case "$var" in
    1) commands ;;
    2) commands ;;
    *) default ;;
esac

;; پایان هر حالت است و * یعنی «هر چیز دیگر».

choice=2
case "$choice" in
    1) echo "One" ;;
    2) echo "Two" ;;
    *) echo "Unknown" ;;
esac

۹. هدایت ورودی و خروجی (>، >>، <)

echo "first" > test.txt
echo "second" >> test.txt
cat test.txt
wc -l < test.txt
first
second
2

۱۰. Pipe و دستور uniq -c

printf 'b\na\nb\nc\nb\n' | sort | uniq -c | sort -nr
      3 b
      1 c
      1 a

۱۱. دستور date و گزینه‌های تازهٔ grep

بخش چهارم: کد کامل پروژه

نام فایل اصلی log_analyzer.sh است و در ~/log_project قرار می‌گیرد. کد ۱۰۹ خط است، فقط از دستورات پیش‌فرض Ubuntu استفاده می‌کند، هیچ فایلی پاک نمی‌کند و فقط در پوشهٔ reports می‌نویسد.

#!/bin/bash
# ============================================================
#  Log Analyzer
#  Usage: ./log_analyzer.sh <log_file>
#  Example: ./log_analyzer.sh logs/server.log
#  Log line format: DATE TIME LEVEL MESSAGE
#  e.g. 2026-11-01 08:10:03 ERROR Disk space low on /home
# ============================================================

# ---------- 1) Settings (variables) ----------
REPORT_DIR="reports"
LOG_FILE="$1"

# ---------- 2) Check the input argument ----------
if [ $# -ne 1 ]; then
    echo "Usage: $0 <log_file>"
    echo "Example: $0 logs/server.log"
    exit 1
fi

if [ ! -f "$LOG_FILE" ]; then
    echo "Error: file '$LOG_FILE' not found."
    exit 2
fi

if [ ! -s "$LOG_FILE" ]; then
    echo "Error: file '$LOG_FILE' is empty."
    exit 3
fi

# ---------- 3) Functions ----------

# Count lines that have a given level (INFO / WARNING / ERROR)
count_level() {
    local level="$1"
    grep -c " $level " "$LOG_FILE"
}

# Show a short summary of the log file
show_summary() {
    local total=$(wc -l < "$LOG_FILE")
    echo "------ Summary of $LOG_FILE ------"
    echo "Total lines : $total"
    echo "INFO        : $(count_level INFO)"
    echo "WARNING     : $(count_level WARNING)"
    echo "ERROR       : $(count_level ERROR)"
}

# Show only ERROR lines
show_errors() {
    echo "------ ERROR lines ------"
    grep " ERROR " "$LOG_FILE"
}

# Search for a word that the user types
search_keyword() {
    read -p "Enter a word to search: " keyword

    if [ -z "$keyword" ]; then
        echo "Error: you did not enter any word."
        return
    fi

    echo "------ Lines containing '$keyword' ------"
    if ! grep -i -- "$keyword" "$LOG_FILE"; then
        echo "No result found for '$keyword'."
    fi
}

# Show the 3 most repeated error messages
top_errors() {
    echo "------ Top 3 repeated errors ------"
    grep " ERROR " "$LOG_FILE" | cut -d' ' -f4- | sort | uniq -c | sort -nr | head -3
}

# Save summary + top errors into a report file
save_report() {
    mkdir -p "$REPORT_DIR"
    local report_file="$REPORT_DIR/report_$(date +%Y-%m-%d).txt"

    echo "Report created at: $(date '+%Y-%m-%d %H:%M:%S')" > "$report_file"
    show_summary >> "$report_file"
    top_errors   >> "$report_file"

    echo "Report saved to: $report_file"
}

# ---------- 4) Main menu (loop) ----------
while true; do
    echo
    echo "========= Log Analyzer ========="
    echo "1) Show summary"
    echo "2) Show ERROR lines"
    echo "3) Search a word"
    echo "4) Top 3 repeated errors"
    echo "5) Save report"
    echo "0) Exit"
    read -p "Your choice: " choice

    case "$choice" in
        1) show_summary ;;
        2) show_errors ;;
        3) search_keyword ;;
        4) top_errors ;;
        5) save_report ;;
        0) echo "Goodbye!"; exit 0 ;;
        *) echo "Invalid choice. Please enter a number from 0 to 5." ;;
    esac
done

بررسی منطقی: با bash -n خطای نحوی ندارد، روی GNU bash 5.2 (همان نسخهٔ Ubuntu 24.04) اجرا شده، نیازی به sudo و اینترنت ندارد، و اجرای مجدد همان نتیجه را می‌دهد چون گزارش هر روز با > بازنویسی می‌شود و mkdir -p اگر پوشه باشد خطا نمی‌دهد.

بخش پنجم: توضیح بخش‌به‌بخش کد

کد چهار بخش اصلی دارد که با کامنت ---------- جدا شده‌اند: تنظیمات، بررسی ورودی، توابع، و منوی اصلی. ترتیب اجرا هم همین است: اول چک می‌کند فایل درست است، بعد منو را تا وقتی 0 زده نشده تکرار می‌کند.

بخش ۰ — سربرگ (خط ۱ تا ۸)

بخش ۱ — تنظیمات (REPORT_DIR و LOG_FILE)

بخش ۲ — بررسی ورودی (سه if)

بخش ۳الف — count_level و show_summary

بخش ۳ب — show_errors

بخش ۳پ — search_keyword

بخش ۳ت — top_errors (مهم‌ترین خط)

این یک خط پنج pipe دارد. داده مرحله‌به‌مرحله این‌طور عوض می‌شود:

مرحله دستور خروجی این مرحله
۱ grep " ERROR " ۶ خط خطا، با تاریخ و ساعت
۲ cut -d' ' -f4- فقط متن خطا، مثل Failed login for user root
۳ sort متن‌های یکسان کنار هم می‌آیند
۴ uniq -c هر متن یک بار با تعدادش: 3 Failed login...، 2 Disk space...، 1 Service nginx...
۵ sort -nr از بیشترین به کمترین
۶ head -3 فقط سه مورد اول

بخش ۳ث — save_report

بخش ۴ — منوی اصلی (while + case)

بخش ششم: اجرای عملی و آزمایش پروژه

همهٔ خروجی‌های این بخش از اجرای واقعی اسکریپت کپی شده‌اند. برای کوتاه شدن، منوی تکراری فقط یک بار نشان داده شده.

اجرا (داخل ~/log_project):

cd ~/log_project
./log_analyzer.sh logs/server.log

منویی که باید ببینی:

========= Log Analyzer =========
1) Show summary
2) Show ERROR lines
3) Search a word
4) Top 3 repeated errors
5) Save report
0) Exit
Your choice:

سناریوی ۱ — اجرای عادی و موفق

ورودی‌ها به ترتیب: 1، 2، 4، 5، 0

Your choice: 1
------ Summary of logs/server.log ------
Total lines : 16
INFO        : 7
WARNING     : 3
ERROR       : 6

Your choice: 2
------ ERROR lines ------
2026-11-01 08:10:03 ERROR Disk space low on /home
2026-11-01 08:15:10 ERROR Failed login for user root
2026-11-01 08:15:45 ERROR Failed login for user root
2026-11-01 08:30:12 ERROR Disk space low on /home
2026-11-01 08:40:19 ERROR Failed login for user root
2026-11-01 08:55:37 ERROR Service nginx stopped unexpectedly

Your choice: 4
------ Top 3 repeated errors ------
      3 Failed login for user root
      2 Disk space low on /home
      1 Service nginx stopped unexpectedly

Your choice: 5
Report saved to: reports/report_2026-11-01.txt

Your choice: 0
Goodbye!

بعد از خروج، گزارش را نشان بده (تاریخ و ساعت در آزمایشگاه همان روز است):

ls reports
cat reports/report_*.txt
report_2026-11-01.txt
Report created at: 2026-11-01 22:23:08
------ Summary of logs/server.log ------
Total lines : 16
INFO        : 7
WARNING     : 3
ERROR       : 6
------ Top 3 repeated errors ------
      3 Failed login for user root
      2 Disk space low on /home
      1 Service nginx stopped unexpectedly

سناریوی ۲ — جست‌وجو با ورودی‌های متفاوت

ورودی‌ها: گزینهٔ 3 چهار بار، با کلمه‌های root، backup، kernel و یک بار فقط Enter

Your choice: 3
Enter a word to search: root
------ Lines containing 'root' ------
2026-11-01 08:15:10 ERROR Failed login for user root
2026-11-01 08:15:45 ERROR Failed login for user root
2026-11-01 08:40:19 ERROR Failed login for user root

Your choice: 3
Enter a word to search: backup
------ Lines containing 'backup' ------
2026-11-01 08:20:00 INFO Backup started
2026-11-01 08:31:08 INFO Backup finished

Your choice: 3
Enter a word to search: kernel
------ Lines containing 'kernel' ------
No result found for 'kernel'.

Your choice: 3
Enter a word to search:
Error: you did not enter any word.

نکتهٔ نمایشی: backup با حروف کوچک تایپ شده ولی Backup پیدا شد؛ این کار -i است.

سناریوی ۳ — وضعیت‌های نامعتبر

بعد از هر دستور، echo $? را بزن تا کد خروج را ببینی.

حالت دستور خروجی $?
بدون آرگومان ./log_analyzer.sh Usage: ./log_analyzer.sh <log_file> و Example: ./log_analyzer.sh logs/server.log 1
فایل ناموجود ./log_analyzer.sh logs/nothing.log Error: file 'logs/nothing.log' not found. 2
فایل خالی ./log_analyzer.sh logs/empty.log Error: file 'logs/empty.log' is empty. 3
انتخاب غلط در منو اجرای عادی و وارد کردن 9 یا abc Invalid choice. Please enter a number from 0 to 5. و منو دوباره می‌آید برنامه ادامه می‌دهد

مثال:

$ ./log_analyzer.sh logs/nothing.log
Error: file 'logs/nothing.log' not found.
$ echo $?
2

بخش هفتم: برنامهٔ ارائهٔ ۹ دقیقه‌ای

ارائه ۸ دقیقه و ۳۰ ثانیه است و ۳۰ ثانیه برای تأخیر خالی می‌ماند. قبل از شروع، ترمینال را در ~/log_project باز نگه دار و فونت را با Ctrl+Shift+= بزرگ کن.

بخش زمان زمان تجمعی
۱. معرفی مسئله و هدف ۱:۰۰ ۱:۰۰
۲. دستورات و مفاهیم جدید ۲:۰۰ ۳:۰۰
۳. ساختار کد ۱:۳۰ ۴:۳۰
۴. اجرای عملی ۳:۰۰ ۷:۳۰
۵. نتیجه و جمع‌بندی ۱:۰۰ ۸:۳۰

۱. معرفی مسئله و هدف (۱ دقیقه)

«سلام. پروژهٔ من یک تحلیلگر لاگ با Bash است. در لینوکس تقریباً همهٔ سرویس‌ها اتفاقاتشان را در فایل لاگ می‌نویسند، مثل ورود کاربر، هشدار و خطا. این فایل‌ها معمولاً هزاران خط دارند و مدیر سیستم نمی‌تواند همه را بخواند. سؤال اصلی او این است: چند خطا داشتیم و کدام خطا بیشتر تکرار شده؟ ابزار من همین سؤال را با یک منوی ساده جواب می‌دهد و نتیجه را در یک فایل گزارش ذخیره می‌کند. کاملاً آفلاین است و sudo لازم ندارد.»

همزمان cat logs/server.log را اجرا کن و بگو: «هر خط چهار بخش دارد: تاریخ، ساعت، سطح و پیام.»

۲. دستورات و مفاهیم جدید (۲ دقیقه)

«برای این پروژه چند مفهوم جدید یاد گرفتم. اول آرگومان: مسیر فایل لاگ با $1 به اسکریپت داده می‌شود، پس ابزار با هر فایلی کار می‌کند. دوم if با تست فایل: -f می‌پرسد فایل هست؟ و -s می‌پرسد خالی نیست؟ سوم کد خروج: هر برنامه آخر کار یک عدد برمی‌گرداند؛ صفر یعنی موفق. من برای هر خطا یک کد جدا گذاشتم. چهارم تابع: هر گزینهٔ منو یک تابع است که کد مرتب و قابل استفادهٔ دوباره باشد. پنجم while و case: منو داخل یک حلقهٔ بی‌پایان است و case انتخاب کاربر را به تابع درست می‌فرستد. و آخر uniq -c: خطوط تکراری را می‌شمارد، البته فقط وقتی پشت سر هم باشند؛ برای همین قبلش sort می‌کنم.»

۳. ساختار کد (۱ دقیقه و ۳۰ ثانیه)

فایل را با cat log_analyzer.sh یا در ویرایشگر نشان بده و فقط روی چهار بخش اشاره کن:

«کد چهار بخش دارد. اول دو متغیر تنظیمات. بعد سه بررسی ورودی؛ ایده این است که اول ورودی را چک کنیم تا بقیهٔ کد با خیال راحت کار کند. بخش سوم شش تابع است. مهم‌ترینشان top_errors است که با یک خط pipe کار می‌کند: grep خطاها را جدا می‌کند، cut تاریخ را حذف می‌کند تا خطاهای یکسان واقعاً یکسان شوند، sort و uniq می‌شمارند، و sort -nr و head سه تای اول را می‌دهند. بخش آخر منوی اصلی است.»

۴. اجرای عملی (۳ دقیقه)

  1. ./log_analyzer.sh logs/server.log → گزینهٔ 1: «۱۶ خط، ۶ خطا.»
  2. گزینهٔ 4: «مهم‌ترین مشکل سه ورود ناموفق root است؛ یعنی احتمالاً کسی رمز را حدس می‌زند.»
  3. گزینهٔ 3 با backup: «با حرف کوچک نوشتم ولی پیدا شد، به خاطر -i.»
  4. گزینهٔ 9: «ورودی غلط برنامه را نمی‌شکند.»
  5. گزینهٔ 5، بعد 0، بعد cat reports/report_*.txt.
  6. ./log_analyzer.sh logs/nothing.log و echo $?: «خطا و کد خروج ۲.»

۵. نتیجه و جمع‌بندی (۱ دقیقه)

«در این پروژه دیدیم که با ترکیب چند دستور ساده مثل grep و sort و uniq با pipe، می‌شود یک ابزار واقعی ساخت. از مفاهیم جدید مثل آرگومان، شرط، تابع، حلقه و کد خروج استفاده کردم و ورودی‌های غلط را هم مدیریت کردم. این ابزار می‌تواند با تغییر کوچک روی لاگ‌های واقعی سیستم هم کار کند. ممنون از توجهتان.»

بخش هشتم: سؤالات احتمالی استاد

۱۱ سؤال با پاسخ. سه سؤال آخر دربارهٔ تغییر کد است و کدشان تست شده.

۱. هدف این پروژه چیست؟ به مدیر سیستم کمک می‌کند بدون خواندن کل فایل لاگ، تعداد خطاها و پرتکرارترین‌شان را ببیند و گزارش ذخیره کند.

۲. چرا قبل از uniq -c از sort استفاده کردی؟ uniq فقط خطوط تکراری پشت‌سرهم را یکی می‌کند. در لاگ ما Disk space low در خط ۴ و ۱۰ آمده؛ بدون sort دو بار با تعداد ۱ شمرده می‌شد.

۳. چرا cut -d' ' -f4- لازم است؟ چون هر خط تاریخ و ساعت مختلفی دارد. اگر حذفشان نکنیم، هیچ دو خطی یکسان نیست و همه تعداد ۱ می‌گیرند. -f4- یعنی از ستون چهارم تا آخر؛ چون پیام خودش چند کلمه است.

۴. فرق $1 بیرون و داخل تابع چیست؟ بیرون تابع، $1 اولین آرگومان اسکریپت است (مسیر لاگ). داخل count_level، $1 آرگومان خود تابع است (مثلاً ERROR). به همین دلیل مسیر لاگ را اول کار در LOG_FILE ذخیره کردم.

۵. فرق exit و return چیست؟ exit کل اسکریپت را تمام می‌کند؛ return فقط از تابع بیرون می‌آید. در search_keyword اگر ورودی خالی باشد return زدم تا کاربر به منو برگردد، نه اینکه برنامه بسته شود.

۶. خطاها را چطور مدیریت کردی؟ پنج حالت: بدون آرگومان (کد ۱)، فایل ناموجود (کد ۲)، فایل خالی (کد ۳)، کلمهٔ جست‌وجوی خالی، و انتخاب نامعتبر از منو با *). سه حالت اول برنامه را می‌بندند چون بدون فایل کاری نمی‌شود کرد؛ دو حالت آخر فقط پیام می‌دهند.

۷. اگر برنامه را دو بار اجرا کنیم و دو بار گزارش بگیریم چه می‌شود؟ در یک روز، همان فایل بازنویسی می‌شود چون خط اول با > نوشته می‌شود؛ فقط ساعت داخلش عوض می‌شود. در روز دیگر فایل جدیدی با تاریخ تازه ساخته می‌شود. mkdir -p هم بار دوم خطا نمی‌دهد.

۸. محدودیت‌های پروژه چیست؟

۹. (تغییر کد) اگر بخواهیم ۵ خطای پرتکرار نشان دهد چه کار کنیم؟ در top_errors، head -3 را head -5 می‌کنیم. بهتر است بالای فایل متغیر TOP_COUNT=5 بسازیم و بنویسیم head -"$TOP_COUNT" تا فقط یک جا عوض شود. متن عنوان و منو هم باید از Top 3 به Top 5 تغییر کند.

۱۰. (توسعهٔ کد) یک گزینهٔ جدید برای نمایش WARNING اضافه کن. سه کار: یک تابع می‌سازیم، یک خط به منو و یک حالت به case اضافه می‌کنیم:

show_warnings() {
    echo "------ WARNING lines ------"
    grep " WARNING " "$LOG_FILE"
}

# in the menu:
echo "6) Show WARNING lines"

# in case:
6) show_warnings ;;

پیام *) هم باید به from 0 to 6 تغییر کند. این نشان می‌دهد چرا تابع مفید است: اضافه کردن قابلیت به بقیهٔ کد دست نمی‌زند.

۱۱. (توسعهٔ کد) بدون نوشتن نام سطح‌ها، تعداد همهٔ سطح‌ها را بشمار. با awk ستون سوم را جدا می‌کنیم و همان زنجیرهٔ شمارش را می‌زنیم:

awk '{print $3}' logs/server.log | sort | uniq -c | sort -nr
      7 INFO
      6 ERROR
      3 WARNING

مزیتش این است که اگر سطح جدیدی مثل DEBUG در لاگ بیاید، خودکار شمرده می‌شود.

بخش نهم: چک‌لیست آمادگی

شب قبل از آزمایشگاه این موارد را تیک بزن: