Практичне застосування Bash-скриптів

Завдання

  • Використайте cut, щоб знайти в масиві записів час (08:12:34.123Z) та подію (User login successful). Виведіть знайдене у stdout
    • Для (08:12:34.123Z):
    cut -d'T' -f2 app_name.log | cut -d' ' -f1
    
    • Для (User login successful) , без sed або awk хз як прибрати різну кількість пробілів на початку події (в логах то один, то два), звісно можна через цикл, але то ще довше буде
    cut -d ']' -f2 app_name.log | cut -d ':' -f1 | sed 's/^ */''/g'
    
    • А якщо треба разом, то:
    paste <(cut -d'T' -f2 app_name.log | cut -d' ' -f1) <(cut -d ']' -f2 app_name.log | cut -d ':' -f1 | sed 's/^ */''/g')
    
  • Виконайте попереднє завдання за допомогою awk, але так, щоб отримати події лише за одну годину.
    awk -F'[T\\[\\:\\]]+' '$2 == "08" { gsub(/^ */, "", $6); print $2":"$3":"$4, $6 }' app_name.log
    
  • Створіть systemd юніт, який буде при запуску перевіряти якийсь з присутніх у вашій системі логів (на ваш вибір) на кількість помилок (статусів ERROR або подібних). Продемонструйте його в роботі.
  1. /etc/systemd/system/traefik-err-log-counter.service
[Unit]
Description=Traefik Error Log counter
After=network.target

[Service]
Type=simple
ExecStart=/home/pervent/check_errors.sh /mnt/demo/traefik/logs/traefik.log
Restart=on-failure
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
  1. ./check_errors.sh
#!/bin/bash

ERROR_PATTERNS=("ERR" "CRT")
ERROR_COUNT=0

if [ -n "$1" ]; then
  if [ "$1" == "-" ]; then
    INPUT_SOURCE="/dev/stdin" # Читаемо данні зі стандартного вводу
  else
    LOG_FILE="$1" # Читаємо данні з переданого першого параметра
    if [ ! -f "$LOG_FILE" ]; then
      echo "Error: Лог файл '$LOG_FILE' не знайден." >&2
      exit 1
    fi
    INPUT_SOURCE="$LOG_FILE"
  fi
else
  echo "Error: Не визначен лог файл." >&2
  echo "Usage: $0 <log_file> або $0 - (для стандартного вводу)"
  exit 1
fi

while IFS= read -r LINE; do
  for PATTERN in "${ERROR_PATTERNS[@]}"; do
    if [[ "$LINE" == *"$PATTERN"* ]]; then
      ERROR_COUNT=$((ERROR_COUNT + 1))
      break
    fi
  done
done < "$INPUT_SOURCE"

if [ "$ERROR_COUNT" -gt 0 ]; then
  echo "Знайдено $ERROR_COUNT помилок в '$INPUT_SOURCE'." >&1
  # Тут можемо відправити e-mail вказавши кількість знайдених помилок або іншу дію
else
  echo "В '$INPUT_SOURCE' помилок не знайдено." >&1
fi

exit 0
  1. Результат

  • Використайте інструменти на ваш розсуд, щоб конвертувати наступний датасет в yaml.
  1. Вхідні дані, які припустимо, що зберігаються в файлі data.log

  1. Напишемо невеликий скрипт, який зконвертує вхідні данні в .yml формат. P.S. код можна скоротити в два рази, залишивши тільки читання зі стандартного вводу, але так зручніше :)
if [ -n "$1" ]; then
  if [ "$1" == "-" ]; then
    INPUT_SOURCE="/dev/stdin" # Читаемо данні зі стандартного вводу
  else
    LOG_FILE="$1" # Читаємо данні з переданого першого параметра
    if [ ! -f "$LOG_FILE" ]; then
      echo "Error: Лог файл '$LOG_FILE' не знайден." >&2
      exit 1
    fi
    INPUT_SOURCE="$LOG_FILE"
  fi
else
  echo "Error: Не визначен лог файл." >&2
  echo "Usage: $0 <log_file> або $0 - (для стандартного вводу)"
  exit 1
fi

declare -A data

while read -r line; do
  category=$(echo "$line" | awk -F" - " '{print $1}')
  type=$(echo "$line" | awk -F" - " '{print $2}')
  name=$(echo "$line" | awk -F" - " '{print $3}')
  data["$category"]+="$type: $name"$'\n'
done < "$INPUT_SOURCE"

echo "---"
for category in "${!data[@]}"; do
  echo "$category:"
  echo "$(echo "${data[$category]}" | sed 's/^/  /')"
done
  1. Результат