bash logging - ghdrako/doc_snipets GitHub Wiki

Po dodaniu tego fragmentu na początku skryptu, wszystkie komunikaty wypisywane przez skrypt (w tym błędy) będą zapisywane do /var/log/myscript.log i jednocześnie będą wyświetlane w konsoli.

#!/bin/bash

log_file="/var/log/myscript.log"

exec > >(tee -a "$log_file") 2>&1
  1. Definiuje zmienną log_file: log_file="/var/log/myscript.log" - ustawia lokalizację pliku logu, w którym będą zapisywane logi.
  2. Przekierowuje standardowe wyjście i błąd:
    • exec > >(tee -a "$log_file"): Używa polecenia exec, aby przekierować standardowe wyjście (stdout) do procesu tee, który zapisuje wszystkie wyjścia do pliku oraz jednocześnie wyświetla je na standardowym wyjściu.
    • -a oznacza, że dane będą dopisywane do pliku (jeśli plik już istnieje).
    • 2>&1: Przekierowuje standardowy błąd (stderr) do standardowego wyjścia (stdout), co oznacza, że zarówno błędy, jak i normalne komunikaty będą zapisywane do tego samego pliku logu.

Logging to file and system log

Usage of the logger command sends messages to the syslog system within the script execution

#!/bin/bash

LOG_TAG="MyScript"
LOG_FILE="/var/log/myscript.log"

log_message() {
    local message="$1"
    echo "$(date +'%Y-%m-%d %H:%M:%S') $message" | tee -a "$LOG_FILE" | logger -t "$LOG_TAG"
}

log_message "Script execution started."

# Script operations...

log_message "Script execution completed."
sudo journalctl --since "24 hours ago"
sudo journalctl --since "24 hours ago" --follow  # --follow: Aby na bieżąco śledzić nowe wpisy w logach
sudo journalctl -u my_service.service --since "24 hours ago" # -u <unit>: Aby wyświetlić logi dla konkretnej usługi (np. my_service.service)
sudo journalctl --since "24 hours ago" -n 100  # -n <number>: Aby ograniczyć liczbę wyświetlanych wpisów, możesz użyć opcji -n

Log with mail notification

#!/bin/bash

RECIPIENT="[email protected]"

log_and_notify() {
    local message="$1"
    echo "$(date +'%Y-%m-%d %H:%M:%S') $message" | mail -s "Script Alert" "$RECIPIENT"
}

log_and_notify "Anomaly detected in script execution."

Log function

log_file="/var/log/my_backup.log"
log() {
  local message="$1"
  local log_file="script.log"
  echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$log_file"
}

# Usage
log "Script started."

Verbose Logging

Provide a verbose mode that logs additional information for in-depth debugging. verbose_log() { [ "$VERBOSE" = true ] && echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> verbose.log }

Debug Mode

if [ "$DEBUG" = true ]; then
  set -x Enable debugging
fi
if [ "$DEBUG" = true ]; then
  set +x Disable debugging
fi

Logging Levels

#!/bin/bash

# Function to log messages
log_message() {
  local LOG_TYPE=$1
  local MESSAGE=$2
  echo "$(date '+%Y-%m-%d %H:%M:%S') [${LOG_TYPE}] ${MESSAGE}"
}

# Function to check if a file exists
check_file() {
  local FILE=$1
  if [[ -f $FILE ]]; then
    log_message "INFO" "File ${FILE} exists."
    return 0
  else
    log_message "ERROR" "File ${FILE} does not exist."
    return 1
  fi
}

# Main script
FILE_PATH="/path/to/file.txt"
check_file "$FILE_PATH"
log_info() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') - INFO: $1" >> script.log
}
log_warning() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') - WARNING: $1" >> script.log
}
log_error() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') - ERROR: $1" >> script.log
}

Rotating Log Files

  • implementation
log_file="script.log"
max_logs=5
if [ -f "$log_file" ]; then
  mv "$log_file" "$log_file.1"
fi
ls -1 "$log_file". | sort -r -n | tail -n +$max_logs | xargs -I {} rm -- {}
<your_program> 2>&1 | rotatelogs <opts> <logfile> <rotation_criteria>

logrotate

Example logrotate config snippet for your Script:

/var/log/my_script.log {
daily
rotate 14 # Keep 2 weeks of history
compress
missingok # No fuss if the log file isn't there yet
}

Syslog

Most Linux systems have a logging daemon (rsyslogd or syslog-ng) configured to:

  • Categorize Logs: Messages tagged with facilities (auth, cron, user, etc.) and severity levels (info, warn, crit)
  • Route Log Traffic: To different files, network targets, even databases.

Integration with Syslog

logger -t my_script "Starting data import process" # '-t' adds a tag
logger -p user.notice "Script executed successfully."

Using logger Effectively

  1. Set Message Priority:
logger -p user.notice "Script initiated archival process"

See man logger for priority levels.

  1. Tagging (Important!):
logger -t disk_cleanup -s "Cleaned 10.5GB of old log files"
# '-s' also prints to STDOUT, great for live status display

Tags give you log filters to see just your script’s output

Centralized Logging

For multiple machines, send logs over the network:

  • Remote Syslog Server: Can receive messages over UDP, TCP (reliable, use for mission-critical stuff). Your rsyslog config defines which messages it accepts.
  • ELK/EFK or Graylog: Popular log aggregation platforms. Great when lots of different sources need management, analysis, and dashboards.
⚠️ **GitHub.com Fallback** ⚠️