Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagebash
#!/bin/bash
# Written by Milton Suen (milton.suen@datacore.com) Oct 31, 2024
# Revision: Update to support running the script in a detachablepersistent session using screen or tmux..

# Define colors
RED='\033[0;31m'
BOLD_RED='\033[1;31m'
GREEN='\033[0;32m'
BOLD_GREEN='\033[1;32m'
UNDERLINE_BOLD_GREEN='\033[4;32m'
YELLOW='\033[0;33m'
BOLD_YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD_BLUE='\033[1;34m'
MAGENTA='\033[0;35m'
BOLD_MAGENTA='\033[1;35m'
CYAN='\033[0;36m'
BOLD_CYAN='\033[1;36m'
RESET='\033[0m' # Reset color to default

# Function to display usage information
usage() {
    echo "Usage: $0 -d swarm_ip -p admin:password -i new_log_level [-t duration_in_seconds] [-D|--detachpersistent] [-v]"
    echo "  -d, --swarm_ip           IP address of the Swarm API endpoint (or set SCSP_HOST environment variable)"
    echo "  -p, --credentials        Credentials in the format admin:password"
    echo "  -i, --log.level          New log level to set"
    echo "  -t, --time               Duration in seconds to keep the new log level (optional)"
    echo "  -D, --detachpersistent             Run the script in a detachabledetached session using screen or tmux"
    echo "  -v, --verbose            Enable verbose mode for debug messages"
    exit 1
}

# Default options
detachpersistent=false
verbose=false
output_log="script_output.log"  # Log file for capturing detachablepersistent session output

# Function to display debug messages if verbose mode is enabled
debug() {
    if $verbose; then
        echo "[DEBUG] $1"
    fi
}

# Function to check if either 'screen' or 'tmux' is installed
check_screen_or_tmux() {
    if ! command -v tmuxscreen &>/dev/null && ! command -v screentmux &>/dev/null; then
        echo "Error: Neither 'screen' nor 'tmux' is installed. Cannot run in detachablepersistent mode."
        detachpersistent=false  # Disable detachablepersistent session
    fi
}

# Function to format file size
format_size() {
    local size=$1
    if (( size >= 1073741824 )); then
        echo "$(awk "BEGIN {printf \"%.1fGB\", $size/1073741824}")"
    elif (( size >= 1048576 )); then
        echo "$(awk "BEGIN {printf \"%.1fMB\", $size/1048576}")"
    elif (( size >= 1024 )); then
        echo "$(awk "BEGIN {printf \"%.1fKB\", $size/1024}")"
    else
        echo "${size}B"
    fi
}

# Function to format duration
format_duration() {
    local duration=$1
    local hours=$((duration / 3600))
    local minutes=$(( (duration % 3600) / 60 ))
    local seconds=$((duration % 60))
    printf "%02d:%02d:%02d" $hours $minutes $seconds
}

# Function to check if jq is available and set up JSON parsing method
check_jq() {
    if [[ -x "/usr/local/bin/jq" ]]; then
        echo "/usr/local/bin/jq"
    elif [[ -x "$(pwd)/jq" ]]; then
        echo "$(pwd)/jq"
    elif command -v jq &>/dev/null; then
        echo "jq"
    else
        echo "grep"
    fi
}

jq_or_grep=$(check_jq)

# Parse input arguments
while [[ "$#" -gt 0 ]]; do
    case $1 in
        -d|--swarm_ip) swarm_ip="$2"; shift 2 ;;
        -p|--credentials) credentials="$2"; shift 2 ;;
        -i|--log.level) new_log_level="$2"; shift 2 ;;
        -t|--time)
            if [[ -n "$2" && "$2" != -* ]]; then
                duration="$2"
                shift 2
            else
                read -p "Enter duration in seconds: " duration
                shift
            fi
            ;;
        -D|--detachpersistent) detachpersistent=true; shift ;;
        -v|--verbose) verbose=true; shift ;;
        *) usage ;;
    esac
done

# Check if 'screen' or 'tmux' is installed
check_screen_or_tmux

