From 9a7a28055f0f36d9dd04611d8dcc93620df10b74 Mon Sep 17 00:00:00 2001 From: FailedProxy Date: Wed, 8 Apr 2026 17:36:58 -0400 Subject: [PATCH] all scripts are now current with common.sh v2.1 --- Master.conf | 2 + Rsync/user_script_pluin.sh | 71 -------- common.sh | 176 ++++++++++++-------- unRAID Essentials/clear_logs.sh | 122 -------------- unRAID Essentials/docker_syslog_filter.sh | 125 -------------- unRAID Essentials/mover-stop.sh | 119 -------------- unRAID Essentials/php_fpm_max_children.sh | 135 --------------- unRAID Essentials/rsync_stop.sh | 109 ------------ unRAID Essentials/server-reboot.sh | 152 ----------------- unRAID Essentials/user_scripts_stop.sh | 114 ------------- unRAID Essentials/zfs_memory_snapshot.sh | 92 ----------- unRAID_Essentials/clear_logs.sh | 129 +++++++++++++++ unRAID_Essentials/docker_syslog_filter.sh | 118 +++++++++++++ unRAID_Essentials/mover-stop.sh | 114 +++++++++++++ unRAID_Essentials/php_fpm_max_children.sh | 131 +++++++++++++++ unRAID_Essentials/rsync_stop.sh | 192 ++++++++++++++++++++++ unRAID_Essentials/server-reboot.sh | 159 ++++++++++++++++++ unRAID_Essentials/user_scripts_stop.sh | 125 ++++++++++++++ unRAID_Essentials/zfs_memory_snapshot.sh | 103 ++++++++++++ user_script_pluin.sh | 173 +++++++++++++++++++ 20 files changed, 1356 insertions(+), 1105 deletions(-) delete mode 100644 Rsync/user_script_pluin.sh delete mode 100644 unRAID Essentials/clear_logs.sh delete mode 100644 unRAID Essentials/docker_syslog_filter.sh delete mode 100644 unRAID Essentials/mover-stop.sh delete mode 100644 unRAID Essentials/php_fpm_max_children.sh delete mode 100644 unRAID Essentials/rsync_stop.sh delete mode 100644 unRAID Essentials/server-reboot.sh delete mode 100644 unRAID Essentials/user_scripts_stop.sh delete mode 100644 unRAID Essentials/zfs_memory_snapshot.sh create mode 100644 unRAID_Essentials/clear_logs.sh create mode 100644 unRAID_Essentials/docker_syslog_filter.sh create mode 100644 unRAID_Essentials/mover-stop.sh create mode 100644 unRAID_Essentials/php_fpm_max_children.sh create mode 100644 unRAID_Essentials/rsync_stop.sh create mode 100644 unRAID_Essentials/server-reboot.sh create mode 100644 unRAID_Essentials/user_scripts_stop.sh create mode 100644 unRAID_Essentials/zfs_memory_snapshot.sh create mode 100644 user_script_pluin.sh diff --git a/Master.conf b/Master.conf index 541ddc3..e1cfe7c 100644 --- a/Master.conf +++ b/Master.conf @@ -69,6 +69,8 @@ ) # ━━━ unRAID Essential Scripts ━━━ +# clear_logs.sh system log file paths + LOG_FILES=(/var/log/syslog /var/log/messages /var/log/dmesg) # unRAID reboot script user warning time (seconds) REBOOT_SLEEP=300 # unRAID mover stop script timeout (seconds) diff --git a/Rsync/user_script_pluin.sh b/Rsync/user_script_pluin.sh deleted file mode 100644 index 86c3589..0000000 --- a/Rsync/user_script_pluin.sh +++ /dev/null @@ -1,71 +0,0 @@ -!/bin/bash -# ---------------------------------------------------------------------------------------------- -# ------------------------------------ Rsync command ------------------------------------------- -# ---------------------------------------------------------------------------------------------- - -/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-test/Arrs/ - -# ---------------------------------------------------------------------------------------------- -# ------------------------------------------- Info --------------------------------------------- -# ---------------------------------------------------------------------------------------------- -# -# These global configuartions can be added as arguments at the end of the script after folder location -# -# Its better to add profile in Master.conf for perm changes -# -# Profiles in Master.conf match the last string of folder location -# -# if a match is made with a list in Master.conf then the associated profile will be used -# If no match is made it defualts to global defualts - - -#----------------------------------------------------------------------------------------------- -#----------------------------- Arguments, add after rsync command ------------------------------ -#----------------------------------------------------------------------------------------------- -# Does a dry run making no changes -# --dry-run -# -# Force logging -# --log) -# -# Force logging to be dissabled -# --no-log -# -# --help -# -# Example = /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-test/Arrs/ --dry-run --no-log -#----------------------------------------------------------------------------------------------- -#----------------- User Variables, Please adjust in Master.cong as needed ---------------------- -#----------------------------------------------------------------------------------------------- -# -# -# Network speed limit (KB/s) -# BW_LIMIT=12500 -# -# Retry logic -# RETRY_COUNT=3 -# -# Sleep between retries (seconds) -# SLEEP=300 -# -# Max number of concurrently running rsync processes -# MAX_RSYNC_PROCS=1 -# -# Container start/stop/restart before and after rsync -# CRITICAL_CONTAINER_NAMES=() -# -# Containers that need delayed before starting -# DELAYED_CONTAINERS=() -# -# Delay in seconds between starting containers, useful for things like Authelia -# CONTAINER_DELAY=5 -# -#----------------------------------------------------------------------------------------------- -#---------------End Of User Variables, Please adjust in Master.cong as needed ------------------ -#----------------------------------------------------------------------------------------------- -# -# Examples -# /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-test/Arrs/ MAX_RSYNC_PROCS=2 -# /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-test/Arrs/ --dry-run MAX_RSYNC_PROCS=2 -# -# Copy and paste into unRAID User Script plugin \ No newline at end of file diff --git a/common.sh b/common.sh index 68f6338..7939641 100644 --- a/common.sh +++ b/common.sh @@ -1,6 +1,8 @@ #!/bin/bash # ----------------------------------------------------------------------------------------------- -# ------------------------- UNRAID OPS COMMON LIBRARY (v1.6) ------------------------------------ +# ----------------- UNRAID OPS COMMON LIBRARY (STABLE FRAMEWORK v1) ---------------------------- +# ----------------------------------------------------------------------------------------------- +# Version: 2.1 # ----------------------------------------------------------------------------------------------- # Changelog: # v1.0 — Initial stable framework @@ -23,24 +25,32 @@ # ICON_NOT_RUNNING changed to ⭕ — distinct from ICON_STOPPED 🔴 # Section dividers updated from --- to ━━━ for cleaner log readability # Summary passed/failed lines use ICON_SUCCESS and ICON_ERROR consistently +# v1.7 — ICON_MOVER added for mover operations +# ICON_CONTAINERS replaces ICON_DOCKER for docker/container operations +# validate_int added — reusable integer validation for any script +# v1.8 — ICON_PHP added for PHP-FPM operations +# v1.9 — ICON_REBOOT added for server reboot operations +# v2.0 — ICON_PLUGIN added for User Scripts plugin operations +# v2.1 — ICON_ZFS and ICON_MEM added for ZFS and memory diagnostics +# Diagnostics icon group added to icon block # ----------------------------------------------------------------------------------------------- - + # ----------------------------------------------------------------------------------------------- # ICONS # Each icon has one job — do not reuse across different contexts. # ----------------------------------------------------------------------------------------------- - + # System / Host ICON_HOST="🖥️" # host detection ICON_NET="🌐" # network / IP resolution ICON_PING="📡" # connectivity check ICON_GEAR="⚙️" # setup section header / profile load - + # Health Checks ICON_DISK="💾" # disk checks ICON_HEALTH="🩺" # rootfs / share health checks ICON_SHIELD="🛡️" # pre-flight section header - + # Containers ICON_CONTAINERS="📦" # container section anchor — paired with action icon for direction ICON_STOP="⛔" # stop command being issued @@ -49,23 +59,33 @@ ICON_START="▶️" # start command being issued ICON_STARTED="💚" # container confirmed started ICON_RUNNING="🟢" # container already running when checked ICON_NOT_RUNNING="⭕" # container already stopped when checked — distinct from ICON_STOPPED - + # Transfer ICON_SYNC="🔄" # transfer section header ICON_RUN="🚀" # sync starting / rsync attempt ICON_RETRY="🔁" # retry attempt ICON_DONE="🏁" # transfer complete - + # Summary ICON_SUMMARY="📋" # summary section header ICON_TIME="⏱️" # duration line - + +# System Operations +ICON_MOVER="🔃" # mover operations +ICON_REBOOT="⚡" # server reboot operations +ICON_PLUGIN="🧩" # user scripts plugin operations +ICON_PHP="👥" # PHP-FPM operations + +# Diagnostics +ICON_ZFS="📊" # ZFS ARC statistics +ICON_MEM="🧠" # memory status + # Output ICON_INFO="ℹ️" ICON_WARN="⚠️" ICON_ERROR="❌" ICON_SUCCESS="✅" - + # ----------------------------------------------------------------------------------------------- # OUTPUT HELPERS # Standardised output functions used across all scripts. @@ -75,11 +95,11 @@ info() { echo "$ICON_INFO [INFO] $*"; } warn() { echo "$ICON_WARN [WARN] $*"; } error() { echo "$ICON_ERROR [ERROR] $*"; } success() { echo "$ICON_SUCCESS [OK] $*"; } - + log() { [[ "${ENABLE_LOGGING:-false}" == true ]] && echo "[LOG] $*" } - + # ----------------------------------------------------------------------------------------------- # DURATION FORMATTER # Converts raw seconds into a human readable string — e.g. 10m53s or 47s @@ -92,7 +112,7 @@ format_duration() { local rem=$((secs % 60)) [[ $mins -gt 0 ]] && echo "${mins}m${rem}s" || echo "${rem}s" } - + # ----------------------------------------------------------------------------------------------- # ARG PARSER # Processes all flags and key=value pairs passed to any script. @@ -105,14 +125,14 @@ parse_args() { ENABLE_LOGGING=${ENABLE_LOGGING:-false} DRY_RUN=${DRY_RUN:-false} SHOW_STATUS=${SHOW_STATUS:-false} - + CLEAN_ARGS=() - + for ARG in "$@"; do if [[ "$ARG" == *=* ]]; then VAR="${ARG%%=*}" VAL="${ARG#*=}" - + case "$VAR" in LOG) [[ "$VAL" == "true" ]] && ENABLE_LOGGING=true @@ -141,10 +161,10 @@ parse_args() { esac fi done - + PARSED_ARGS=("${CLEAN_ARGS[@]}") } - + # ----------------------------------------------------------------------------------------------- # VALIDATION # Checks that a required variable is set and non-empty. @@ -154,7 +174,31 @@ parse_args() { require_var() { [[ -z "${!1:-}" ]] && error "Missing required: $1" && exit 1 } - + +# ----------------------------------------------------------------------------------------------- +# INTEGER VALIDATION +# Checks that a variable contains a valid positive integer. +# Exits with a clear error if the value is missing, empty, or not a number. +# Usage: validate_int VAR_NAME "$VAR_VALUE" +# Example: validate_int MOVER_STOP_TIMEOUT "$MOVER_STOP_TIMEOUT" +# ----------------------------------------------------------------------------------------------- +validate_int() { + local name="$1" + local value="$2" + + if [[ -z "$value" ]]; then + error "$name is not set — check Master.conf" + exit 1 + fi + + if ! [[ "$value" =~ ^[0-9]+$ ]]; then + error "$name must be a positive integer — got: '$value'" + exit 1 + fi + + log "$name validated: $value" +} + # ----------------------------------------------------------------------------------------------- # HOST DETECTION # Determines local and remote server names by comparing hostname against HOST1/HOST2. @@ -163,7 +207,7 @@ require_var() { # ----------------------------------------------------------------------------------------------- detect_hosts() { LOCAL_HOSTNAME="$(hostname)" - + if [[ "$LOCAL_HOSTNAME" == "$HOST1" ]]; then LOCAL_SERVER_NAME="$HOST1" REMOTE_SERVER_NAME="$HOST2" @@ -174,18 +218,18 @@ detect_hosts() { error "Unknown host: $LOCAL_HOSTNAME" exit 1 fi - + declare -A SSH_KEYS SSH_KEYS["$HOST1|$HOST2"]="$HOST1_SSH_KEY" SSH_KEYS["$HOST2|$HOST1"]="$HOST2_SSH_KEY" - + SSH_KEY="${SSH_KEYS[$LOCAL_SERVER_NAME|$REMOTE_SERVER_NAME]}" - + [[ -z "$SSH_KEY" ]] && error "Missing SSH key mapping for $LOCAL_SERVER_NAME → $REMOTE_SERVER_NAME" && exit 1 - + info "$ICON_HOST Host: $LOCAL_SERVER_NAME → $REMOTE_SERVER_NAME" } - + # ----------------------------------------------------------------------------------------------- # REMOTE IP RESOLUTION # Resolves the Tailscale IPv4 address of the remote server. @@ -195,12 +239,12 @@ detect_hosts() { resolve_remote_ip() { log "Resolving remote IP for $REMOTE_SERVER_NAME..." REMOTE_SERVER=$(tailscale ip -4 "$REMOTE_SERVER_NAME" 2>/dev/null) - + [[ -z "$REMOTE_SERVER" ]] && error "Failed to resolve Tailscale IP for $REMOTE_SERVER_NAME" && exit 1 - + info "$ICON_NET Remote IP: $REMOTE_SERVER" } - + # ----------------------------------------------------------------------------------------------- # CONNECTIVITY CHECK # Pings the remote server to confirm it is reachable before starting any transfers. @@ -216,7 +260,7 @@ check_connectivity() { fi info "$ICON_PING $REMOTE_SERVER_NAME is reachable" } - + # ----------------------------------------------------------------------------------------------- # REMOTE ROOTFS SPACE CHECK # Checks the remote server's rootfs usage before any rsync runs. @@ -227,15 +271,15 @@ check_connectivity() { # ----------------------------------------------------------------------------------------------- check_remote_rootfs() { log "Checking remote rootfs usage..." - + REMOTE_USAGE=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ "df / --output=pcent | tail -1 | tr -d ' %'" 2>/dev/null) - + if [[ -z "$REMOTE_USAGE" ]]; then error "Could not retrieve rootfs usage from $REMOTE_SERVER_NAME" exit 1 fi - + if [[ "$REMOTE_USAGE" -ge "${ROOTFS_WARN:-75}" ]]; then echo "" error "$ICON_HEALTH Remote rootfs is ${REMOTE_USAGE}% full — threshold is ${ROOTFS_WARN:-75}%" @@ -244,10 +288,10 @@ check_remote_rootfs() { echo "" exit 1 fi - + info "$ICON_HEALTH Remote rootfs: ${REMOTE_USAGE}% used (threshold: ${ROOTFS_WARN:-75}%)" } - + # ----------------------------------------------------------------------------------------------- # REMOTE SHARE VALIDATION # Verifies that the target directory exists and is not empty on the remote server. @@ -258,12 +302,12 @@ check_remote_rootfs() { # ----------------------------------------------------------------------------------------------- check_remote_share() { local dir="$1" - + log "Checking remote share: $dir..." - + SHARE_EXISTS=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ "[[ -d '$dir' ]] && echo yes || echo no" 2>/dev/null) - + if [[ "$SHARE_EXISTS" != "yes" ]]; then echo "" error "$ICON_HEALTH Remote share does not exist: $dir" @@ -272,10 +316,10 @@ check_remote_share() { echo "" exit 1 fi - + SHARE_EMPTY=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ "[[ -z \"\$(ls -A '$dir' 2>/dev/null)\" ]] && echo yes || echo no" 2>/dev/null) - + if [[ "$SHARE_EMPTY" == "yes" ]]; then echo "" warn "$ICON_HEALTH Remote share exists but is empty: $dir" @@ -284,10 +328,10 @@ check_remote_share() { echo "" exit 1 fi - + info "$ICON_HEALTH Remote share verified: $dir" } - + # ----------------------------------------------------------------------------------------------- # REMOTE DISK CHECK # Verifies that all physical disks backing a share are online and mounted on the remote server. @@ -301,12 +345,12 @@ check_remote_disks() { local dir="$1" local share_name share_name=$(basename "$dir") - + info "$ICON_DISK Checking disks backing $share_name on $REMOTE_SERVER_NAME..." - + DISK_PATHS=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ "ls -d /mnt/disk*/$share_name 2>/dev/null" 2>/dev/null) - + if [[ -z "$DISK_PATHS" ]]; then echo "" error "$ICON_DISK No disks found backing share $share_name on $REMOTE_SERVER_NAME" @@ -315,18 +359,18 @@ check_remote_disks() { echo "" exit 1 fi - + local all_ok=true - + while IFS= read -r disk_share_path; do local disk_mount disk_mount=$(dirname "$disk_share_path") local disk_name disk_name=$(basename "$disk_mount") - + MOUNTED=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ "mountpoint -q '$disk_mount' && echo yes || echo no" 2>/dev/null) - + if [[ "$MOUNTED" == "yes" ]]; then info "$ICON_DISK $disk_name $ICON_RUNNING — $share_name present" else @@ -334,7 +378,7 @@ check_remote_disks() { all_ok=false fi done <<< "$DISK_PATHS" - + if [[ "$all_ok" == false ]]; then echo "" error "One or more disks backing $share_name are offline on $REMOTE_SERVER_NAME" @@ -343,10 +387,10 @@ check_remote_disks() { echo "" exit 1 fi - + success "All disks backing $share_name are online" } - + # ----------------------------------------------------------------------------------------------- # CONTAINER MANAGEMENT — STOP # Stops all containers listed in CRITICAL_CONTAINER_NAMES on the remote server. @@ -355,29 +399,29 @@ check_remote_disks() { # CRITICAL_CONTAINER_NAMES must be a bash array — rsync.sh handles conversion from profile strings. # ----------------------------------------------------------------------------------------------- RUNNING_CONTAINERS=() - + stop_containers() { if [[ ${#CRITICAL_CONTAINER_NAMES[@]} -eq 0 ]] || \ [[ "${CRITICAL_CONTAINER_NAMES[*]}" == "" ]]; then log "No containers configured for this profile, skipping stop." return fi - + info "Stopping containers..." RUNNING_CONTAINERS=() - + for c in "${CRITICAL_CONTAINER_NAMES[@]}"; do [[ -z "$c" ]] && continue - + info "Checking $c..." - + STATUS=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ "docker inspect -f '{{.State.Running}}' $c 2>/dev/null" 2>/dev/null || echo "false") - + if [[ "$STATUS" == "true" ]]; then echo "$ICON_STOP Stopping $c..." RUNNING_CONTAINERS+=("$c") - + if ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker stop $c" >/dev/null; then echo "$ICON_STOPPED $c stopped" else @@ -388,7 +432,7 @@ stop_containers() { fi done } - + # ----------------------------------------------------------------------------------------------- # CONTAINER MANAGEMENT — START # Restarts only the containers that were running before rsync and were stopped by stop_containers. @@ -401,12 +445,12 @@ start_containers() { log "No containers to restart." return fi - + info "Starting containers..." - + for c in "${RUNNING_CONTAINERS[@]}"; do [[ -z "$c" ]] && continue - + local needs_delay=false for d in "${DELAYED_CONTAINERS[@]}"; do if [[ "$c" == "$d" ]]; then @@ -414,12 +458,12 @@ start_containers() { break fi done - + if [[ "$needs_delay" == true ]]; then info "Waiting ${CONTAINER_DELAY}s before starting $c..." sleep "$CONTAINER_DELAY" fi - + echo "$ICON_START Starting $c..." if ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker start $c" >/dev/null; then echo "$ICON_STARTED $c started" @@ -428,7 +472,7 @@ start_containers() { fi done } - + # ----------------------------------------------------------------------------------------------- # RSYNC OPTIONS # Loads rsync options for the current profile from PROFILE_RSYNC_OPTS in Master.conf. @@ -445,11 +489,11 @@ get_rsync_opts() { log "Using default rsync opts: ${RSYNC_OPTS[*]}" fi } - + # ----------------------------------------------------------------------------------------------- # STATUS DISPLAY # Prints a summary of the current runtime configuration. -# Triggered by --status or --summary flag passed to rsync.sh. +# Triggered by --status or --summary flag passed to any script. # Useful for verifying profile resolution and variable state before a live run. # ----------------------------------------------------------------------------------------------- show_status() { diff --git a/unRAID Essentials/clear_logs.sh b/unRAID Essentials/clear_logs.sh deleted file mode 100644 index 29733fa..0000000 --- a/unRAID Essentials/clear_logs.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash -set -e -# ---------------------------------------------------------------------------------------------- -# ------------- Clear Unraid system logs and Docker container logs safely ---------------------- -# ---------------------------------------------------------------------------------------------- - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -source "$SCRIPT_DIR/../Master.conf" -source "$SCRIPT_DIR/../common.sh" - -parse_args "$@" - -# 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 - -# CONFIG -LOG_FILES=("${LOG_FILES[@]:-/var/log/syslog /var/log/messages /var/log/dmesg}") - -# 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 - warn "🟡 Not found: $file" - return - fi - - if [[ "$DRY_RUN" == true ]]; then - warn "🧪 Would clear: $file" - else - : > "$file" - info "🟢 Cleared: $file" - fi -} - -clear_docker_logs() { - - 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 || true) - - if [[ -z "$files" ]]; then - warn "🟡 No Docker logs found" - return - fi - - for file in $files; do - if [[ "$DRY_RUN" == true ]]; then - warn "🧪 Would clear Docker log: $file" - else - : > "$file" - info "🟢 Cleared Docker log: $file" - fi - done -} - -# EXECUTION -START_TIME=$(date +%s) - -for log in "${LOG_FILES[@]}"; do - clear_file "$log" -done - -clear_docker_logs - -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 - 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 deleted file mode 100644 index 69d9795..0000000 --- a/unRAID Essentials/docker_syslog_filter.sh +++ /dev/null @@ -1,125 +0,0 @@ -#!/bin/bash -set -e -# ---------------------------------------------------------------------------------------------- -# ----------- Suppress noisy Docker veth/docker0 syslog messages on Unraid boot ---------------- -# ---------------------------------------------------------------------------------------------- -# ---------------- User Variables, Please adjust in Master.conf as needed ---------------------- -# ---------------------------------------------------------------------------------------------- -# -# User variables can be adjusted in Master.conf -# -# Scripts now just contain runtime logic -# -# This new setup allows for profiles and arguments to use the core script -# Use arguments in unRAID User Plugin for directory -# Example: /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh --dry-run -# ---------------------------------------------------------------------------------------------- -# -------------- End Of User Variables, Please adjust in Master.conf as needed ----------------- -# ---------------------------------------------------------------------------------------------- - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -source "$SCRIPT_DIR/../Master.conf" -source "$SCRIPT_DIR/../common.sh" - -parse_args "$@" - -# 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 - -# 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 - 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 - - info "🟢 Filter file written" -} - -restart_rsyslog() { - - 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 - error "🔴 Failed to restart rsyslog" - fi -} - -# EXECUTION -START_TIME=$(date +%s) - -create_filter -restart_rsyslog - -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 deleted file mode 100644 index 4f2f9ef..0000000 --- a/unRAID Essentials/mover-stop.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash -set -e -# ---------------------------------------------------------------------------------------------- -# --------------------------- Mover Stop Script for Unraid ------------------------------------- -# ---------------------------------------------------------------------------------------------- -# ---------------- User Variables, Please adjust in Master.conf as needed ---------------------- -# ---------------------------------------------------------------------------------------------- -# -# User variables can be adjusted in Master.conf -# -# Scripts now just contain runtime logic -# -# This new setup allows for profiles and arguments to use the core script -# Use arguments in unRAID User Plugin for directory -# Example: /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh --dry-run -# ---------------------------------------------------------------------------------------------- -# -------------- End Of User Variables, Please adjust in Master.conf as needed ----------------- -# ---------------------------------------------------------------------------------------------- - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -source "$SCRIPT_DIR/../Master.conf" -source "$SCRIPT_DIR/../common.sh" - -parse_args "$@" - -# CONFIG -MOVER_STOP_TIMEOUT=${MOVER_STOP_TIMEOUT:-30} -validate_int MOVER_STOP_TIMEOUT "$MOVER_STOP_TIMEOUT" - -# 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 - -# 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 - warn "🧪 Would stop Unraid Mover process" - return - fi - - info "🟡 Stopping Unraid Mover process" - - if pkill -f "emhttp.*Mover"; then - info "🟢 Mover stopped successfully" - else - warn "🔴 Failed to stop mover (may not be running)" - fi -} - -# 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 - -else - 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 deleted file mode 100644 index 6e322ef..0000000 --- a/unRAID Essentials/php_fpm_max_children.sh +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/bash -set -e -# ---------------------------------------------------------------------------------------------- -# ------------------ Persistently set PHP-FPM pm.max_children on Unraid ------------------------ -# ---------------------------------------------------------------------------------------------- -# ---------------- User Variables, Please adjust in Master.conf as needed ---------------------- -# ---------------------------------------------------------------------------------------------- -# -# User variables can be adjusted in Master.conf -# -# Scripts now just contain runtime logic -# -# This new setup allows for profiles and arguments to use the core script -# Use arguments in unRAID User Plugin for directory -# Example: /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh --dry-run -# ---------------------------------------------------------------------------------------------- -# -------------- End Of User Variables, Please adjust in Master.conf as needed ----------------- -# ---------------------------------------------------------------------------------------------- - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -source "$SCRIPT_DIR/../Master.conf" -source "$SCRIPT_DIR/../common.sh" - -parse_args "$@" - -# 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 - -# ROOT CHECK -if [[ "$EUID" -ne 0 ]]; then - error "🔴 Must be run as root" -fi - -# 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 - 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 - error "🔴 Failed to update PHP config" - fi - - # Restart service - info "🟡 Restarting PHP-FPM" - - if /etc/rc.d/rc.php-fpm restart; then - info "🟢 PHP-FPM restarted successfully" - else - error "🔴 PHP-FPM restart failed" - fi - - # 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 -} - -# 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 deleted file mode 100644 index 5b2551f..0000000 --- a/unRAID Essentials/rsync_stop.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/bash -set -e -# ---------------------------------------------------------------------------------------------- -# ------------------------ Stop all running Rsync processes for Unraid ------------------------- -# ---------------------------------------------------------------------------------------------- - - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -source "$SCRIPT_DIR/../Master.conf" -source "$SCRIPT_DIR/../common.sh" - -# ----------------------------- INIT ----------------------------- - -parse_args "$@" - -require_var "HOST1" -require_var "HOST2" - -detect_hosts -resolve_remote_ip - -# ----------------------------- POSITIONAL MAP ----------------------------- - -SOURCE="${POSITIONAL_ARGS[0]:-}" -DEST="${POSITIONAL_ARGS[1]:-}" - -# ----------------------------- STATUS MODE ----------------------------- - -if [[ "$SHOW_STATUS" == true ]]; then - show_status - exit 0 -fi - -# ----------------------------- HEADER ----------------------------- - -ui_header "RSYNC OPERATION" - -ui_section "Context" -ui_kv "Source" "$SOURCE" -ui_kv "Destination" "$DEST" -ui_kv "Remote" "$REMOTE_SERVER_NAME" -ui_kv "IP" "$REMOTE_SERVER" -ui_kv "Dry Run" "$DRY_RUN" - -# ----------------------------- VALIDATION ----------------------------- - -if [[ -z "$SOURCE" ]]; then - echo_error "Missing SOURCE argument" - exit 1 -fi - -if [[ -z "$DEST" ]]; then - echo_error "Missing DEST argument" - exit 1 -fi - -ui_status ok "Validation passed" - -# ----------------------------- MIRROR MODE ----------------------------- - -if [[ "$SOURCE" == "$DEST" ]]; then - echo - echo "[INFO] Mirror mode detected (identical paths)" - echo "[INFO] Treating as cross-host sync of same structure" - log "Mirror mode active" -fi - -# ----------------------------- PRECHECK ----------------------------- - -if ! check_remote_online; then - echo_error "Remote host offline" - exit 1 -fi - -echo "[OK] Remote reachable" - -# ----------------------------- CONTAINERS ----------------------------- - -stop_containers - -# ----------------------------- RSYNC EXECUTION ----------------------------- - -get_rsync_opts - -RSYNC_CMD=( - rsync - "${RSYNC_OPTS[@]}" - "$SOURCE" - root@"$REMOTE_SERVER":"$DEST" -) - -if [[ "$DRY_RUN" == true ]]; then - RSYNC_CMD+=("--dry-run") -fi - -ui_section "Execution" -echo "[RUN] Starting rsync..." -log "CMD: ${RSYNC_CMD[*]}" - -"${RSYNC_CMD[@]}" - -# ----------------------------- RECOVERY ----------------------------- - -start_containers - -# ----------------------------- END ----------------------------- - -ui_footer "RSYNC COMPLETE" \ No newline at end of file diff --git a/unRAID Essentials/server-reboot.sh b/unRAID Essentials/server-reboot.sh deleted file mode 100644 index b9704c4..0000000 --- a/unRAID Essentials/server-reboot.sh +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/bash -set -e -# ---------------------------------------------------------------------------------------------- -# ---------------------------- Unattended Reboot Script for Unraid ----------------------------- -# ---------------------------------------------------------------------------------------------- -# ---------------- User Variables, Please adjust in Master.conf as needed ---------------------- -# ---------------------------------------------------------------------------------------------- -# -# User variables can be adjusted in Master.conf -# -# Scripts now just contain runtime logic -# -# This new setup allows for profiles and arguments to use the core script -# Use arguments in unRAID User Plugin for directory -# Example: /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh --dry-run -# ---------------------------------------------------------------------------------------------- -# -------------- End Of User Variables, Please adjust in Master.conf as needed ----------------- -# ---------------------------------------------------------------------------------------------- - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -source "$SCRIPT_DIR/../Master.conf" -source "$SCRIPT_DIR/../common.sh" - -parse_args "$@" - -# 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" - -# 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." -} - -stop_docker() { - if [[ "$DRY_RUN" == true ]]; then - warn "🧪 Would stop Docker service" - return - fi - - 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 - - info "🟡 Stopping VM Manager" - - if /etc/rc.d/rc.libvirt stop; then - info "🟢 VM Manager stopped" - else - warn "🔴 VM Manager stop failed or already stopped" - fi -} - -sync_disks() { - if [[ "$DRY_RUN" == true ]]; then - warn "🧪 Would sync filesystem buffers" - return - 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" - - /sbin/reboot -} - -# 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 deleted file mode 100644 index c42471e..0000000 --- a/unRAID Essentials/user_scripts_stop.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/bash -set -e -# ---------------------------------------------------------------------------------------------- -# ----------------- Stop all running User Scripts spawned by the User Scripts plugin ----------- -# ---------------------------------------------------------------------------------------------- - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -source "$SCRIPT_DIR/../Master.conf" -source "$SCRIPT_DIR/../common.sh" - -parse_args "$@" - -# 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() { - - 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 - warn "🧪 Would kill User Script PID $pid" - else - 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 - - if [[ "$DRY_RUN" == true ]]; then - warn "🧪 Would stop $count User Script process(es)" - else - info "🟢 Process cleanup complete ($count process(es) targeted)" - fi -} - -# EXECUTION -START_TIME=$(date +%s) - -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 deleted file mode 100644 index 7923254..0000000 --- a/unRAID Essentials/zfs_memory_snapshot.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash -set -e - -# ---------------------------------------------------------------------------------------------- -# --------------------------- ZFS ARC & Memory Snapshot for Unraid ----------------------------- -# ---------------------------------------------------------------------------------------------- - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -source "$SCRIPT_DIR/../Master.conf" -source "$SCRIPT_DIR/../common.sh" - -parse_args "$@" - -# 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 - 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 - 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 -} - -# EXECUTION -START_TIME=$(date +%s) - -if [[ "$DRY_RUN" == true ]]; then - warn "🧪 Dry run enabled - no system data collected" -else - show_zfs_arc - show_memory_status -fi - -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 diff --git a/unRAID_Essentials/clear_logs.sh b/unRAID_Essentials/clear_logs.sh new file mode 100644 index 0000000..39981f1 --- /dev/null +++ b/unRAID_Essentials/clear_logs.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# ----------------------------------------------------------------------------------------------- +# --------------------------------- Clear Logs Script ------------------------------------------ +# ----------------------------------------------------------------------------------------------- +# Clears unRAID system logs and Docker container logs safely. +# Log file paths are configured in Master.conf under LOG_FILES. +# Supports --dry-run to preview what would be cleared without making changes. +# ----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" +source "$SCRIPT_DIR/../common.sh" + +parse_args "$@" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_GEAR Setup ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_GEAR Setup ━━━" + +# ROOT CHECK +if [[ "$EUID" -ne 0 ]]; then + error "Must be run as root" + exit 1 +fi + +success "Running as root" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Status ━━━ +# ----------------------------------------------------------------------------------------------- +if [[ "$SHOW_STATUS" == true ]]; then + echo "" + echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━" + echo "$ICON_HEALTH System Logs: ${LOG_FILES[*]}" + echo "$ICON_DOCKER Docker Logs: /var/lib/docker/containers" + echo "$ICON_GEAR Dry Run: $DRY_RUN" + echo "━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 +fi + +# ----------------------------------------------------------------------------------------------- +# FUNCTIONS +# ----------------------------------------------------------------------------------------------- + +# Clears a single log file if it exists. +# Skips with a warning if the file is not found. +clear_file() { + local file="$1" + + if [[ ! -f "$file" ]]; then + warn "Not found: $file — skipping" + return + fi + + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would clear: $file" + else + : > "$file" + success "Cleared: $file" + fi +} + +# Finds and clears all Docker container json log files. +# Skips gracefully if Docker directory or log files are not found. +clear_docker_logs() { + if [[ ! -d /var/lib/docker/containers ]]; then + warn "$ICON_DOCKER Docker directory not found — skipping" + return + fi + + local files + files=$(find /var/lib/docker/containers/ -name "*-json.log" 2>/dev/null || true) + + if [[ -z "$files" ]]; then + warn "$ICON_DOCKER No Docker logs found — skipping" + return + fi + + while IFS= read -r file; do + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would clear Docker log: $file" + else + : > "$file" + success "Cleared Docker log: $(basename "$(dirname "$file")")" + fi + done <<< "$files" +} + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_HEALTH Clear Logs ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_HEALTH Clear Logs ━━━" +echo "$ICON_HEALTH System Logs: ${LOG_FILES[*]}" +echo "$ICON_DOCKER Docker Logs: enabled" +echo "$ICON_GEAR Dry Run: $DRY_RUN" +echo "" + +[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made" + +START=$(date +%s) + +for logfile in "${LOG_FILES[@]}"; do + clear_file "$logfile" +done + +echo "" +echo "━━━ $ICON_DOCKER Docker ━━━" +clear_docker_logs + +END=$(date +%s) + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Summary ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━━━ $ICON_SUMMARY LOG CLEANER SUMMARY ━━━━━" +echo "$ICON_HEALTH System Logs: ${LOG_FILES[*]}" +echo "$ICON_DOCKER Docker Logs: $([[ "$DRY_RUN" == true ]] && echo "skipped (dry run)" || echo "cleared")" +echo "$ICON_TIME Duration: $(format_duration $((END - START)))" +if [[ "$DRY_RUN" == true ]]; then + echo "$ICON_WARN Status: DRY RUN — no changes made" +else + echo "$ICON_DONE Status: $ICON_SUCCESS DONE" +fi +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" \ No newline at end of file diff --git a/unRAID_Essentials/docker_syslog_filter.sh b/unRAID_Essentials/docker_syslog_filter.sh new file mode 100644 index 0000000..1db45a5 --- /dev/null +++ b/unRAID_Essentials/docker_syslog_filter.sh @@ -0,0 +1,118 @@ +#!/bin/bash +# ----------------------------------------------------------------------------------------------- +# --------------------------------- Docker Syslog Filter --------------------------------------- +# ----------------------------------------------------------------------------------------------- +# Suppresses noisy Docker veth/docker0 syslog messages on unRAID boot. +# Creates an rsyslog filter file and restarts the rsyslog service. +# Filter file path is configured in Master.conf under FILTER_FILE. +# Supports --dry-run to preview what would be done without making changes. +# ----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" +source "$SCRIPT_DIR/../common.sh" + +parse_args "$@" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_GEAR Setup ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_GEAR Setup ━━━" + +# ROOT CHECK +if [[ "$EUID" -ne 0 ]]; then + error "Must be run as root" + exit 1 +fi + +success "Running as root" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Status ━━━ +# ----------------------------------------------------------------------------------------------- +if [[ "$SHOW_STATUS" == true ]]; then + echo "" + echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━" + echo "$ICON_HEALTH Filter File: $FILTER_FILE" + echo "$ICON_CONTAINERS Targets: veth, docker0" + echo "$ICON_GEAR Dry Run: $DRY_RUN" + echo "━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 +fi + +# ----------------------------------------------------------------------------------------------- +# FUNCTIONS +# ----------------------------------------------------------------------------------------------- + +# Creates the rsyslog filter file that suppresses veth and docker0 noise. +# Filter is written to FILTER_FILE defined in Master.conf. +create_filter() { + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would create filter file: $FILTER_FILE" + return + fi + + info "Writing rsyslog filter file: $FILTER_FILE" + + cat <<'EOF' > "$FILTER_FILE" +if ($msg contains "veth" or $msg contains "docker0") then { + stop +} +EOF + + success "Filter file written" +} + +# Restarts the rsyslog service to apply the new filter. +# Uses unRAID's native rc.rsyslogd script. +restart_rsyslog() { + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would restart rsyslog service" + return + fi + + info "Restarting rsyslog..." + + if /etc/rc.d/rc.rsyslogd restart; then + success "rsyslog restarted" + else + error "Failed to restart rsyslog" + exit 1 + fi +} + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_HEALTH Syslog Filter ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_HEALTH Syslog Filter ━━━" +echo "$ICON_HEALTH Filter File: $FILTER_FILE" +echo "$ICON_CONTAINERS Targets: veth / docker0" +echo "$ICON_GEAR Dry Run: $DRY_RUN" +echo "" + +[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made" + +START=$(date +%s) + +create_filter +restart_rsyslog + +END=$(date +%s) + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Summary ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━━━ $ICON_SUMMARY SYSLOG FILTER SUMMARY ━━━━━" +echo "$ICON_HEALTH Filter File: $FILTER_FILE" +echo "$ICON_CONTAINERS Targets: veth / docker0" +echo "$ICON_TIME Duration: $(format_duration $((END - START)))" +if [[ "$DRY_RUN" == true ]]; then + echo "$ICON_WARN Status: DRY RUN — no changes made" +else + echo "$ICON_DONE Status: $ICON_SUCCESS DONE" +fi +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" \ No newline at end of file diff --git a/unRAID_Essentials/mover-stop.sh b/unRAID_Essentials/mover-stop.sh new file mode 100644 index 0000000..a55645d --- /dev/null +++ b/unRAID_Essentials/mover-stop.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# ----------------------------------------------------------------------------------------------- +# --------------------------------- Mover Stop Script ------------------------------------------ +# ----------------------------------------------------------------------------------------------- +# Safely stops the unRAID mover process with a user warning before halting. +# Timeout before stopping is configured in Master.conf under MOVER_STOP_TIMEOUT. +# Supports --dry-run to preview what would happen without making changes. +# ----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" +source "$SCRIPT_DIR/../common.sh" + +parse_args "$@" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_GEAR Setup ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_GEAR Setup ━━━" + +# ROOT CHECK +if [[ "$EUID" -ne 0 ]]; then + error "Must be run as root" + exit 1 +fi + +success "Running as root" + +# Validate MOVER_STOP_TIMEOUT is a valid integer before using it +validate_int MOVER_STOP_TIMEOUT "$MOVER_STOP_TIMEOUT" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Status ━━━ +# ----------------------------------------------------------------------------------------------- +if [[ "$SHOW_STATUS" == true ]]; then + echo "" + echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━" + echo "$ICON_MOVER Timeout: ${MOVER_STOP_TIMEOUT}s" + echo "$ICON_GEAR Dry Run: $DRY_RUN" + echo "━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 +fi + +# ----------------------------------------------------------------------------------------------- +# FUNCTIONS +# ----------------------------------------------------------------------------------------------- + +# Returns 0 if the unRAID mover process is currently running, 1 if not. +check_mover_running() { + pgrep -f "emhttp.*Mover" >/dev/null 2>&1 +} + +# Broadcasts a wall message to all logged in users warning mover is stopping. +notify_users() { + warn "Notifying users — mover stopping in ${MOVER_STOP_TIMEOUT}s" + wall "$ICON_WARN unRAID Mover will stop in ${MOVER_STOP_TIMEOUT} second(s)." +} + +# Sends SIGTERM to the mover process via pkill. +# Skips if dry run is active. +stop_mover() { + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would stop unRAID Mover process" + return + fi + + info "Stopping unRAID Mover..." + + if pkill -f "emhttp.*Mover"; then + success "Mover stopped" + else + warn "Could not stop mover — may have already stopped" + fi +} + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_MOVER Mover Stop ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_MOVER Mover Stop ━━━" +echo "$ICON_MOVER Timeout: ${MOVER_STOP_TIMEOUT}s" +echo "$ICON_GEAR Dry Run: $DRY_RUN" +echo "" + +[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made" + +START=$(date +%s) + +if check_mover_running; then + info "$ICON_MOVER Mover is running" + notify_users + info "Waiting ${MOVER_STOP_TIMEOUT}s before stopping..." + sleep "$MOVER_STOP_TIMEOUT" + stop_mover +else + info "$ICON_MOVER Mover is not running — nothing to do" +fi + +END=$(date +%s) + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Summary ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━━━ $ICON_SUMMARY MOVER STOP SUMMARY ━━━━━" +echo "$ICON_TIME Duration: $(format_duration $((END - START)))" +if check_mover_running; then + echo "$ICON_ERROR Status: $ICON_ERROR STILL RUNNING" +else + echo "$ICON_DONE Status: $ICON_SUCCESS STOPPED / NOT RUNNING" +fi +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" \ No newline at end of file diff --git a/unRAID_Essentials/php_fpm_max_children.sh b/unRAID_Essentials/php_fpm_max_children.sh new file mode 100644 index 0000000..c2591e4 --- /dev/null +++ b/unRAID_Essentials/php_fpm_max_children.sh @@ -0,0 +1,131 @@ +#!/bin/bash +# ----------------------------------------------------------------------------------------------- +# ----------------------------- PHP-FPM Max Children Script ------------------------------------ +# ----------------------------------------------------------------------------------------------- +# Persistently sets PHP-FPM pm.max_children on unRAID. +# Config file path and max children value are set in Master.conf. +# Supports --dry-run to preview what would be changed without making changes. +# ----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" +source "$SCRIPT_DIR/../common.sh" + +parse_args "$@" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_GEAR Setup ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_GEAR Setup ━━━" + +# ROOT CHECK +if [[ "$EUID" -ne 0 ]]; then + error "Must be run as root" + exit 1 +fi + +success "Running as root" + +# VALIDATION +validate_int PHP_MAX_CHILDREN "$PHP_MAX_CHILDREN" +require_var PHP_CONF + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Status ━━━ +# ----------------------------------------------------------------------------------------------- +if [[ "$SHOW_STATUS" == true ]]; then + echo "" + echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━" + echo "$ICON_GEAR Config File: $PHP_CONF" + echo "$ICON_PHP Max Children: $PHP_MAX_CHILDREN" + echo "$ICON_GEAR Dry Run: $DRY_RUN" + echo "━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 +fi + +# ----------------------------------------------------------------------------------------------- +# FUNCTIONS +# ----------------------------------------------------------------------------------------------- + +# Applies pm.max_children to the PHP-FPM config file and restarts the service. +# Verifies the value was applied correctly after restart. +# Skips all changes if dry run is active. +apply_php_max_children() { + local target="pm.max_children = $PHP_MAX_CHILDREN" + + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would set pm.max_children = $PHP_MAX_CHILDREN in $PHP_CONF" + warn "DRY RUN — would restart PHP-FPM service" + return + fi + + # Verify config file exists before attempting changes + if [[ ! -f "$PHP_CONF" ]]; then + error "PHP config file not found: $PHP_CONF" + exit 1 + fi + + info "Applying pm.max_children = $PHP_MAX_CHILDREN..." + + if sed -i "s/^pm\.max_children.*/$target/" "$PHP_CONF"; then + success "Config updated" + else + error "Failed to update PHP config: $PHP_CONF" + exit 1 + fi + + info "Restarting PHP-FPM..." + + if /etc/rc.d/rc.php-fpm restart; then + success "PHP-FPM restarted" + else + error "PHP-FPM restart failed" + exit 1 + fi + + # Verify the value was applied correctly + local current + current=$(grep -E "^pm\.max_children" "$PHP_CONF" || true) + + if [[ -n "$current" ]]; then + success "Verified: $current" + logger "Userscript: PHP-FPM updated → $current" + else + warn "Could not verify configuration value — check $PHP_CONF manually" + fi +} + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_PHP PHP-FPM Config ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_PHP PHP-FPM Config ━━━" +echo "$ICON_GEAR Config File: $PHP_CONF" +echo "$ICON_PHP Max Children: $PHP_MAX_CHILDREN" +echo "$ICON_GEAR Dry Run: $DRY_RUN" +echo "" + +[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made" + +START=$(date +%s) + +apply_php_max_children + +END=$(date +%s) + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Summary ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━━━ $ICON_SUMMARY PHP-FPM SUMMARY ━━━━━" +echo "$ICON_GEAR Config File: $PHP_CONF" +echo "$ICON_PHP Max Children: $PHP_MAX_CHILDREN" +echo "$ICON_TIME Duration: $(format_duration $((END - START)))" +if [[ "$DRY_RUN" == true ]]; then + echo "$ICON_WARN Status: DRY RUN — no changes made" +else + echo "$ICON_DONE Status: $ICON_SUCCESS DONE" +fi +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" \ No newline at end of file diff --git a/unRAID_Essentials/rsync_stop.sh b/unRAID_Essentials/rsync_stop.sh new file mode 100644 index 0000000..af6a989 --- /dev/null +++ b/unRAID_Essentials/rsync_stop.sh @@ -0,0 +1,192 @@ +#!/bin/bash +# ----------------------------------------------------------------------------------------------- +# --------------------------------- Rsync Stop Script ------------------------------------------ +# ----------------------------------------------------------------------------------------------- +# Stops all running rsync processes on both the local and remote server. +# Used during array stop or manually when rsync needs to be forcefully terminated. +# If rsync processes were killed locally, checks all profile containers and restarts any +# that were left stopped by the interrupted rsync run. +# Remote is killed but left in whatever container state it is in — secondary is self-healing. +# Supports --dry-run to preview what would be killed without making changes. +# ----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" +source "$SCRIPT_DIR/../common.sh" + +parse_args "$@" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_GEAR Setup ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_GEAR Setup ━━━" + +detect_hosts +resolve_remote_ip + +# Check connectivity but do not exit on failure — remote may already be going down +REMOTE_REACHABLE=true +if ! ping -c1 -W3 "$REMOTE_SERVER" &>/dev/null; then + warn "$ICON_PING Remote $REMOTE_SERVER_NAME is unreachable — will skip remote kill" + REMOTE_REACHABLE=false +else + info "$ICON_PING $REMOTE_SERVER_NAME is reachable" +fi + +[[ "$SHOW_STATUS" == true ]] && show_status && exit 0 +[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_STOP Local Rsync ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_STOP Local Rsync ━━━" + +LOCAL_KILLED=false +LOCAL_PIDS=$(pgrep -x rsync || true) + +if [[ -z "$LOCAL_PIDS" ]]; then + info "No rsync processes running locally — nothing to kill" +else + info "Found rsync processes locally: $(echo "$LOCAL_PIDS" | tr '\n' ' ')" + + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would kill local rsync processes" + else + if pkill -x rsync; then + success "Local rsync processes killed" + LOCAL_KILLED=true + else + warn "pkill returned non-zero — processes may have already exited" + fi + fi +fi + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_STOP Remote Rsync ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_STOP Remote Rsync ($REMOTE_SERVER_NAME) ━━━" + +REMOTE_KILLED=false + +if [[ "$REMOTE_REACHABLE" == false ]]; then + warn "Skipping remote kill — $REMOTE_SERVER_NAME unreachable" +else + REMOTE_PIDS=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ + "pgrep -x rsync || true" 2>/dev/null || true) + + if [[ -z "$REMOTE_PIDS" ]]; then + info "No rsync processes running on $REMOTE_SERVER_NAME — nothing to kill" + else + info "Found rsync processes on $REMOTE_SERVER_NAME: $(echo "$REMOTE_PIDS" | tr '\n' ' ')" + + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would kill remote rsync processes" + else + if ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "pkill -x rsync || true" 2>/dev/null; then + success "Remote rsync processes killed" + REMOTE_KILLED=true + else + warn "Remote pkill returned non-zero — processes may have already exited" + fi + fi + fi +fi + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_START $ICON_CONTAINERS Local Container Recovery ━━━ +# Only runs if rsync was actually killed locally — containers may have been left stopped +# by the interrupted rsync run. Checks all containers across all profiles and restarts +# any that are currently stopped. Remote containers are left in their current state. +# ----------------------------------------------------------------------------------------------- +CONTAINERS_RESTARTED=() + +if [[ "$LOCAL_KILLED" == true ]]; then + echo "" + echo "━━━ $ICON_START $ICON_CONTAINERS Local Container Recovery ━━━" + info "Rsync was killed locally — checking all profile containers..." + + # Build deduplicated list of all containers across all profiles + declare -A SEEN + ALL_CONTAINERS=() + + for profile_containers in "${PROFILE_CRITICAL_CONTAINER_NAMES[@]}"; do + read -r -a container_list <<< "$profile_containers" + for c in "${container_list[@]}"; do + [[ -z "$c" ]] && continue + if [[ -z "${SEEN[$c]:-}" ]]; then + SEEN[$c]=1 + ALL_CONTAINERS+=("$c") + fi + done + done + + if [[ ${#ALL_CONTAINERS[@]} -eq 0 ]]; then + info "No containers defined across any profile — skipping recovery" + else + for c in "${ALL_CONTAINERS[@]}"; do + info "Checking $c..." + + STATUS=$(docker inspect -f '{{.State.Running}}' "$c" 2>/dev/null || echo "unknown") + + if [[ "$STATUS" == "true" ]]; then + echo "$ICON_RUNNING $c is running — no action needed" + elif [[ "$STATUS" == "false" ]]; then + echo "$ICON_NOT_RUNNING $c is stopped — restarting..." + + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would restart $c" + else + if docker start "$c" >/dev/null 2>&1; then + echo "$ICON_STARTED $c restarted" + CONTAINERS_RESTARTED+=("$c") + else + error "Failed to restart $c" + fi + fi + else + warn "$c state unknown — may not exist on this machine, skipping" + fi + done + fi +elif [[ "$DRY_RUN" == false ]]; then + info "No local rsync was killed — skipping container recovery" +fi + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Summary ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━━━ $ICON_SUMMARY RSYNC STOP SUMMARY ━━━━━" +echo "$ICON_HOST Local ($LOCAL_SERVER_NAME):" +if [[ "$LOCAL_KILLED" == true ]]; then + echo " $ICON_STOPPED Rsync killed" +elif [[ "$DRY_RUN" == true ]]; then + echo " $ICON_WARN Dry run — no changes made" +else + echo " $ICON_SUCCESS No rsync running" +fi + +echo "$ICON_NET Remote ($REMOTE_SERVER_NAME):" +if [[ "$REMOTE_REACHABLE" == false ]]; then + echo " $ICON_WARN Unreachable — state unknown" +elif [[ "$REMOTE_KILLED" == true ]]; then + echo " $ICON_STOPPED Rsync killed" +else + echo " $ICON_SUCCESS No rsync running" +fi + +if [[ ${#CONTAINERS_RESTARTED[@]} -gt 0 ]]; then + echo "$ICON_CONTAINERS Containers restarted locally:" + for c in "${CONTAINERS_RESTARTED[@]}"; do + echo " $ICON_STARTED $c" + done +elif [[ "$LOCAL_KILLED" == true ]]; then + echo "$ICON_CONTAINERS No containers needed restarting" +fi + +echo "$ICON_TIME Dry Run: $DRY_RUN" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" \ No newline at end of file diff --git a/unRAID_Essentials/server-reboot.sh b/unRAID_Essentials/server-reboot.sh new file mode 100644 index 0000000..295be85 --- /dev/null +++ b/unRAID_Essentials/server-reboot.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# ----------------------------------------------------------------------------------------------- +# --------------------------------- Server Reboot Script --------------------------------------- +# ----------------------------------------------------------------------------------------------- +# Gracefully reboots the unRAID server with a configurable user warning delay. +# Stops Docker and VM Manager cleanly before issuing reboot. +# Reboot delay is configured in Master.conf under REBOOT_SLEEP. +# Supports --dry-run to walk through the sequence without actually rebooting. +# ----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" +source "$SCRIPT_DIR/../common.sh" + +parse_args "$@" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_GEAR Setup ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_GEAR Setup ━━━" + +# ROOT CHECK +if [[ "$EUID" -ne 0 ]]; then + error "Must be run as root" + exit 1 +fi + +success "Running as root" + +# VALIDATION +validate_int REBOOT_SLEEP "$REBOOT_SLEEP" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Status ━━━ +# ----------------------------------------------------------------------------------------------- +if [[ "$SHOW_STATUS" == true ]]; then + echo "" + echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━" + echo "$ICON_REBOOT Delay: ${REBOOT_SLEEP}s" + echo "$ICON_GEAR Dry Run: $DRY_RUN" + echo "━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 +fi + +# ----------------------------------------------------------------------------------------------- +# FUNCTIONS +# ----------------------------------------------------------------------------------------------- + +# Broadcasts a wall message warning all logged in users of the upcoming reboot. +notify_users() { + warn "Notifying users — reboot in ${REBOOT_SLEEP}s" + wall "$ICON_WARN unRAID server will reboot in ${REBOOT_SLEEP} second(s). Save your work." +} + +# Stops the Docker service cleanly. +# Warns but continues if Docker is already stopped or fails — shutdown must proceed. +stop_docker() { + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would stop Docker service" + return + fi + + info "Stopping Docker service..." + + if /etc/rc.d/rc.docker stop; then + success "Docker stopped" + else + warn "Docker stop failed or already stopped — continuing" + fi +} + +# Stops the VM Manager (libvirt) cleanly. +# Warns but continues if libvirt is already stopped or fails — shutdown must proceed. +stop_vm_manager() { + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would stop VM Manager (libvirt)" + return + fi + + info "Stopping VM Manager..." + + if /etc/rc.d/rc.libvirt stop; then + success "VM Manager stopped" + else + warn "VM Manager stop failed or already stopped — continuing" + fi +} + +# Flushes filesystem buffers to disk before reboot. +sync_disks() { + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would sync filesystem buffers" + return + fi + + info "Syncing disks..." + + if sync; then + success "Disk sync complete" + else + warn "Sync returned an error — continuing" + fi +} + +# Issues the system reboot command. +# System will not return from this call unless dry-run is active. +reboot_system() { + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would reboot system now" + return + fi + + echo "" + echo "$ICON_REBOOT Rebooting system NOW..." + /sbin/reboot +} + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_REBOOT Reboot Sequence ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_REBOOT Reboot Sequence ━━━" +echo "$ICON_REBOOT Delay: ${REBOOT_SLEEP}s" +echo "$ICON_GEAR Dry Run: $DRY_RUN" +echo "" + +[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made" + +START=$(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 is active +END=$(date +%s) + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Summary ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━━━ $ICON_SUMMARY REBOOT SUMMARY ━━━━━" +echo "$ICON_REBOOT Delay: ${REBOOT_SLEEP}s" +echo "$ICON_TIME Duration: $(format_duration $((END - START)))" +if [[ "$DRY_RUN" == true ]]; then + echo "$ICON_WARN Status: DRY RUN — no reboot executed" +else + echo "$ICON_REBOOT Status: $ICON_WARN SYSTEM SHOULD BE REBOOTING" +fi +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" \ No newline at end of file diff --git a/unRAID_Essentials/user_scripts_stop.sh b/unRAID_Essentials/user_scripts_stop.sh new file mode 100644 index 0000000..5339dff --- /dev/null +++ b/unRAID_Essentials/user_scripts_stop.sh @@ -0,0 +1,125 @@ +#!/bin/bash +# ----------------------------------------------------------------------------------------------- +# --------------------------------- User Script Stop ------------------------------------------- +# ----------------------------------------------------------------------------------------------- +# Stops all running User Script processes spawned by the unRAID User Scripts plugin. +# Identifies processes by their /tmp/user.scripts path signature. +# Supports --dry-run to preview what would be killed without making changes. +# ----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" +source "$SCRIPT_DIR/../common.sh" + +parse_args "$@" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_GEAR Setup ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_GEAR Setup ━━━" + +# ROOT CHECK +if [[ "$EUID" -ne 0 ]]; then + error "Must be run as root" + exit 1 +fi + +success "Running as root" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Status ━━━ +# ----------------------------------------------------------------------------------------------- +if [[ "$SHOW_STATUS" == true ]]; then + echo "" + echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━" + echo "$ICON_PLUGIN Target: /tmp/user.scripts processes" + echo "$ICON_GEAR Dry Run: $DRY_RUN" + echo "━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 +fi + +# ----------------------------------------------------------------------------------------------- +# FUNCTIONS +# ----------------------------------------------------------------------------------------------- + +# Returns PIDs of all processes running under /tmp/user.scripts +# These are processes spawned by the unRAID User Scripts plugin. +get_user_script_pids() { + /usr/bin/ps -eo pid,cmd | grep "/tmp/user.scripts" | grep -v grep | awk '{print $1}' +} + +# Kills all running User Script processes one by one. +# Reports each PID killed or skipped in dry run mode. +# Checks remaining processes after kill to confirm cleanup. +stop_user_scripts() { + local pids + pids=$(get_user_script_pids) + + if [[ -z "$pids" ]]; then + info "$ICON_PLUGIN No running User Script processes found — nothing to do" + return + fi + + local count=0 + + for pid in $pids; do + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would kill User Script PID $pid" + else + info "Killing User Script PID $pid..." + + if kill "$pid" 2>/dev/null; then + success "Killed PID $pid" + else + warn "Could not kill PID $pid — may have already exited" + fi + fi + + count=$((count + 1)) + done + + if [[ "$DRY_RUN" == true ]]; then + warn "DRY RUN — would have targeted $count process(es)" + else + info "$count process(es) targeted" + fi +} + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_PLUGIN User Script Stop ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_PLUGIN User Script Stop ━━━" +echo "$ICON_PLUGIN Target: User Scripts Plugin processes" +echo "$ICON_GEAR Dry Run: $DRY_RUN" +echo "" + +[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made" + +START=$(date +%s) + +stop_user_scripts + +END=$(date +%s) + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Summary ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━━━ $ICON_SUMMARY USER SCRIPTS STOP SUMMARY ━━━━━" +echo "$ICON_TIME Duration: $(format_duration $((END - START)))" + +if [[ "$DRY_RUN" == true ]]; then + echo "$ICON_WARN Status: DRY RUN — no processes killed" +else + REMAINING=$(get_user_script_pids) + if [[ -z "$REMAINING" ]]; then + echo "$ICON_DONE Status: $ICON_SUCCESS ALL PROCESSES STOPPED" + else + echo "$ICON_WARN Status: $ICON_WARN SOME PROCESSES MAY STILL BE RUNNING" + fi +fi + +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" \ No newline at end of file diff --git a/unRAID_Essentials/zfs_memory_snapshot.sh b/unRAID_Essentials/zfs_memory_snapshot.sh new file mode 100644 index 0000000..14bd7bb --- /dev/null +++ b/unRAID_Essentials/zfs_memory_snapshot.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# ----------------------------------------------------------------------------------------------- +# --------------------------------- ZFS Memory Snapshot ---------------------------------------- +# ----------------------------------------------------------------------------------------------- +# Captures a point-in-time snapshot of ZFS ARC statistics and system memory usage. +# Read-only diagnostic tool — no changes are made to the system regardless of flags. +# Dry run mode still collects and displays data since no modifications occur. +# ----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$SCRIPT_DIR/../Master.conf" +source "$SCRIPT_DIR/../common.sh" + +parse_args "$@" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_GEAR Setup ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_GEAR Setup ━━━" + +info "$ICON_ZFS ZFS ARC + Memory Snapshot" +info "$ICON_TIME $(date)" + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Status ━━━ +# ----------------------------------------------------------------------------------------------- +if [[ "$SHOW_STATUS" == true ]]; then + echo "" + echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━" + echo "$ICON_ZFS Mode: Read-only diagnostics" + echo "$ICON_MEM Source: ZFS ARC + system memory" + echo "$ICON_GEAR Dry Run: $DRY_RUN" + echo "━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 +fi + +# ----------------------------------------------------------------------------------------------- +# FUNCTIONS +# ----------------------------------------------------------------------------------------------- + +# Reads ZFS ARC statistics from the kernel stats interface. +# Filters for the most useful ARC metrics — size, hits, misses and metadata. +# Skips gracefully if ZFS is not available on this system. +show_zfs_arc() { + echo "" + echo "━━━ $ICON_ZFS ZFS ARC Stats ━━━" + + if [[ ! -r /proc/spl/kstat/zfs/arcstats ]]; then + warn "ZFS arcstats not available on this system — is ZFS loaded?" + 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" +} + +# Reads current system memory and swap usage using free. +# Skips gracefully if free is not available. +show_memory_status() { + echo "" + echo "━━━ $ICON_MEM Memory Status ━━━" + + if ! command -v free >/dev/null 2>&1; then + warn "free command not available on this system" + return + fi + + free -h | awk ' + NR==1 { print $0 } + /Mem:/ { print $0 } + /Swap:/ { print $0 }' +} + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_ZFS Snapshot ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━ $ICON_ZFS Snapshot ━━━" +echo "$ICON_ZFS Source: ZFS ARC + system memory" +echo "$ICON_GEAR Dry Run: $DRY_RUN" +echo "" + +[[ "$DRY_RUN" == true ]] && warn "DRY RUN — this script is read-only, data will still be collected" + +START=$(date +%s) + +show_zfs_arc +show_memory_status + +END=$(date +%s) + +# ----------------------------------------------------------------------------------------------- +# ━━━ $ICON_SUMMARY Summary ━━━ +# ----------------------------------------------------------------------------------------------- +echo "" +echo "━━━━━ $ICON_SUMMARY SNAPSHOT SUMMARY ━━━━━" +echo "$ICON_ZFS Source: ZFS ARC + system memory" +echo "$ICON_GEAR Mode: READ-ONLY — no changes made" +echo "$ICON_TIME Duration: $(format_duration $((END - START)))" +echo "$ICON_DONE Status: $ICON_SUCCESS DONE" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" \ No newline at end of file diff --git a/user_script_pluin.sh b/user_script_pluin.sh new file mode 100644 index 0000000..74a10e6 --- /dev/null +++ b/user_script_pluin.sh @@ -0,0 +1,173 @@ +#!/bin/bash +# ============================================================================================== +# ================================= User Script Template ======================================= +# ============================================================================================== +# +# This file is the master template for all scripts run via the unRAID User Scripts plugin. +# Copy and paste the contents of this file into a new User Script entry in the plugin, +# then uncomment the script you want to run and set your schedule. +# +# All scripts in this ecosystem live at: +# /mnt/user/appdata/unraid_scripts/ +# +# Configuration for all scripts is managed in one place: +# /mnt/user/appdata/unraid_scripts/Master.conf +# +# Shared runtime functions used by all scripts: +# /mnt/user/appdata/unraid_scripts/common.sh +# +# For full setup instructions see: +# /mnt/user/appdata/unraid_scripts/README.md +# +# ============================================================================================== +# Changelog: +# v1.0 — Initial template +# v1.1 — MAX_RSYNC_PROCS removed — bandwidth limiting handles concurrency +# Typo fixes Master.cong → Master.conf +# Added --status flag to arguments section +# Added full directory tree +# All script calls pre-written and grouped by type +# Changelog added +# ============================================================================================== + +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# ━━━ 📂 Repository Structure ━━━ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# +# /mnt/user/appdata/unraid_scripts/ +# ├── Master.conf # All user configuration — edit this file only +# ├── common.sh # Shared library — functions used by all scripts +# ├── README.md # Project overview and quick start +# ├── User_Script_Template.sh # This file — copy into User Scripts plugin +# │ +# ├── Orchestrators/ +# │ └── daily_sync.sh # Runs all daily media share syncs sequentially +# │ # add shares to master.conf, for seqential syncs +# ├── Rsync/ +# │ ├── rsync.sh # Core rsync script — called per share or profile +# │ └── README_Rsync_Setup.md # Rsync-specific setup guide +# │ +# ├── Tools/ +# │ └── recreate_shares.sh # Recreates share dirs from .cfg files after incident +# │ +# └── unRAID_Essentials/ +# ├── clear_logs.sh # Clears unRAID log files +# ├── docker_syslog_filter.sh # Filters docker veth noise from syslog +# ├── mover_stop.sh # Safely stops the unRAID mover +# ├── php_fpm_max_children.sh # Sets php-fpm max children value +# ├── rsync_stop.sh # Cleanly stops all running rsync processes +# ├── server_reboot.sh # Graceful server reboot with user warning +# ├── user_script_stop.sh # Stops a running User Scripts job +# └── zfs_memory_snapshot.sh # Creates a ZFS memory snapshot +# +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# ━━━ 🚀 Script Commands — Uncomment the one you want to run ━━━ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# +# ━━━ Orchestrators (README) ━━━ +# The daily orchestrator runs all bulk media shares sequentially in a single scheduled job. +# Instead of creating a User Script entry per share, add the share path to DAILY_SYNC_SHARES +# in Master.conf and the orchestrator handles it automatically at 1am. +# +# Media shares are nothing special — they carry no profile and fall through to global defaults +# in Master.conf. Sequential execution means one share finishes before the next starts, +# no concurrency needed, bandwidth limiting keeps things sane if appdata jobs overlap. +# +# This is where 80% of your rsync shares should live. Only create individual scheduled +# entries for shares that need their own timing — like appdata profiles above. +# +# ━━━ Orchestrators ━━━ +#/mnt/user/appdata/unraid_scripts/Orchestrators/daily_sync.sh +# +# ━━━ Rsync — Appdata Profiles (scheduled individually) ━━━ +#/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-Failover/Arrs_Stack +#/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-Failover/Critical-Data +#/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-Failover/Important-Data +#/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-Failover/Emby +#/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-Failover/Gmer4Lfe +# +# ━━━ Rsync — Individual Media Share (ad hoc use) ━━━ +#/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/Movies +#/mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/Tv_Shows +# +# ━━━ Tools ━━━ +#/mnt/user/appdata/unraid_scripts/Tools/recreate_shares.sh +# +# ━━━ unRAID Essentials ━━━ +#/mnt/user/appdata/unraid_scripts/unRAID_Essentials/clear_logs.sh +#/mnt/user/appdata/unraid_scripts/unRAID_Essentials/docker_syslog_filter.sh +#/mnt/user/appdata/unraid_scripts/unRAID_Essentials/mover_stop.sh +#/mnt/user/appdata/unraid_scripts/unRAID_Essentials/php_fpm_max_children.sh +#/mnt/user/appdata/unraid_scripts/unRAID_Essentials/rsync_stop.sh +#/mnt/user/appdata/unraid_scripts/unRAID_Essentials/server_reboot.sh +#/mnt/user/appdata/unraid_scripts/unRAID_Essentials/user_script_stop.sh +#/mnt/user/appdata/unraid_scripts/unRAID_Essentials/zfs_memory_snapshot.sh +# + +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# ━━━ ⚙️ Arguments — Add after the script path ━━━ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# +# ━━━ Rsync / Orchestrators ━━━ +# +# --dry-run Preview what would be transferred — no changes made +# --log Enable verbose logging output +# --no-log Disable logging (overrides Master.conf setting) +# --status Print resolved profile and configuration then exit +# --help Show usage information +# +# KEY=VALUE Override any Master.conf variable for this run only +# Better to add a profile in Master.conf for permanent changes +# +# ━━━ unRAID Essentials ━━━ +# +# Arguments vary per script — see comments inside each script for details +# +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# ━━━ 📋 Profile System ━━━ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# +# Profiles are defined in Master.conf and matched automatically by the +# basename of the directory path passed to rsync.sh (lowercased). +# +# Example: +# /mnt/user/appdata-Failover/Arrs_Stack → matches profile key [arrs_stack] +# /mnt/user/Movies → no match, uses global defaults +# +# If a profile match is found — profile settings are used for that run +# If no profile match is found — global defaults from Master.conf are used +# +# Profile settings control: +# - rsync options PROFILE_RSYNC_OPTS +# - bandwidth limit PROFILE_BW_LIMIT +# - retry count PROFILE_RETRY_COUNT +# - sleep between retry PROFILE_SLEEP +# - containers to stop PROFILE_CRITICAL_CONTAINER_NAMES +# - delayed containers PROFILE_DELAYED_CONTAINERS +# - container delay PROFILE_CONTAINER_DELAY +# - excluded dirs PROFILE_EXCLUDE_DIRS +# +# To add a new profile — add a key to each array in Master.conf +# For permanent changes — always use Master.conf +# For one-off overrides — use KEY=VALUE arguments (see above) +# +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# ━━━ 💡 Examples ━━━ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# +# Run arrs_stack profile sync: +# /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-Failover/Arrs_Stack +# +# Dry run with logging enabled: +# /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-Failover/Arrs_Stack --dry-run --log +# +# Check what profile and settings resolved before running: +# /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/appdata-Failover/Arrs_Stack --status +# +# Override bandwidth limit for this run only: +# /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh /mnt/user/Movies BW_LIMIT=5000 +# +# Run daily orchestrator: +# /mnt/user/appdata/unraid_scripts/Orchestrators/daily_sync.sh +# +# ============================================================================================== \ No newline at end of file