#!/bin/bash # ============================================================================= # SAP HANA Monitoring Library - Shared Functions # ============================================================================= # Logging function with script name prefix # Usage: log_message "SCRIPT_NAME" "message" log_message() { local script_name="$1" local message="$2" local timestamp=$(date "+%Y-%m-%d %H:%M:%S") echo "[${timestamp}] [${script_name}] ${message}" | tee -a "${LOG_FILE}" } # Acquire lock for script execution # Usage: acquire_lock "SCRIPT_NAME" # Returns: 0 on success, 1 on failure (already running) acquire_lock() { local script_name="$1" local lock_file="${LOCK_DIR}/hana_${script_name}.lock" if [ -e "$lock_file" ]; then log_message "$script_name" "Script is already running. Exiting." return 1 fi touch "$lock_file" echo "$lock_file" return 0 } # Release lock # Usage: release_lock "LOCK_FILE" release_lock() { local lock_file="$1" if [ -n "$lock_file" ] && [ -f "$lock_file" ]; then rm -f "$lock_file" fi } # Get state value # Usage: get_state "KEY" get_state() { local key="$1" if [ -f "${STATE_DIR}/${key}.state" ]; then cat "${STATE_DIR}/${key}.state" else echo "" fi } # Set state value # Usage: set_state "KEY" "VALUE" set_state() { local key="$1" local value="$2" echo "$value" > "${STATE_DIR}/${key}.state" } # Send notification if state changed # Usage: send_notification_if_changed "SCRIPT_NAME" "ALERT_KEY" "TITLE_PREFIX" "MESSAGE" "IS_ALERT" "CURRENT_VALUE" send_notification_if_changed() { local script_name="$1" local alert_key="$2" local title_prefix="$3" local current_message="$4" local is_alert_condition="$5" local current_value="$6" local hostname=$(hostname) local previous_value=$(get_state "$alert_key") if [ "$current_value" != "$previous_value" ]; then local full_title="" local full_message="" if [ "$is_alert_condition" == "true" ]; then full_title="${title_prefix} Alert" full_message="🚨 Critical: ${current_message}" log_message "$script_name" "ALERT: ${full_message}" else if [ -n "$previous_value" ] && [ "$previous_value" != "OK" ]; then full_title="${title_prefix} Resolved" full_message="✅ Resolved: ${current_message}" log_message "$script_name" "RESOLVED: ${full_message}" else set_state "$alert_key" "$current_value" return fi fi local final_message="[${COMPANY_NAME} | ${hostname}] ${full_message}" if [ -n "$NTFY_TOKEN" ] && [ -n "$NTFY_TOPIC_URL" ]; then curl -H "Authorization: Bearer ${NTFY_TOKEN}" -H "Title: ${full_title}" -d "${final_message}" "${NTFY_TOPIC_URL}" > /dev/null 2>&1 log_message "$script_name" "Notification sent: ${full_title}" else log_message "$script_name" "Ntfy not configured, skipping notification" fi set_state "$alert_key" "$current_value" fi } # Run command as HANA user using su # Usage: run_as_hana_user "COMMAND" run_as_hana_user() { local command="$1" su - "$HANA_USER" -c "$command" } # Get disk usage percentage for a directory # Usage: get_disk_usage_percentage "/path/to/dir" # Returns: Usage percentage as integer (without % sign) get_disk_usage_percentage() { local dir="$1" if [ ! -d "$dir" ]; then echo "0" return fi df "$dir" 2>/dev/null | awk 'NR==2 {gsub(/%/,"",$5); print $5}' } # Get mount point for a directory # Usage: get_mount_point "/path/to/dir" # Returns: Mount point path get_mount_point() { local dir="$1" df "$dir" 2>/dev/null | awk 'NR==2 {print $NF}' } # Get available disk space in KB for a directory # Usage: get_available_space_kb "/path/to/dir" # Returns: Available space in KB get_available_space_kb() { local dir="$1" df -k "$dir" 2>/dev/null | awk 'NR==2 {print $4}' } # Find log directories on the same mount point # Usage: find_log_dirs_on_mount "mount_point" # Returns: Space-separated list of log directories find_log_dirs_on_mount() { local mount_point="$1" local result="" for log_entry in "${LOG_DIRS_FOR_CLEANUP[@]}"; do local entry_mount="${log_entry%%:*}" local log_dir="${log_entry#*:}" if [ "$entry_mount" == "$mount_point" ] && [ -d "$log_dir" ]; then if [ -n "$result" ]; then result="$result $log_dir" else result="$log_dir" fi fi done echo "$result" } # Clean old log files in a directory # Usage: clean_log_files "/path/to/log/dir" "max_age_days" # Returns: Number of files deleted and space freed clean_log_files() { local log_dir="$1" local max_age_days="${2:-7}" local files_deleted=0 local space_freed=0 if [ ! -d "$log_dir" ]; then log_message "CLEANUP" "Log directory '$log_dir' not found. Skipping." echo "0:0" return fi # Find and delete old log files while IFS= read -r -d '' file; do if [ -f "$file" ]; then local file_size=$(stat -c%s "$file" 2>/dev/null || echo "0") rm -f "$file" 2>/dev/null && { files_deleted=$((files_deleted + 1)) space_freed=$((space_freed + file_size)) } fi done < <(find "$log_dir" -type f -mtime +$max_age_days -print0 2>/dev/null) # Also clean empty directories find "$log_dir" -type d -empty -delete 2>/dev/null log_message "CLEANUP" "Deleted $files_deleted files from '$log_dir', freed $((space_freed / 1024)) KB" echo "${files_deleted}:${space_freed}" } # Automatic disk cleanup function # Usage: auto_cleanup "mount_point" "target_free_percentage" # Returns: 0 if cleanup successful, 1 if failed or not needed auto_cleanup() { local mount_point="$1" local target_free_percentage="${2:-5}" if [ "$AUTO_CLEANUP_ENABLED" != "true" ]; then log_message "CLEANUP" "Auto-cleanup is disabled. Skipping." return 1 fi local log_dirs=$(find_log_dirs_on_mount "$mount_point") if [ -z "$log_dirs" ]; then log_message "CLEANUP" "No log directories configured for mount point '$mount_point'. Skipping cleanup." return 1 fi log_message "CLEANUP" "Starting auto-cleanup for mount point '$mount_point'. Log dirs: $log_dirs" local total_freed=0 local total_files=0 for log_dir in $log_dirs; do local result=$(clean_log_files "$log_dir" "$MAX_LOG_FILE_AGE_DAYS") local files="${result%%:*}" local freed="${result#*:}" total_files=$((total_files + files)) total_freed=$((total_freed + freed)) done log_message "CLEANUP" "Cleanup complete. Total files deleted: $total_files, Total space freed: $((total_freed / 1024)) KB" if [ $total_freed -gt 0 ]; then return 0 else return 1 fi } # Check disk space and perform auto-cleanup if needed # Usage: check_and_cleanup_disk "directory" "threshold" # Returns: 0 if OK or cleanup successful, 1 if critical and cleanup failed check_and_cleanup_disk() { local dir="$1" local threshold="${2:-85}" local usage=$(get_disk_usage_percentage "$dir") local mount_point=$(get_mount_point "$dir") if [ -z "$usage" ] || [ "$usage" -eq 0 ]; then log_message "CLEANUP" "Could not determine disk usage for '$dir'. Skipping." return 1 fi if [ "$usage" -gt "$threshold" ]; then log_message "CLEANUP" "Disk usage ${usage}% exceeds threshold ${threshold}% for '$dir'. Attempting cleanup..." if auto_cleanup "$mount_point" "$MIN_FREE_SPACE_AFTER_CLEANUP"; then local new_usage=$(get_disk_usage_percentage "$dir") log_message "CLEANUP" "After cleanup, disk usage is ${new_usage}%" if [ "$new_usage" -le "$threshold" ]; then return 0 else log_message "CLEANUP" "Cleanup completed but usage ${new_usage}% still above threshold" return 0 fi else log_message "CLEANUP" "Cleanup failed or no files to clean for '$dir'" return 1 fi fi return 0 }