# If swarm_ip is not provided, try using SCSP_HOST environment variable
if [[ -z "$swarm_ip" ]]; then
    if [[ -n "$SCSP_HOST" ]]; then
        swarm_ip="$SCSP_HOST"
        debug "Using Swarm IP from SCSP_HOST: $swarm_ip"
    else
        echo "Error: swarm_ip not provided and SCSP_HOST is not set."
        usage
    fi
fi

# Check if required arguments are provided
if [[ -z "$credentials" || -z "$new_log_level" ]]; then
    usage
fi

# Retrieve cluster name and handle JSON parsing
debug "Retrieving the cluster name from Swarm API."
if [[ "$jq_or_grep" == "grep" ]]; then
    clusterName=$(curl --user "$credentials" -sS "http://$swarm_ip:91/api/storage/clusters" | grep -oP '"name":\s*"\K[^"]+')
else
    clusterName=$(curl --user "$credentials" -sS "http://$swarm_ip:91/api/storage/clusters" | "$jq_or_grep" -r '._embedded.clusters[0].name')
fi

if [[ -z "$clusterName" ]]; then
    echo "Failed to retrieve the cluster name. Please check your inputs."
    exit 1
fi
debug "Cluster Name: $clusterName"

# Main logic function to run the script tasks
main_script() {
    local swarm_ip="$1"
    local credentials="$2"
    local new_log_level="$3"
    local duration="$4"
    local clusterName="$5"
    local log_file="/var/log/datacore/castor.log"
    local initial_size=$(stat -c%s "$log_file" 2>/dev/null || echo 0)
    local current_log_level
    local jq_or_grep="$6"

    # Display initial information
    echo -e "Swarm IP: ${GREEN}$swarm_ipip${RESET}"
    echo -e "Credentials: ${GREEN}[hidden for security]${RESET}"
    echo -e "Cluster Name: $clusterName${GREEN}$clusterName${RESET}"

    debug "Starting main_script function..."

    # Retrieve current log level
    if [[ "$jq_or_grep" == "grep" ]]; then
        current_log_level=$(curl --user "$credentials" -sS "http://$swarm_ip:91/api/storage/clusters/$clusterName/settings/log.level" | grep -oP '"value":\s*\K[0-9]+')
    else
        current_log_level=$(curl --user "$credentials" -sS "http://$swarm_ip:91/api/storage/clusters/$clusterName/settings/log.level" | "$jq_or_grep" -r '.value')
    fi
    echo ""
    echo -e "New log level: : ${BOLD_GREEN}$new_log_levellevel${RESET}"
    echo -e "Current log level is ${GREEN}$current_log_level.${RESET}"

    # Skip update if new level matches the current level
    if [[ "$current_log_level" -eq "$new_log_level" ]]; then
        echo ""
        echo -e "Log level is already set to ${BOLD_GREEN}$new_log_levellevel${RESET}. No changes made."
        return
    fi

    # Update the log level using PUT
    echo -e "Updating log level to ${GREEN}$new_log_levellevel${RESET}..."
    response=$(curl --user "$credentials" -sS -X PUT -H "Content-Type: application/json" \
        "http://$swarm_ip:91/api/storage/clusters/$clusterName/settings/log.level" \
        -d "{\"value\": $new_log_level}")

    if [[ "$jq_or_grep" == "grep" ]]; then
        updated_log_level=$(echo "$response" | grep -oP '"value":\s*\K[0-9]+')
    else
        updated_log_level=$(echo "$response" | "$jq_or_grep" -r '.value')
    fi

    if [[ "$updated_log_level" -eq "$new_log_level" ]]; then
        echo -e "Log level changed successfully from ${GREEN}$current_log_levellevel${RESET}${BOLD_GREEN}$new_log_levellevel${RESET}."
    else
        echo -e "Failed to update log level. Response: $response: ${RED}$response${RESET}"
        exit 1
    fi

    # Countdown and revert log level
    if [[ -n "$duration" && "$duration" -gt 0 ]]; then
        echo -e "Keeping log level at ${YELLOW}$new_log_levellevel${RESET} for $duration${YELLOW}$duration${RESET} second(s)..."
        echo -e ""
        for ((i=duration; i>0; i--)); do
            printf -v countdown "%02d:%02d:%02d" $((i/3600)) $(( (i%3600) / 60 )) $((i%60))
            echo -ne "Countdown: $countdown${YELLOW}$countdown${RESET} remaining...\r"
            sleep 1
        done
        echo -e "\n\nTime's up! Reverting log level back to ${GREEN}$current_log_levellevel${RESET}..."

        response=$(curl --user "$credentials" -sS -X PUT -H "Content-Type: application/json" \
            "http://$swarm_ip:91/api/storage/clusters/$clusterName/settings/log.level" \
            -d "{\"value\": $current_log_level}")

        if [[ "$jq_or_grep" == "grep" ]]; then
            reverted_log_level=$(echo "$response" | grep -oP '"value":\s*\K[0-9]+')
        else
            reverted_log_level=$(echo "$response" | "$jq_or_grep" -r '.value')
        fi

        final_size=$(stat -c%s "$log_file" 2>/dev/null || echo 0)
        size_diff=$(( final_size - initial_size ))
        size_diff_formatted=$(format_size "$size_diff")
        duration_formatted=$(format_duration "$duration")
        echo -e "Approximate ${BOLD_GREEN}$size_diff_formattedformatted${RESET} new logs were generated at log level ${BOLD_GREEN}$new_log_levellevel${RESET}. Current castor.log size is ${BOLD_GREEN}$(format_size "$final_size")${RESET} after $duration_formatted."

        if [[ "$reverted_log_level" -eq "$current_log_level" ]]; then
            echo -e "Log level reverted successfully back to $current_log_level."
        else
            echo "Failed to revert log level. Response: $response"
            exit 1${BOLD_GREEN}$current_log_level${RESET}."
        else
   fi     else    echo -e "Failed to revert echolog "Log level. change is permanent until manually modified.Response: ${RED}$response${RESET}"
    fi } 
