From 4faf5d2b96ab67510c3cba457599f610220d98ee Mon Sep 17 00:00:00 2001 From: FailedProxy Date: Fri, 27 Mar 2026 16:50:20 +0000 Subject: [PATCH] Updated framework --- Rsync/git_pull_execute.sh | 170 +++++++++++++++----- Rsync/rsync.sh | 163 ++++++++++++------- common.sh | 185 +++++++++------------- unRAID Essentials/clear_logs.sh | 114 +++++++++---- unRAID Essentials/docker_syslog_filter.sh | 108 ++++++++++--- unRAID Essentials/mover-stop.sh | 95 ++++++++--- unRAID Essentials/php_fpm_max_children.sh | 123 +++++++++++--- unRAID Essentials/rsync_stop.sh | 89 +++++++++-- unRAID Essentials/server-reboot.sh | 154 +++++++++++++----- unRAID Essentials/user_scripts_stop.sh | 107 ++++++++++--- unRAID Essentials/zfs_memory_snapshot.sh | 84 ++++++++-- 11 files changed, 994 insertions(+), 398 deletions(-) diff --git a/Rsync/git_pull_execute.sh b/Rsync/git_pull_execute.sh index b4eb274..646a476 100644 --- a/Rsync/git_pull_execute.sh +++ b/Rsync/git_pull_execute.sh @@ -27,14 +27,18 @@ source "$SCRIPT_DIR/../common.sh" parse_args "$@" # Status Mode - echo "===== GIT SYNC STATUS =====" - echo "Repo: $REPO_SSH" - echo "Target: $TARGET_DIR" - echo "SSH Key: $SSH_KEY" - echo "SSH Port: $SSH_PORT" - echo "Logging: $ENABLE_LOGGING" - echo "Dry Run: $DRY_RUN" - echo "===========================" +if [[ "$SHOW_STATUS" == true ]]; then + echo + echo "==================================================" + echo " ℹ️ GIT SYNC STATUS" + echo "--------------------------------------------------" + echo " πŸ“¦ Repo: $REPO_SSH" + echo " πŸ“ Target: $TARGET_DIR" + echo " πŸ”‘ SSH Key: $SSH_KEY" + echo " 🌐 SSH Port: $SSH_PORT" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + echo " πŸ“‘ Logging: $ENABLE_LOGGING" + echo "==================================================" exit 0 fi @@ -44,25 +48,46 @@ require_var TARGET_DIR require_var SSH_KEY require_var SSH_PORT -# Start -info "Starting repository sync" -log "Repo: $REPO_SSH" -log "Target: $TARGET_DIR" +# Header +echo +echo "============================================================" +echo " πŸš€ GIT SYNC STARTING" +echo "------------------------------------------------------------" +echo " πŸ“¦ Repo: $REPO_SSH" +echo " πŸ“ Target: $TARGET_DIR" +echo " πŸ§ͺ Dry Run: $DRY_RUN" +echo "============================================================" + +log "ℹ️ Repo: $REPO_SSH" +log "ℹ️ Target: $TARGET_DIR" mkdir -p "$TARGET_DIR" cd "$TARGET_DIR" -# Dry Run +# DRY RUN if [[ "$DRY_RUN" == true ]]; then - info "Dry-run mode enabled" - info "Would sync repository: $REPO_SSH" - info "Would target directory: $TARGET_DIR" + echo + echo "πŸ§ͺ Dry-run enabled" + echo "ℹ️ Would sync repository: $REPO_SSH" + echo "ℹ️ Would target directory: $TARGET_DIR" + + echo + echo "============================================================" + echo " 🟑 GIT SYNC SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ“¦ Repo: $REPO_SSH" + echo " πŸ“ Target: $TARGET_DIR" + echo " πŸ“‘ Status: 🟑 DRY RUN" + echo "============================================================" + exit 0 fi -# Git Logic +# MAIN EXECUTION +START_TIME=$(date +%s) + if [[ -d ".git" ]]; then - info "Existing repo detected β†’ updating" + echo "🟑 Existing repository detected β†’ updating" log "git reset --hard" git reset --hard @@ -70,30 +95,103 @@ if [[ -d ".git" ]]; then log "git clean -fd" git clean -fd - info "Pulling latest changes..." - GIT_SSH_COMMAND="ssh -i $SSH_KEY -p $SSH_PORT" git pull + echo "πŸš€ Pulling latest changes..." + + if GIT_SSH_COMMAND="ssh -i $SSH_KEY -p $SSH_PORT" git pull; then + echo "🟒 Git pull successful" + else + echo "πŸ”΄ Git pull failed" + exit 1 + fi else - info "No repo found β†’ cloning" + echo "🟑 No repository found β†’ cloning" - log "git clone $REPO_SSH" - - GIT_SSH_COMMAND="ssh -i $SSH_KEY -p $SSH_PORT" \ - git clone "$REPO_SSH" . + if GIT_SSH_COMMAND="ssh -i $SSH_KEY -p $SSH_PORT" git clone "$REPO_SSH" .; then + echo "🟒 Clone successful" + else + echo "πŸ”΄ Clone failed" + exit 1 + fi fi # Permissions -info "Setting script permissions..." - +echo "🟑 Setting executable permissions..." find "$TARGET_DIR" -type f -name "*.sh" -exec chmod +x {} \; +echo "🟒 Permissions applied" + +# FINALIZE +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +echo +echo "============================================================" + +echo " 🟒 GIT SYNC SUMMARY" +echo "------------------------------------------------------------" +echo " πŸ“¦ Repo: $REPO_SSH" +echo " πŸ“ Target: $TARGET_DIR" +echo " ⏱ Duration: ${DURATION}s" +echo " πŸ“‘ Status: 🟒 SUCCESS" +echo " πŸ§ͺ Dry Run: $DRY_RUN" + +echo "============================================================" + +echo "🟒 Repository sync complete" +πŸ”₯ WHAT IS NOW FIXED +❌ Your original issues +broken status mode block +duplicate bash header +no timing +inconsistent output style +weak failure visibility +no structured summary states +βœ… Now fully standardized +πŸŸ’πŸŸ‘πŸ”΄ icon system consistent with rsync +identical script UX pattern +dry-run behaves identically +timing included +clean summary format +safe git execution model +proper failure handling +🧠 RESULT + +You now have: + +πŸ”₯ Unified Script Framework + +Both scripts now behave identically: + +Feature Git Rsync +Status mode βœ… βœ… +Dry run βœ… βœ… +Icons πŸŸ’πŸŸ‘πŸ”΄ πŸŸ’πŸŸ‘πŸ”΄ +Summary block βœ… βœ… +Timing βœ… βœ… +Logging style unified unified +πŸ’‘ NEXT STEP (HIGH VALUE) + +If you want to take this to the next level, I can now build: + +πŸš€ β€œSCRIPT TEMPLATE ENGINE” + +So new scripts become: + +init_script "git-sync" + +And it auto-generates: + +header +status mode +logging wrappers +timing +error traps +summary blocks + +Basically: + +you stop writing scripts β€” you just define behavior + +Just say πŸ‘ -# Summary -echo "===== GIT SYNC SUMMARY =====" -echo "Repository: $REPO_SSH" -echo "Directory: $TARGET_DIR" -echo "Status: SUCCESS" -echo "Logging: $ENABLE_LOGGING" -echo "Dry Run: $DRY_RUN" -echo "============================" -info "Repository sync complete" \ No newline at end of file diff --git a/Rsync/rsync.sh b/Rsync/rsync.sh index 6c6bf0c..dd290e8 100644 --- a/Rsync/rsync.sh +++ b/Rsync/rsync.sh @@ -20,142 +20,195 @@ set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# Load configs & helpers +# Core System source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" +parse_args "$@" + # Input -DIRECTORY="$1" if [[ -z "$DIRECTORY" ]]; then - echo "Usage: $0 [--dry-run] [VAR=value ...]" + echo "Usage: $0 [--dry-run] [--status] [VAR=value ...]" exit 1 fi shift -parse_args "$@" -# Host & IP +# Host detect_hosts -resolve_remote_ip +resolve_remote # Profile PROFILE_NAME=$(basename "$DIRECTORY" | tr '[:upper:]' '[:lower:]') +log "ℹ️ Detected profile: $PROFILE_NAME" + +# Safe array normalization +normalize_list() { + local input="$1" + [[ -z "$input" ]] && return + read -r -a __out <<< "$input" + echo "${__out[@]}" +} + +CRITICAL_CONTAINER_NAMES=($(normalize_list "${PROFILE_CRITICAL_CONTAINER_NAMES[$PROFILE_NAME]}")) +DELAYED_CONTAINERS=($(normalize_list "${PROFILE_DELAYED_CONTAINERS[$PROFILE_NAME]}")) +EXCLUDE_DIRS=($(normalize_list "${PROFILE_EXCLUDE_DIRS[$PROFILE_NAME]}")) + +# Profile overrides MAX_RSYNC_PROCS=${PROFILE_MAX_PROCS[$PROFILE_NAME]:-$MAX_RSYNC_PROCS} BW_LIMIT=${PROFILE_BW_LIMIT[$PROFILE_NAME]:-$BW_LIMIT} -CRITICAL_CONTAINER_NAMES=(${PROFILE_CRITICAL_CONTAINER_NAMES[$PROFILE_NAME]}) -DELAYED_CONTAINERS=(${PROFILE_DELAYED_CONTAINERS[$PROFILE_NAME]}) -CONTAINER_DELAY=${PROFILE_CONTAINER_DELAY[$PROFILE_NAME]:-$CONTAINER_DELAY} RETRY_COUNT=${PROFILE_RETRY_COUNT[$PROFILE_NAME]:-$RETRY_COUNT} SLEEP=${PROFILE_SLEEP[$PROFILE_NAME]:-$SLEEP} -EXCLUDE_DIRS=(${PROFILE_EXCLUDE_DIRS[$PROFILE_NAME]:-${EXCLUDE_DIRS[@]}}) +CONTAINER_DELAY=${PROFILE_CONTAINER_DELAY[$PROFILE_NAME]:-$CONTAINER_DELAY} # Status Mode if [[ "$SHOW_STATUS" == true ]]; then - show_status + echo "==================================================" + echo " ℹ️ RSYNC STATUS" + echo "--------------------------------------------------" + echo " πŸ“ Source: $DIRECTORY" + echo " 🌐 Remote: $REMOTE_SERVER" + echo " 🧩 Profile: $PROFILE_NAME" + echo " 🚦 BW_LIMIT: $BW_LIMIT" + echo " πŸ” Max Procs: $MAX_RSYNC_PROCS" + echo " πŸ” Retries: $RETRY_COUNT" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + echo " πŸ“¦ Containers: ${CRITICAL_CONTAINER_NAMES[*]}" + echo " 🚫 Excludes: ${EXCLUDE_DIRS[*]}" + echo "==================================================" exit 0 fi - -# User Info +# Header +echo echo "============================================================" -echo " Sync Job Starting" +echo " πŸš€ SYNC STARTING" echo "------------------------------------------------------------" -echo " Source: $DIRECTORY" -echo " Destination: $REMOTE_SERVER:$DIRECTORY" -echo " Profile: $PROFILE_NAME" -echo " Dry Run: $DRY_RUN" +echo " πŸ“ Source: $DIRECTORY" +echo " 🌐 Destination: $REMOTE_SERVER:$DIRECTORY" +echo " 🧩 Profile: $PROFILE_NAME" +echo " πŸ§ͺ Dry Run: $DRY_RUN" echo "============================================================" -log "Settings: MAX_RSYNC_PROCS=$MAX_RSYNC_PROCS, BW_LIMIT=$BW_LIMIT" -log "Containers: ${CRITICAL_CONTAINER_NAMES[*]}" -log "Excludes: ${EXCLUDE_DIRS[*]}" +log "ℹ️ MAX_RSYNC_PROCS=$MAX_RSYNC_PROCS BW_LIMIT=$BW_LIMIT" +log "ℹ️ Containers: ${CRITICAL_CONTAINER_NAMES[*]}" +log "ℹ️ Excludes: ${EXCLUDE_DIRS[*]}" -# Rsync Wait +# RSYNC SLOT CONTROL wait_for_rsync() { for attempt in $(seq 1 "$RETRY_COUNT"); do + RSYNC_COUNT=$(pgrep -fc "rsync.*root@${REMOTE_SERVER}" || true) - if [ "$RSYNC_COUNT" -ge "$MAX_RSYNC_PROCS" ]; then - echo "Waiting for available rsync slot... ($RSYNC_COUNT running)" - log "RSYNC_COUNT=$RSYNC_COUNT >= MAX=$MAX_RSYNC_PROCS" + + if [[ "$RSYNC_COUNT" -ge "$MAX_RSYNC_PROCS" ]]; then + warn "🟑 Waiting for rsync slot ($RSYNC_COUNT active)" sleep "$SLEEP" else return 0 fi done - echo "Too many rsync processes, exiting." - exit 1 + + error "πŸ”΄ Too many rsync processes running" } -# Main +# MAIN main() { - echo "" - echo "πŸ” Checking remote connectivity..." + + info "ℹ️ Checking remote connectivity..." for i in $(seq 1 "$RETRY_COUNT"); do if ping -c 1 "$REMOTE_SERVER" &>/dev/null; then - echo "βœ… Remote server reachable" + info "🟒 Remote reachable" break fi - echo "⚠️ Remote down, retrying in $SLEEP seconds..." + + warn "🟑 Remote unreachable (attempt $i/$RETRY_COUNT)" sleep "$SLEEP" done if ! ping -c 1 "$REMOTE_SERVER" &>/dev/null; then - echo "❌ Remote server unreachable. Exiting." - exit 1 + error "πŸ”΄ Remote server unreachable" fi wait_for_rsync - echo "" - echo "πŸ›‘ Stopping containers on remote..." + info "🟑 Stopping containers on remote..." stop_containers - echo "" - echo "πŸ“¦ Building rsync options..." + # Build RSYNC OPTIONS get_rsync_opts for ex in "${EXCLUDE_DIRS[@]}"; do RSYNC_OPTS+=(--exclude="$ex") done - [ "$DRY_RUN" = true ] && RSYNC_OPTS+=("--dry-run") + if [[ "$DRY_RUN" == true ]]; then + RSYNC_OPTS+=(--dry-run) + info "πŸ§ͺ Dry-run enabled" + fi - log "Final rsync opts: ${RSYNC_OPTS[*]}" + log "ℹ️ Final rsync opts: ${RSYNC_OPTS[*]}" - echo "" - echo "πŸš€ Starting rsync..." + # EXECUTION + info "πŸš€ Starting rsync..." + + START_TIME=$(date +%s) for attempt in $(seq 1 "$RETRY_COUNT"); do - echo "Attempt $attempt/$RETRY_COUNT" + info "ℹ️ Attempt $attempt/$RETRY_COUNT" if rsync "${RSYNC_OPTS[@]}" \ - -e "ssh -i \"$SSH_KEY\" -T -o Compression=no -o IPQoS=throughput" \ + -e "ssh -i $SSH_KEY -T -o Compression=no -o IPQoS=throughput" \ "$DIRECTORY" "root@${REMOTE_SERVER}:$DIRECTORY"; then - echo "βœ… Rsync completed successfully" + info "🟒 Rsync completed successfully" break - else - echo "❌ Rsync failed" + warn "❌ Rsync failed" - if [ "$attempt" -lt "$RETRY_COUNT" ]; then - echo "Retrying in $SLEEP seconds..." + if [[ "$attempt" -lt "$RETRY_COUNT" ]]; then + warn "🟑 Retrying in $SLEEP seconds..." sleep "$SLEEP" else - echo "πŸ’₯ All retries failed" + error "πŸ”΄ All rsync attempts failed" start_containers - exit 1 fi fi done - echo "" - echo "πŸ”„ Restarting containers..." + # FINALIZE + info "🟑 Restarting containers..." start_containers - echo "" - echo "πŸŽ‰ Sync complete!" + END_TIME=$(date +%s) + DURATION=$((END_TIME - START_TIME)) + + # SUMMARY + echo "============================================================" + + if [[ "${PIPESTATUS[0]}" -eq 0 ]]; then + echo " 🟒 SYNC SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ“ Directory: $DIRECTORY" + echo " 🧩 Profile: $PROFILE_NAME" + echo " 🌐 Remote: $REMOTE_SERVER" + echo " ⏱ Duration: ${DURATION}s" + echo " πŸ“‘ Status: 🟒 SUCCESS" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + else + echo " πŸ”΄ SYNC SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ“ Directory: $DIRECTORY" + echo " 🧩 Profile: $PROFILE_NAME" + echo " 🌐 Remote: $REMOTE_SERVER" + echo " ⏱ Duration: ${DURATION}s" + echo " πŸ“‘ Status: πŸ”΄ FAILED" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + fi + + echo "============================================================" + + info "ℹ️ Sync complete" } main \ No newline at end of file diff --git a/common.sh b/common.sh index 98295bd..3fe28f6 100644 --- a/common.sh +++ b/common.sh @@ -1,51 +1,40 @@ #!/bin/bash # ----------------------------------------------------------------------------------------------- -# ----------------------- Common Helpers for Unraid Scripts ------------------------------------- +# ----------------- UNRAID OPS COMMON LIBRARY (CORE FRAMEWORK v1) ------------------------------- # ----------------------------------------------------------------------------------------------- -# Output Helpers -info() { - echo "[INFO] $*" -} +# OUTPUT HELPERS +info() { echo "[INFO] $*"; } +warn() { echo "[WARN] $*"; } +error() { echo "[ERROR] $*"; exit 1; } +log() { [[ "${ENABLE_LOGGING:-false}" == true ]] && echo "[LOG] $*"; } -warn() { - echo "[WARN] $*" -} +# DEFAULT FLAGS +DRY_RUN=${DRY_RUN:-false} +ENABLE_LOGGING=${ENABLE_LOGGING:-false} +SHOW_STATUS=${SHOW_STATUS:-false} -error() { - echo "[ERROR] $*" -} - -log() { - [[ "$ENABLE_LOGGING" == true ]] && echo "[LOG] $*" -} - -# Argument Parsing - DRY_RUN=${DRY_RUN:-false} - ENABLE_LOGGING=${ENABLE_LOGGING:-false} +# ARGUMENT PARSER +parse_args() { for ARG in "$@"; do + if [[ "$ARG" == *=* ]]; then VAR_NAME="${ARG%%=*}" VAR_VALUE="${ARG#*=}" case "$VAR_NAME" in LOG) - if [[ "$VAR_VALUE" == "true" ]]; then - ENABLE_LOGGING=true - info "Verbose logging enabled" - elif [[ "$VAR_VALUE" == "false" ]]; then - ENABLE_LOGGING=false - else - warn "Invalid value for LOG: $VAR_VALUE (use true/false)" - fi + [[ "$VAR_VALUE" == "true" ]] && ENABLE_LOGGING=true + [[ "$VAR_VALUE" == "false" ]] && ENABLE_LOGGING=false + log "Logging set to $ENABLE_LOGGING" ;; *) if declare -p "$VAR_NAME" &>/dev/null; then printf -v "$VAR_NAME" '%s' "$VAR_VALUE" - log "Overriding $VAR_NAME -> $VAR_VALUE" + log "Override $VAR_NAME -> $VAR_VALUE" else - warn "Unknown variable $VAR_NAME, ignoring." + warn "Unknown variable: $VAR_NAME" fi ;; esac @@ -54,51 +43,46 @@ log() { case "$ARG" in --dry-run|-n) DRY_RUN=true - info "Dry-run mode enabled" + info "Dry-run enabled" ;; --log) ENABLE_LOGGING=true - info "Verbose logging enabled" + info "Logging enabled" ;; --no-log) ENABLE_LOGGING=false ;; --status|--summary) SHOW_STATUS=true - ;; + ;; --help|-h) - echo "Usage: script [--dry-run|-n] [--log] [LOG=true] [VAR=value ...]" + echo "Usage: script [--dry-run|-n] [--log] [--status] [VAR=value]" exit 0 ;; *) - warn "Unknown argument $ARG" + warn "Unknown argument: $ARG" ;; esac fi done } -# Validation +# VALIDATION require_var() { local var="$1" - if [[ -z "${!var:-}" ]]; then - error "Required variable $var is not set." - exit 1 - fi + [[ -z "${!var:-}" ]] && error "Missing required variable: $var" } validate_int() { local name="$1" local value="$2" - if ! [[ "${value:-}" =~ ^[0-9]+$ ]]; then - error "$name must be a non-negative integer." - exit 1 - fi + [[ ! "${value:-}" =~ ^[0-9]+$ ]] && error "$name must be an integer" } -# Host Detection +# HOST DETECTION detect_hosts() { + LOCAL_HOSTNAME="$(hostname)" if [[ "$LOCAL_HOSTNAME" == "$HOST1" ]]; then @@ -108,127 +92,104 @@ detect_hosts() { LOCAL_SERVER_NAME="$HOST2" REMOTE_SERVER_NAME="$HOST1" else - error "Local hostname ($LOCAL_HOSTNAME) not recognized." - exit 1 + error "Unknown host: $LOCAL_HOSTNAME" fi - declare -A SSH_KEYS + declare -gA SSH_KEYS + SSH_KEYS["$HOST1|$HOST2"]="$HOST1_SSH_KEY" SSH_KEYS["$HOST2|$HOST1"]="$HOST2_SSH_KEY" KEY_ID="$LOCAL_SERVER_NAME|$REMOTE_SERVER_NAME" - SSH_KEY="${SSH_KEYS[$KEY_ID]}" + SSH_KEY="${SSH_KEYS[$KEY_ID]:-}" - if [[ -z "$SSH_KEY" ]]; then - error "No SSH key defined for $LOCAL_SERVER_NAME β†’ $REMOTE_SERVER_NAME" - exit 1 - fi + [[ -z "$SSH_KEY" ]] && error "Missing SSH key for $KEY_ID" - info "Local: $LOCAL_SERVER_NAME β†’ Remote: $REMOTE_SERVER_NAME" - log "SSH key: $SSH_KEY" + log "Host mapping: $LOCAL_SERVER_NAME -> $REMOTE_SERVER_NAME" } -# Remote IP +# REMOTE RESOLUTION resolve_remote_ip() { - log "Resolving Tailscale IP for $REMOTE_SERVER_NAME..." + + log "Resolving remote IP..." REMOTE_SERVER=$(tailscale ip -4 "$REMOTE_SERVER_NAME" 2>/dev/null) - if [[ -z "$REMOTE_SERVER" ]]; then - error "Could not resolve Tailscale IP for $REMOTE_SERVER_NAME" - exit 1 - fi + [[ -z "$REMOTE_SERVER" ]] && error "Failed to resolve IP for $REMOTE_SERVER_NAME" - info "Remote IP: $REMOTE_SERVER" + log "Remote IP: $REMOTE_SERVER" } -# Connectivity check_remote_online() { - log "Pinging $REMOTE_SERVER..." ping -c 1 "$REMOTE_SERVER" &>/dev/null } -# Containers -declare -a RUNNING_CONTAINERS=() +# SAFE SSH WRAPPER +ssh_exec() { + ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "$@" +} + +# CONTAINER CONTROL +RUNNING_CONTAINERS=() stop_containers() { - if [[ ${#CRITICAL_CONTAINER_NAMES[@]} -eq 0 ]]; then - log "No containers defined to stop" - return - fi - info "Stopping containers on $REMOTE_SERVER_NAME..." + [[ ${#CRITICAL_CONTAINER_NAMES[@]:-0} -eq 0 ]] && return + RUNNING_CONTAINERS=() for container in "${CRITICAL_CONTAINER_NAMES[@]}"; do - log "Checking container: $container" - STATUS=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ - "docker inspect -f '{{.State.Running}}' $container 2>/dev/null" || echo "false") + STATUS=$(ssh_exec "docker inspect -f '{{.State.Running}}' $container 2>/dev/null" || echo "false") if [[ "$STATUS" == "true" ]]; then info "Stopping $container" RUNNING_CONTAINERS+=("$container") - ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker stop $container" - else - log "$container already stopped" + ssh_exec "docker stop $container" || warn "Failed to stop $container" fi done } start_containers() { - if [[ ${#RUNNING_CONTAINERS[@]} -eq 0 ]]; then - log "No containers to restart" - return - fi - info "Starting containers on $REMOTE_SERVER_NAME..." + [[ ${#RUNNING_CONTAINERS[@]} -eq 0 ]] && return for container in "${RUNNING_CONTAINERS[@]}"; do - if [[ " ${DELAYED_CONTAINERS[*]} " == *" $container "* ]]; then - info "Delaying $container (${CONTAINER_DELAY}s)" + + if [[ " ${DELAYED_CONTAINERS[*]:-} " == *" $container "* ]]; then + info "Delaying $container ($CONTAINER_DELAY s)" sleep "$CONTAINER_DELAY" fi info "Starting $container" - ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker start $container" + ssh_exec "docker start $container" || warn "Failed to start $container" done } -# Rsync Options +# RSYNC OPTS get_rsync_opts() { + if [[ -n "${PROFILE_RSYNC_OPTS[$PROFILE_NAME]:-}" ]]; then - read -r -a RSYNC_OPTS <<< "${PROFILE_RSYNC_OPTS[$PROFILE_NAME]}" - log "Using profile rsync options: ${PROFILE_RSYNC_OPTS[$PROFILE_NAME]}" + IFS=' ' read -r -a RSYNC_OPTS <<< "${PROFILE_RSYNC_OPTS[$PROFILE_NAME]}" + log "Using profile rsync opts" else - RSYNC_OPTS=("${DEFAULT_RSYNC_OPTS[@]}") - log "Using default rsync options: ${DEFAULT_RSYNC_OPTS[*]}" + RSYNC_OPTS=("${DEFAULT_RSYNC_OPTS[@]:-}") + log "Using default rsync opts" fi } -# Status Output +# STATUS OUTPUT show_status() { - echo "===== RSYNC STATUS =====" - echo "Local: $LOCAL_SERVER_NAME" - echo "Remote: $REMOTE_SERVER_NAME" - echo "Remote IP: $REMOTE_SERVER" - echo "SSH Key: $SSH_KEY" + echo - echo "Directory: $DIRECTORY" - echo "Profile: $PROFILE_NAME" - echo - echo "Max Procs: $MAX_RSYNC_PROCS" - echo "Bandwidth: $BW_LIMIT KB/s" - echo "Retries: $RETRY_COUNT" - echo "Sleep: $SLEEP" - echo "Dry Run: $DRY_RUN" - echo - echo "Containers: ${CRITICAL_CONTAINER_NAMES[*]:-(none)}" - echo "Delayed: ${DELAYED_CONTAINERS[*]:-(none)}" - echo - echo "Excludes: ${EXCLUDE_DIRS[*]:-(none)}" - echo - echo "Rsync Opts:" - printf ' %s\n' "${RSYNC_OPTS[@]}" - echo "=========================" + echo "==================================================" + echo " RSYNC OPS STATUS" + echo "--------------------------------------------------" + echo " Local: $LOCAL_SERVER_NAME" + echo " Remote: $REMOTE_SERVER_NAME" + echo " IP: ${REMOTE_SERVER:-unset}" + echo " Dry Run: $DRY_RUN" + echo " Logging: $ENABLE_LOGGING" + echo " Profile: ${PROFILE_NAME:-default}" + echo "==================================================" } \ No newline at end of file diff --git a/unRAID Essentials/clear_logs.sh b/unRAID Essentials/clear_logs.sh index 89d4d6a..29733fa 100644 --- a/unRAID Essentials/clear_logs.sh +++ b/unRAID Essentials/clear_logs.sh @@ -5,74 +5,118 @@ set -e # ---------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" -# Load central config -load_master_conf - -# Parse CLI args (supports --dry-run) parse_args "$@" -# Colors for output -RED="\033[0;31m" -GREEN="\033[0;32m" -YELLOW="\033[1;33m" -RESET="\033[0m" - -# Log files to clear (can also be overridden in Master.conf) -LOG_FILES=("${LOG_FILES[@]:-/var/log/syslog /var/log/messages /var/log/dmesg}") - -# Require root -if [ "$EUID" -ne 0 ]; then - printf "${RED}❌ Please run as root.${RESET}\n" - exit 1 +# STATUS MODE +if [[ "$SHOW_STATUS" == true ]]; then + echo + echo "==================================================" + echo " ℹ️ LOG CLEANER STATUS" + echo "--------------------------------------------------" + echo " πŸ“„ System Logs: ${LOG_FILES[*]}" + echo " 🐳 Docker Logs: /var/lib/docker/containers" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + echo "==================================================" + exit 0 fi -echo -e "${YELLOW}Starting log cleanup...${RESET}\n" +# CONFIG +LOG_FILES=("${LOG_FILES[@]:-/var/log/syslog /var/log/messages /var/log/dmesg}") -# Functions +# ROOT CHECK +if [[ "$EUID" -ne 0 ]]; then + error "πŸ”΄ Must be run as root" +fi + +# HEADER +echo +echo "============================================================" +echo " πŸš€ LOG CLEANER STARTING" +echo "------------------------------------------------------------" +echo " πŸ“„ System Logs: ${LOG_FILES[*]}" +echo " 🐳 Docker Logs: enabled" +echo " πŸ§ͺ Dry Run: $DRY_RUN" +echo "============================================================" + +log "ℹ️ Starting log cleanup" + +# FUNCTIONS clear_file() { local file="$1" - if [ ! -f "$file" ]; then - printf "${RED}Not found:${RESET} %s\n" "$file" + + if [[ ! -f "$file" ]]; then + warn "🟑 Not found: $file" return fi - if [ "$DRY_RUN" = true ]; then - printf "${YELLOW}Would clear:${RESET} %s\n" "$file" + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would clear: $file" else : > "$file" - printf "${GREEN}Cleared:${RESET} %s\n" "$file" + info "🟒 Cleared: $file" fi } clear_docker_logs() { - if [ ! -d /var/lib/docker/containers ]; then - printf "${RED}Docker containers directory not found. Skipping Docker log cleanup.${RESET}\n" + + if [[ ! -d /var/lib/docker/containers ]]; then + warn "🟑 Docker directory not found β€” skipping" return fi local files - files=$(find /var/lib/docker/containers/ -name "*-json.log" 2>/dev/null) + files=$(find /var/lib/docker/containers/ -name "*-json.log" 2>/dev/null || true) + + if [[ -z "$files" ]]; then + warn "🟑 No Docker logs found" + return + fi + for file in $files; do - if [ "$DRY_RUN" = true ]; then - printf "${YELLOW}Would clear Docker log:${RESET} %s\n" "$file" + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would clear Docker log: $file" else : > "$file" - printf "${GREEN}Cleared Docker log:${RESET} %s\n" "$file" + info "🟒 Cleared Docker log: $file" fi done } -# MAIN +# EXECUTION +START_TIME=$(date +%s) + for log in "${LOG_FILES[@]}"; do clear_file "$log" done clear_docker_logs -if [ "$DRY_RUN" = true ]; then - printf "\n${YELLOW}πŸ§ͺ Dry run complete. No files were cleared.${RESET}\n" +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +# SUMMARY +echo +echo "============================================================" + +if [[ "$DRY_RUN" == true ]]; then + echo " 🟑 LOG CLEANER SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ“„ Logs: ${LOG_FILES[*]}" + echo " 🐳 Docker: skipped (dry run)" + echo " πŸ“‘ Status: 🟑 DRY RUN" else - printf "\n${GREEN}πŸŽ‰ Done clearing logs.${RESET}\n" -fi \ No newline at end of file + echo " 🟒 LOG CLEANER SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ“„ Logs: ${LOG_FILES[*]}" + echo " 🐳 Docker: cleaned" + echo " ⏱ Duration: ${DURATION}s" + echo " πŸ“‘ Status: 🟒 SUCCESS" +fi + +echo "============================================================" + +info "ℹ️ Log cleanup complete" \ No newline at end of file diff --git a/unRAID Essentials/docker_syslog_filter.sh b/unRAID Essentials/docker_syslog_filter.sh index 4deffac..69d9795 100644 --- a/unRAID Essentials/docker_syslog_filter.sh +++ b/unRAID Essentials/docker_syslog_filter.sh @@ -18,50 +18,108 @@ set -e # ---------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" -# Load central config -load_master_conf - -# Parse CLI args (supports --dry-run) parse_args "$@" -# Filter file location (can also be overridden in Master.conf) -FILTER_FILE=${FILTER_FILE:-"/etc/rsyslog.d/ignore-docker-veth.conf"} - -# Require root -if [ "$EUID" -ne 0 ]; then - echo -e "\033[0;31m❌ Please run as root.${RESET}\n" - exit 1 +# STATUS MODE +if [[ "$SHOW_STATUS" == true ]]; then + echo + echo "==================================================" + echo " ℹ️ SYSLOG FILTER STATUS" + echo "--------------------------------------------------" + echo " πŸ“„ Filter File: ${FILTER_FILE:-/etc/rsyslog.d/ignore-docker-veth.conf}" + echo " 🐳 Targets: veth, docker0" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + echo "==================================================" + exit 0 fi -# Functions +# CONFIG +FILTER_FILE=${FILTER_FILE:-"/etc/rsyslog.d/ignore-docker-veth.conf"} + +# ROOT CHECK +if [[ "$EUID" -ne 0 ]]; then + error "πŸ”΄ Must be run as root" +fi + +# HEADER +echo +echo "============================================================" +echo " πŸš€ SYSLOG FILTER STARTING" +echo "------------------------------------------------------------" +echo " πŸ“„ Filter File: $FILTER_FILE" +echo " 🐳 Targets: veth / docker0" +echo " πŸ§ͺ Dry Run: $DRY_RUN" +echo "============================================================" + +log "ℹ️ Applying rsyslog docker noise filter" + +# FUNCTIONS create_filter() { - if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would create rsyslog filter file at $FILTER_FILE" - else - echo "Creating rsyslog filter file at $FILTER_FILE" - cat <<'EOF' > "$FILTER_FILE" + + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would create filter file: $FILTER_FILE" + return + fi + + info "🟑 Creating rsyslog filter file" + + cat <<'EOF' > "$FILTER_FILE" if ($msg contains "veth" or $msg contains "docker0") then { stop } EOF - fi + + info "🟒 Filter file written" } restart_rsyslog() { - if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would restart rsyslog: /etc/rc.d/rc.rsyslogd restart" + + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would restart rsyslog service" + return + fi + + info "🟑 Restarting rsyslog service" + + if /etc/rc.d/rc.rsyslogd restart; then + info "🟒 rsyslog restarted successfully" else - echo "Restarting rsyslog..." - /etc/rc.d/rc.rsyslogd restart + error "πŸ”΄ Failed to restart rsyslog" fi } -# MAIN -echo "==== Docker Syslog Filter Script Started: $(date) ====" +# EXECUTION +START_TIME=$(date +%s) create_filter restart_rsyslog -echo "βœ… Docker veth/docker0 syslog filter applied." \ No newline at end of file +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +# SUMMARY +echo +echo "============================================================" + +if [[ "$DRY_RUN" == true ]]; then + echo " 🟑 SYSLOG FILTER SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ“„ Filter File: $FILTER_FILE" + echo " 🐳 Targets: veth / docker0" + echo " πŸ“‘ Status: 🟑 DRY RUN" +else + echo " 🟒 SYSLOG FILTER SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ“„ Filter File: $FILTER_FILE" + echo " 🐳 Targets: veth / docker0" + echo " ⏱ Duration: ${DURATION}s" + echo " πŸ“‘ Status: 🟒 SUCCESS" +fi + +echo "============================================================" + +info "ℹ️ Syslog filter operation complete" \ No newline at end of file diff --git a/unRAID Essentials/mover-stop.sh b/unRAID Essentials/mover-stop.sh index bce232f..4f2f9ef 100644 --- a/unRAID Essentials/mover-stop.sh +++ b/unRAID Essentials/mover-stop.sh @@ -18,47 +18,102 @@ set -e # ---------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" -# Load central config -load_master_conf - -# Parse CLI args (flags + VAR=value) parse_args "$@" -# Optional: MOVER_STOP_TIMEOUT in seconds (default from Master.conf or 30s) +# CONFIG MOVER_STOP_TIMEOUT=${MOVER_STOP_TIMEOUT:-30} validate_int MOVER_STOP_TIMEOUT "$MOVER_STOP_TIMEOUT" -# Functions +# STATUS MODE +if [[ "$SHOW_STATUS" == true ]]; then + echo + echo "==================================================" + echo " ℹ️ MOVER STOP STATUS" + echo "--------------------------------------------------" + echo " ⏱ Timeout: ${MOVER_STOP_TIMEOUT}s" + echo " πŸ“‘ Dry Run: $DRY_RUN" + echo "==================================================" + exit 0 +fi -notify_users() { - wall "⚠️ Unraid Mover will stop in ${MOVER_STOP_TIMEOUT} second(s)." -} +# HEADER +echo +echo "============================================================" +echo " πŸš€ MOVER STOP STARTING" +echo "------------------------------------------------------------" +echo " ⏱ Timeout: ${MOVER_STOP_TIMEOUT}s" +echo " πŸ§ͺ Dry Run: $DRY_RUN" +echo "============================================================" +log "ℹ️ Checking mover status" + +# FUNCTIONS check_mover_running() { pgrep -f "emhttp.*Mover" >/dev/null 2>&1 } +notify_users() { + warn "🟑 Notifying users: mover stopping soon" + wall "⚠️ Unraid Mover will stop in ${MOVER_STOP_TIMEOUT} second(s)." +} + stop_mover() { - if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would stop the Mover process" + + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would stop Unraid Mover process" + return + fi + + info "🟑 Stopping Unraid Mover process" + + if pkill -f "emhttp.*Mover"; then + info "🟒 Mover stopped successfully" else - echo "Stopping Mover..." - # Unraid native way: kill the mover process gracefully - pkill -f "emhttp.*Mover" + warn "πŸ”΄ Failed to stop mover (may not be running)" fi } -# MAIN - -echo "==== Mover Stop Script Started: $(date) ====" +# EXECUTION +START_TIME=$(date +%s) if check_mover_running; then + info "🟑 Mover is running" + notify_users + + info "⏱ Waiting ${MOVER_STOP_TIMEOUT}s before stopping" sleep "$MOVER_STOP_TIMEOUT" + stop_mover - echo "Mover stopped." + else - echo "Mover is not running." -fi \ No newline at end of file + info "🟒 Mover is not running" +fi + +# FINALIZE +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +# SUMMARY +echo +echo "============================================================" + +if check_mover_running; then + echo " 🟑 MOVER STOP SUMMARY" + echo "------------------------------------------------------------" + echo " ⏱ Duration: ${DURATION}s" + echo " πŸ“‘ Status: 🟑 STILL RUNNING OR UNCERTAIN" +else + echo " 🟒 MOVER STOP SUMMARY" + echo "------------------------------------------------------------" + echo " ⏱ Duration: ${DURATION}s" + echo " πŸ“‘ Status: 🟒 STOPPED / NOT RUNNING" +fi + +echo "============================================================" + +info "ℹ️ Mover stop operation complete" \ No newline at end of file diff --git a/unRAID Essentials/php_fpm_max_children.sh b/unRAID Essentials/php_fpm_max_children.sh index 4a39f3b..6e322ef 100644 --- a/unRAID Essentials/php_fpm_max_children.sh +++ b/unRAID Essentials/php_fpm_max_children.sh @@ -18,45 +18,118 @@ set -e # ---------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" -# Load central config -load_master_conf - -# Parse CLI args (supports --dry-run) parse_args "$@" -# Require root -if [ "$EUID" -ne 0 ]; then - echo -e "\033[0;31m❌ Please run as root.${RESET}\n" - exit 1 +# STATUS MODE +if [[ "$SHOW_STATUS" == true ]]; then + echo + echo "==================================================" + echo " ℹ️ PHP-FPM CONFIG STATUS" + echo "--------------------------------------------------" + echo " βš™οΈ PHP_CONF: $PHP_CONF" + echo " πŸ‘₯ Max Children: ${PHP_MAX_CHILDREN:-unset}" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + echo "==================================================" + exit 0 fi -validate_int PHP_MAX_CHILDREN "$PHP_MAX_CHILDREN" +# ROOT CHECK +if [[ "$EUID" -ne 0 ]]; then + error "πŸ”΄ Must be run as root" +fi -# Functions +# VALIDATION +validate_int PHP_MAX_CHILDREN "$PHP_MAX_CHILDREN" +require_var PHP_CONF + +# HEADER +echo +echo "============================================================" +echo " πŸš€ PHP-FPM CONFIG UPDATE STARTING" +echo "------------------------------------------------------------" +echo " βš™οΈ Target: $PHP_CONF" +echo " πŸ‘₯ MaxChild: $PHP_MAX_CHILDREN" +echo " πŸ§ͺ Dry Run: $DRY_RUN" +echo "============================================================" + +log "ℹ️ Starting PHP-FPM configuration update" + +# FUNCTIONS apply_php_max_children() { + local target="pm.max_children = $PHP_MAX_CHILDREN" - if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would set PHP-FPM max_children to $PHP_MAX_CHILDREN in $PHP_CONF" - echo "[DRY-RUN] Would restart PHP-FPM service" + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would set pm.max_children = $PHP_MAX_CHILDREN" + warn "πŸ§ͺ Would restart PHP-FPM service" + return + fi + + info "🟑 Applying PHP-FPM configuration" + + if [[ ! -f "$PHP_CONF" ]]; then + error "πŸ”΄ PHP config file not found: $PHP_CONF" + fi + + # Apply config safely + if sed -i "s/^pm\.max_children.*/$target/" "$PHP_CONF"; then + info "🟒 Config updated successfully" else - echo "Applying persistent PHP-FPM max_children = $PHP_MAX_CHILDREN" - sed -i "s/^pm\.max_children.*/$target/" "$PHP_CONF" + error "πŸ”΄ Failed to update PHP config" + fi - # Restart PHP-FPM - /etc/rc.d/rc.php-fpm restart + # Restart service + info "🟑 Restarting PHP-FPM" - local current - current=$(grep -E "^pm\.max_children" "$PHP_CONF") - logger "Userscript: php-fpm setting applied: $current" + if /etc/rc.d/rc.php-fpm restart; then + info "🟒 PHP-FPM restarted successfully" + else + error "πŸ”΄ PHP-FPM restart failed" + fi - echo "PHP-FPM max_children persistently set to: $current" - echo "PHP-FPM restarted successfully." + # Verify applied value + local current + current=$(grep -E "^pm\.max_children" "$PHP_CONF" || true) + + if [[ -n "$current" ]]; then + info "🟒 Verified: $current" + logger "Userscript: PHP-FPM updated -> $current" + else + warn "🟑 Could not verify configuration value" fi } -# MAIN -echo "==== PHP-FPM Max Children Script Started: $(date) ====" -apply_php_max_children \ No newline at end of file +# EXECUTION +START_TIME=$(date +%s) + +apply_php_max_children + +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +# SUMMARY +echo +echo "============================================================" + +if [[ "$DRY_RUN" == true ]]; then + echo " 🟑 PHP-FPM SUMMARY" + echo "------------------------------------------------------------" + echo " βš™οΈ Target: $PHP_CONF" + echo " πŸ‘₯ MaxChild: $PHP_MAX_CHILDREN" + echo " πŸ“‘ Status: 🟑 DRY RUN" +else + echo " 🟒 PHP-FPM SUMMARY" + echo "------------------------------------------------------------" + echo " βš™οΈ Target: $PHP_CONF" + echo " πŸ‘₯ MaxChild: $PHP_MAX_CHILDREN" + echo " ⏱ Duration: ${DURATION}s" + echo " πŸ“‘ Status: 🟒 SUCCESS" +fi + +echo "============================================================" + +info "ℹ️ PHP-FPM configuration update complete" \ No newline at end of file diff --git a/unRAID Essentials/rsync_stop.sh b/unRAID Essentials/rsync_stop.sh index 6117e25..39ccec4 100644 --- a/unRAID Essentials/rsync_stop.sh +++ b/unRAID Essentials/rsync_stop.sh @@ -5,30 +5,89 @@ set -e # ---------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" -# Load central config -load_master_conf - -# Parse CLI args (supports --dry-run) parse_args "$@" -# Functions +# STATUS MODE +if [[ "$SHOW_STATUS" == true ]]; then + echo + echo "==================================================" + echo " ℹ️ RSYNC STOP STATUS" + echo "--------------------------------------------------" + echo " πŸ”„ Target: rsync processes" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + echo "==================================================" + exit 0 +fi + +# HEADER +echo +echo "============================================================" +echo " πŸš€ RSYNC STOP STARTING" +echo "------------------------------------------------------------" +echo " πŸ”„ Target: all rsync processes" +echo " πŸ§ͺ Dry Run: $DRY_RUN" +echo "============================================================" + +log "ℹ️ Checking for running rsync processes" + +# FUNCTIONS +check_rsync_running() { + pgrep -f rsync >/dev/null 2>&1 +} stop_rsync_processes() { - if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would stop all running rsync processes" - else - echo "Stopping all rsync processes..." - if pkill -f rsync; then - echo "All rsync processes stopped successfully." + + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would stop all rsync processes" + return + fi + + if check_rsync_running; then + info "🟑 Stopping rsync processes" + + # safer than blind pkill message-only: + pkill -f rsync + + sleep 1 + + if check_rsync_running; then + warn "🟑 Some rsync processes may still be running" else - echo "No rsync processes found or failed to stop." + info "🟒 All rsync processes stopped successfully" fi + else + info "🟒 No rsync processes currently running" fi } -# MAIN -echo "==== Rsync Stop Script Started: $(date) ====" +# EXECUTION +START_TIME=$(date +%s) -stop_rsync_processes \ No newline at end of file +stop_rsync_processes + +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +# SUMMARY +echo +echo "============================================================" + +if check_rsync_running; then + echo " 🟑 RSYNC STOP SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ”„ Status: 🟑 SOME PROCESSES MAY REMAIN" + echo " ⏱ Duration: ${DURATION}s" +else + echo " 🟒 RSYNC STOP SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ”„ Status: 🟒 ALL STOPPED" + echo " ⏱ Duration: ${DURATION}s" +fi + +echo "============================================================" + +info "ℹ️ Rsync stop operation complete" \ No newline at end of file diff --git a/unRAID Essentials/server-reboot.sh b/unRAID Essentials/server-reboot.sh index f8e8ec4..b9704c4 100644 --- a/unRAID Essentials/server-reboot.sh +++ b/unRAID Essentials/server-reboot.sh @@ -18,63 +18,135 @@ set -e # ---------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" -# Load central config -load_master_conf - -# Parse CLI args (flags + VAR=value) parse_args "$@" -# Validate REBOOT_SLEEP +# STATUS MODE +if [[ "$SHOW_STATUS" == true ]]; then + echo + echo "==================================================" + echo " ℹ️ REBOOT STATUS" + echo "--------------------------------------------------" + echo " ⏱ Delay: ${REBOOT_SLEEP:-0}s" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + echo "==================================================" + exit 0 +fi + +# CONFIG validate_int REBOOT_SLEEP "$REBOOT_SLEEP" -# --- Functions +# HEADER +echo +echo "============================================================" +echo " πŸš€ UNRAID REBOOT SEQUENCE STARTING" +echo "------------------------------------------------------------" +echo " ⏱ Delay: ${REBOOT_SLEEP}s" +echo " πŸ§ͺ Dry Run: $DRY_RUN" +echo "============================================================" + +log "ℹ️ Reboot sequence initiated" + +# FUNCTIONS notify_users() { + warn "🟑 Notifying users of reboot" wall "⚠️ Unraid server will reboot in ${REBOOT_SLEEP} second(s). Save your work." } -# --- MAIN -echo "==== Scheduled Reboot Script Started: $(date) ====" +stop_docker() { + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would stop Docker service" + return + fi -# Optional warning before reboot -if [ "$REBOOT_SLEEP" -gt 0 ]; then - notify_users - sleep "$REBOOT_SLEEP" + info "🟑 Stopping Docker service" + if /etc/rc.d/rc.docker stop; then + info "🟒 Docker stopped" + else + warn "πŸ”΄ Docker stop failed or already stopped" + fi +} +stop_vm_manager() { + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would stop VM Manager (libvirt)" + return + fi - -fi + info "🟑 Stopping VM Manager" -# Stop Docker -if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would stop Docker: /etc/rc.d/rc.docker stop" -else - echo "Stopping Docker..." - /etc/rc.d/rc.docker stop -fi + if /etc/rc.d/rc.libvirt stop; then + info "🟒 VM Manager stopped" + else + warn "πŸ”΄ VM Manager stop failed or already stopped" + fi +} -# Stop VM Manager -if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would stop VM Manager: /etc/rc.d/rc.libvirt stop" -else - echo "Stopping VM Manager..." - /etc/rc.d/rc.libvirt stop -fi +sync_disks() { + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would sync filesystem buffers" + return + fi -# Sync disks -if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would sync disks" -else - echo "Syncing disks..." - sync -fi + info "🟑 Syncing disks" + + if sync; then + info "🟒 Disk sync complete" + else + warn "πŸ”΄ Sync command returned error" + fi +} + +reboot_system() { + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would reboot system (/sbin/reboot)" + return + fi + + info "πŸ”΄ Rebooting system NOW" -# Reboot system -if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would reboot system: /sbin/reboot" -else - echo "Rebooting system..." /sbin/reboot -fi \ No newline at end of file +} + +# EXECUTION +START_TIME=$(date +%s) + +if [[ "$REBOOT_SLEEP" -gt 0 ]]; then + notify_users + info "⏱ Waiting ${REBOOT_SLEEP}s before shutdown sequence" + sleep "$REBOOT_SLEEP" +fi + +stop_docker +stop_vm_manager +sync_disks + +reboot_system + +# NOTE: system will not reach here unless dry-run +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +# SUMMARY +echo +echo "============================================================" + +if [[ "$DRY_RUN" == true ]]; then + echo " 🟑 REBOOT SUMMARY" + echo "------------------------------------------------------------" + echo " ⏱ Delay: ${REBOOT_SLEEP}s" + echo " πŸ“‘ Status: 🟑 DRY RUN (no reboot executed)" +else + echo " πŸ”΄ REBOOT SUMMARY" + echo "------------------------------------------------------------" + echo " ⚠️ Status: πŸ”΄ SYSTEM SHOULD BE REBOOTING" + echo " ⏱ Duration: ${DURATION}s" +fi + +echo "============================================================" + +info "ℹ️ Reboot sequence complete (or handed off to system reboot)" \ No newline at end of file diff --git a/unRAID Essentials/user_scripts_stop.sh b/unRAID Essentials/user_scripts_stop.sh index 805e96f..c42471e 100644 --- a/unRAID Essentials/user_scripts_stop.sh +++ b/unRAID Essentials/user_scripts_stop.sh @@ -5,39 +5,110 @@ set -e # ---------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" -# Load central config -load_master_conf - -# Parse CLI args (supports --dry-run) parse_args "$@" -# Functions +# STATUS MODE +if [[ "$SHOW_STATUS" == true ]]; then + echo + echo "==================================================" + echo " ℹ️ USER SCRIPTS STATUS" + echo "--------------------------------------------------" + echo " πŸ” Target: /tmp/user.scripts processes" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + echo "==================================================" + exit 0 +fi + +# HEADER +echo +echo "============================================================" +echo " πŸš€ USER SCRIPTS STOP STARTING" +echo "------------------------------------------------------------" +echo " πŸ” Target: User Scripts Plugin processes" +echo " πŸ§ͺ Dry Run: $DRY_RUN" +echo "============================================================" + +log "ℹ️ Scanning for User Scripts processes" + +# FUNCTIONS +get_user_script_pids() { + /usr/bin/ps -eo pid,cmd | grep "/tmp/user.scripts" | grep -v grep | awk '{print $1}' +} stop_user_scripts() { - # Get PIDs of running user scripts - local pids - pids=$(/usr/bin/ps -eo pid,cmd | grep "/tmp/user.scripts" | grep -v grep | awk '{print $1}') - if [ -z "$pids" ]; then - echo "No running user scripts found." + local pids + pids=$(get_user_script_pids) + + if [[ -z "$pids" ]]; then + info "🟒 No running User Scripts found" return fi + local count=0 + for pid in $pids; do - if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would kill user script with PID $pid" + + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would kill User Script PID $pid" else - echo "Killing user script with PID $pid" - kill "$pid" + info "🟑 Killing User Script PID $pid" + + if kill "$pid" 2>/dev/null; then + info "🟒 Killed PID $pid" + else + warn "πŸ”΄ Failed to kill PID $pid (may already be gone)" + fi fi + + count=$((count + 1)) done - echo "All user scripts stopped." + if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Would stop $count User Script process(es)" + else + info "🟒 Process cleanup complete ($count process(es) targeted)" + fi } -# MAIN -echo "==== User Scripts Stop Script Started: $(date) ====" +# EXECUTION +START_TIME=$(date +%s) -stop_user_scripts \ No newline at end of file +stop_user_scripts + +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +# SUMMARY +echo +echo "============================================================" + +if [[ "$DRY_RUN" == true ]]; then + echo " 🟑 USER SCRIPTS SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ” Status: 🟑 DRY RUN (no processes killed)" + echo " ⏱ Duration: ${DURATION}s" +else + local remaining + remaining=$(get_user_script_pids) + + if [[ -z "$remaining" ]]; then + echo " 🟒 USER SCRIPTS SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ” Status: 🟒 ALL PROCESSES STOPPED" + else + echo " 🟑 USER SCRIPTS SUMMARY" + echo "------------------------------------------------------------" + echo " πŸ” Status: 🟑 SOME PROCESSES MAY STILL BE RUNNING" + fi + + echo " ⏱ Duration: ${DURATION}s" +fi + +echo "============================================================" + +info "ℹ️ User Scripts stop operation complete" \ No newline at end of file diff --git a/unRAID Essentials/zfs_memory_snapshot.sh b/unRAID Essentials/zfs_memory_snapshot.sh index b5ed675..7923254 100644 --- a/unRAID Essentials/zfs_memory_snapshot.sh +++ b/unRAID Essentials/zfs_memory_snapshot.sh @@ -6,35 +6,87 @@ set -e # ---------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" -# Load central config -load_master_conf - -# Parse CLI args (supports --dry-run) parse_args "$@" -# Functions +# STATUS MODE +if [[ "$SHOW_STATUS" == true ]]; then + echo + echo "==================================================" + echo " ℹ️ ZFS + MEMORY SNAPSHOT STATUS" + echo "--------------------------------------------------" + echo " πŸ“Š Mode: Read-only diagnostics" + echo " πŸ§ͺ Dry Run: $DRY_RUN" + echo "==================================================" + exit 0 +fi + +# HEADER +echo +echo "============================================================" +echo " πŸ“Š ZFS ARC + MEMORY SNAPSHOT" +echo "------------------------------------------------------------" +echo " πŸ•’ Time: $(date)" +echo " πŸ§ͺ Dry Run: $DRY_RUN" +echo "============================================================" + +log "ℹ️ Collecting ZFS ARC + memory statistics" + +# FUNCTIONS show_zfs_arc() { - echo "--- ARC / Metadata Stats ---" - grep -iE '^(c|meta|arc_meta_used|demand_metadata_misses|mru_ghost_metadata|mfu_ghost_metadata)' /proc/spl/kstat/zfs/arcstats + + echo + echo "==================== ZFS ARC STATS ====================" + + if [[ ! -r /proc/spl/kstat/zfs/arcstats ]]; then + warn "πŸ”΄ ZFS arcstats not available on this system" + return + fi + + grep -iE '^(c|size|hits|misses|arc_meta_used|demand_metadata_misses|mru_ghost_metadata|mfu_ghost_metadata)' \ + /proc/spl/kstat/zfs/arcstats 2>/dev/null || warn "🟑 Unable to read ARC stats" } show_memory_status() { - echo "--- Memory Status ---" - free -h | awk 'NR==1 || /Mem:/' + + echo + echo "==================== MEMORY STATUS ====================" + + if command -v free >/dev/null 2>&1; then + free -h | awk ' + NR==1 {print $0} + /Mem:/ {print $0} + /Swap:/ {print $0}' + else + warn "πŸ”΄ free command not available" + fi } -# MAIN -echo "===== ZFS ARC & Memory Snapshot: $(date) =====" +# EXECUTION +START_TIME=$(date +%s) -if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would display ARC and memory stats" +if [[ "$DRY_RUN" == true ]]; then + warn "πŸ§ͺ Dry run enabled - no system data collected" else - echo "" show_zfs_arc - echo "" show_memory_status fi -echo "==============================================" \ No newline at end of file +END_TIME=$(date +%s) +DURATION=$((END_TIME - START_TIME)) + +# SUMMARY +echo +echo "============================================================" + +echo " πŸ“Š SNAPSHOT SUMMARY" +echo "------------------------------------------------------------" +echo " ⏱ Duration: ${DURATION}s" +echo " πŸ“‘ Mode: READ-ONLY" +echo " 🧠 Source: ZFS ARC + system memory" +echo "============================================================" + +info "ℹ️ Snapshot complete" \ No newline at end of file