# Run in detachable or directly ifexit $detach;1
then     # Pass the main_script functionfi
to the tmux session if available, otherwise use screen else
      if command -vecho tmux &>/dev/null; then
    "Log level change is permanent until manually modified."
   tmux new-session -d -s indexer_script "$(declare -f main_script format_size format_duration check_jq debug); main_script \"$swarm_ip\" \"$credentials\" \"$new_log_level\" \"$duration\" \"$clusterName\" \"$jq_or_grep\" | tee \"$output_log\""
        tmux attach-session -t indexer_script
    eliffi
}

# Run in persistent or directly
if $persistent; then
    # Pass the main_script function to the screen session and store the output in a file
    if command -v screen &>/dev/null; then
        screen -dmS indexer_script bash -c "$(declare -f main_script format_size format_duration check_jq debug); main_script \"$swarm_ip\" \"$credentials\" \"$new_log_level\" \"$duration\" \"$clusterName\" \"$jq_or_grep\" | tee \"$output_log\""
        screen -r indexer_script
    else
  
    elif echo "Error: Neithercommand -v tmux nor screen available. Run without --detach."&>/dev/null; then
        tmux new-session -d -s exit 1
    fi

    # Wait for the tmux or screen session to complete and then display the output log
    sleep 1
    if command -v tmux &>/dev/null; then
        while tmux list-sessions | grep -q "indexer_script"; doindexer_script "$(declare -f main_script format_size format_duration check_jq debug); main_script \"$swarm_ip\" \"$credentials\" \"$new_log_level\" \"$duration\" \"$clusterName\" \"$jq_or_grep\" | tee \"$output_log\""
        tmux attach-session -t indexer_script
    else
        echo "Error: Neither screen nor tmux available. Run without --persistent."
        exit 1
    fi
sleep
1    # Wait for the screen donesession to complete and then elifdisplay commandthe -voutput screen &>/dev/null; thenlog
    sleep 1
    while screen -list | grep -q "indexer_script"; do
   
        sleep 1

       done
    fi

    echo ""
    cat "$output_log"
else
    main_script "$swarm_ip" "$credentials" "$new_log_level" "$duration" "$clusterName" "$jq_or_grep" | tee "$output_log"
fi

...