added icons and improved ux

This commit is contained in:
2026-04-06 01:11:30 +00:00
parent 227cdaac19
commit 9cad6ba306
4 changed files with 119 additions and 70 deletions
+18 -17
View File
@@ -16,10 +16,10 @@
ENABLE_LOGGING=true # false = only echo user-facing messages
# ------------------ Git, Pull & Execute Script -----------------
REPO_SSH="git@192.168.50.2:FailedProxy/Unraid_Scripts.git"
TARGET_DIR="/mnt/user/appdata/unraid_scripts"
GITEA_SSH_KEY="/root/.ssh/id_gitea_rsync"
SSH_PORT=221
REPO_SSH="git@192.168.50.2:FailedProxy/Unraid_Scripts.git"
TARGET_DIR="/mnt/user/appdata/unraid_scripts"
GITEA_SSH_KEY="/root/.ssh/id_gitea_rsync"
SSH_PORT=221
# -------------------Rsync Script Defaults-----------------------
# These are the fallback values used when no matching profile is found.
@@ -51,19 +51,20 @@ SSH_PORT=221
# Shares synced once daily by Orchestrators/daily_sync.sh
# Add or remove paths here to manage what gets synced.
# These shares have no profile entry and fall through to DEFAULT_RSYNC_OPTS above.
DAILY_SYNC_SHARES=(
/mnt/user/Anime_Movies-Old
/mnt/user/Anime_Shows-Old
/mnt/user/Anime_Shows
/mnt/user/Books
/mnt/user/Intros
/mnt/user/Kids_Movies
/mnt/user/Kids_Tv_Shows
/mnt/user/Movies
/mnt/user/Music_Videos
/mnt/user/Nextcloud
/mnt/user/stand-up_comedy
/mnt/user/Tv_Shows
DAILY_SYNC_SHARES=(
/mnt/user/Anime_Movies-Old
/mnt/user/Anime_Shows-Old
/mnt/user/Anime_Shows
/mnt/user/Books
/mnt/user/Intros
/mnt/user/Kids_Movies
/mnt/user/Kids_Tv_Shows
/mnt/user/Movies
/mnt/user/Music_Videos
/mnt/user/Nextcloud
/mnt/user/stand-up_comedy
/mnt/user/Tv_Shows
/mnt/user/appdata-Failover/Gmer4Lfe/
)
# ------------------- unRAID essentail scripts ------------------
+20 -12
View File
@@ -23,9 +23,16 @@ echo "--- $ICON_GEAR Setup ---"
detect_hosts
resolve_remote_ip
# Single connectivity check upfront — fail fast before attempting all shares
# against an unreachable host rather than failing per-share through the loop
# -----------------------------------------------------------------------------------------------
# --- $ICON_SHIELD Pre-flight Checks ---
# -----------------------------------------------------------------------------------------------
echo ""
echo "--- $ICON_SHIELD Pre-flight Checks ---"
# Single connectivity and rootfs check upfront — fail fast before attempting all shares
# Individual share and disk checks run per-share inside rsync.sh
check_connectivity
check_remote_rootfs
# -----------------------------------------------------------------------------------------------
# Tracking
@@ -41,7 +48,7 @@ SHARE_COUNT=${#DAILY_SYNC_SHARES[@]}
# -----------------------------------------------------------------------------------------------
echo ""
echo "--- $ICON_SYNC Daily Sync Starting — $(date '+%Y-%m-%d %H:%M:%S') ---"
echo "Shares: $SHARE_COUNT"
echo "$ICON_SUMMARY Shares: $SHARE_COUNT"
echo ""
SHARE_INDEX=0
@@ -57,6 +64,7 @@ for SHARE in "${DAILY_SYNC_SHARES[@]}"; do
SHARE_END=$(date +%s)
SHARE_TIMES+=("$SHARE_NAME:$((SHARE_END - SHARE_START))")
PASS+=("$SHARE_NAME")
echo "$ICON_DONE $SHARE_NAME complete"
else
SHARE_END=$(date +%s)
SHARE_TIMES+=("$SHARE_NAME:$((SHARE_END - SHARE_START))")
@@ -71,11 +79,11 @@ TOTAL_END=$(date +%s)
TOTAL_DURATION=$((TOTAL_END - TOTAL_START))
# -----------------------------------------------------------------------------------------------
# --- $ICON_SUCCESS Summary ---
# --- $ICON_SUMMARY Summary ---
# -----------------------------------------------------------------------------------------------
echo "===== DAILY SYNC SUMMARY ====="
echo "Started: $(date -d @$TOTAL_START '+%Y-%m-%d %H:%M:%S')"
echo "Finished: $(date -d @$TOTAL_END '+%Y-%m-%d %H:%M:%S')"
echo "===== $ICON_SUMMARY DAILY SYNC SUMMARY ====="
echo "$ICON_TIME Started: $(date -d @$TOTAL_START '+%Y-%m-%d %H:%M:%S')"
echo "$ICON_TIME Finished: $(date -d @$TOTAL_END '+%Y-%m-%d %H:%M:%S')"
echo ""
for entry in "${SHARE_TIMES[@]}"; do
SHARE_NAME="${entry%%:*}"
@@ -83,14 +91,14 @@ for entry in "${SHARE_TIMES[@]}"; do
if printf '%s\n' "${FAIL[@]}" | grep -qx "$SHARE_NAME"; then
echo " $ICON_ERROR $SHARE_NAME$(format_duration $DURATION)"
else
echo " $ICON_SUCCESS $SHARE_NAME$(format_duration $DURATION)"
echo " $ICON_DONE $SHARE_NAME$(format_duration $DURATION)"
fi
done
echo ""
echo " Passed: ${#PASS[@]}/$SHARE_COUNT"
echo " Failed: ${#FAIL[@]}/$SHARE_COUNT"
echo " Duration: $(format_duration $TOTAL_DURATION)"
echo "=============================="
echo " $ICON_SUCCESS Passed: ${#PASS[@]}/$SHARE_COUNT"
echo " $ICON_ERROR Failed: ${#FAIL[@]}/$SHARE_COUNT"
echo " $ICON_TIME Duration: $(format_duration $TOTAL_DURATION)"
echo "========================================="
[[ ${#FAIL[@]} -gt 0 ]] && exit 1
exit 0
+24 -14
View File
@@ -36,13 +36,23 @@ echo "--- $ICON_GEAR Setup ---"
detect_hosts
resolve_remote_ip
# -----------------------------------------------------------------------------------------------
# --- $ICON_SHIELD Pre-flight Checks ---
# -----------------------------------------------------------------------------------------------
echo ""
echo "--- $ICON_SHIELD Pre-flight Checks ---"
check_connectivity
check_remote_rootfs
check_remote_share "$DIRECTORY"
check_remote_disks "$DIRECTORY"
# -----------------------------------------------------------------------------------------------
# Profile is inferred from the directory basename (lowercased)
# e.g. /mnt/user/appdata-Failover/Arrs_Stack → arrs_stack
# -----------------------------------------------------------------------------------------------
echo ""
PROFILE_NAME=$(basename "$DIRECTORY" | tr '[:upper:]' '[:lower:]')
info "$ICON_GEAR Loading profile: $PROFILE_NAME"
@@ -72,9 +82,9 @@ stop_containers
# -----------------------------------------------------------------------------------------------
echo ""
echo "--- $ICON_SYNC Transfer ---"
echo "Source: $DIRECTORY"
echo "Remote: $REMOTE_SERVER:$DIRECTORY"
echo "Profile: $PROFILE_NAME"
echo "$ICON_RUN Source: $DIRECTORY"
echo "$ICON_NET Remote: $REMOTE_SERVER:$DIRECTORY"
echo "$ICON_GEAR Profile: $PROFILE_NAME"
echo ""
get_rsync_opts
@@ -97,7 +107,7 @@ for i in $(seq 1 "$RETRY_COUNT"); do
if rsync "${RSYNC_OPTS[@]}" \
-e "ssh -i $SSH_KEY -T -o Compression=no -o IPQoS=throughput" \
"$DIRECTORY" "root@${REMOTE_SERVER}:$(dirname "$DIRECTORY")/"; then
success "Rsync complete"
echo "$ICON_DONE Rsync complete"
RSYNC_SUCCESS=true
break
else
@@ -107,29 +117,29 @@ for i in $(seq 1 "$RETRY_COUNT"); do
done
# -----------------------------------------------------------------------------------------------
# --- $ICON_RUN Containers ---
# --- $ICON_START Containers ---
# -----------------------------------------------------------------------------------------------
echo ""
echo "--- $ICON_RUN Containers ---"
echo "--- $ICON_START Containers ---"
start_containers
END=$(date +%s)
# -----------------------------------------------------------------------------------------------
# --- Summary ---
# --- $ICON_SUMMARY Summary ---
# -----------------------------------------------------------------------------------------------
echo ""
echo "===== SUMMARY ====="
echo "Directory: $DIRECTORY"
echo "Profile: $PROFILE_NAME"
echo "Duration: $(format_duration $((END - START)))"
echo "===== $ICON_SUMMARY SUMMARY ====="
echo "$ICON_RUN Directory: $DIRECTORY"
echo "$ICON_GEAR Profile: $PROFILE_NAME"
echo "$ICON_TIME Duration: $(format_duration $((END - START)))"
if [[ "$RSYNC_SUCCESS" == true ]]; then
echo "Status: $ICON_SUCCESS DONE"
echo "$ICON_DONE Status: $ICON_SUCCESS DONE"
else
echo "Status: $ICON_ERROR FAILED after $RETRY_COUNT attempts"
echo "$ICON_ERROR Status: $ICON_ERROR FAILED after $RETRY_COUNT attempts"
fi
echo "==================="
echo "========================="
[[ "$RSYNC_SUCCESS" == false ]] && exit 1
exit 0
+57 -27
View File
@@ -2,7 +2,7 @@
# -----------------------------------------------------------------------------------------------
# ----------------- UNRAID OPS COMMON LIBRARY (STABLE FRAMEWORK v1) ----------------------------
# -----------------------------------------------------------------------------------------------
# Version: 1.4
# Version: 1.5
# -----------------------------------------------------------------------------------------------
# Changelog:
# v1.0 — Initial stable framework
@@ -18,19 +18,50 @@
# v1.4 — check_remote_disks added — verifies all physical disks backing a share are mounted
# Discovers disk layout automatically at runtime, no configuration required
# Aborts if any single disk backing the share is offline or unmounted
# v1.5 — Full icon set expanded — each operation and state has its own distinct icon
# All function output updated to use correct icon per context
# Icons grouped and commented by category for clarity
# -----------------------------------------------------------------------------------------------
# -----------------------------------------------------------------------------------------------
# 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_STOP="⛔" # stop command being issued
ICON_STOPPED="🔴" # container confirmed stopped
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
# 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
# Output
ICON_INFO="️"
ICON_WARN="⚠️"
ICON_ERROR="❌"
ICON_SUCCESS="✅"
ICON_RUN="🚀"
ICON_STOP="🛑"
ICON_RETRY="🔁"
ICON_SYNC="🔄"
ICON_GEAR="⚙️"
ICON_DISK="💾"
# -----------------------------------------------------------------------------------------------
# OUTPUT HELPERS
@@ -149,7 +180,7 @@ detect_hosts() {
[[ -z "$SSH_KEY" ]] && error "Missing SSH key mapping for $LOCAL_SERVER_NAME$REMOTE_SERVER_NAME" && exit 1
info "$ICON_GEAR Host: $LOCAL_SERVER_NAME$REMOTE_SERVER_NAME"
info "$ICON_HOST Host: $LOCAL_SERVER_NAME$REMOTE_SERVER_NAME"
}
# -----------------------------------------------------------------------------------------------
@@ -159,12 +190,12 @@ detect_hosts() {
# Exits if resolution fails — likely means Tailscale is down or peer is offline.
# -----------------------------------------------------------------------------------------------
resolve_remote_ip() {
log "$ICON_SYNC Resolving remote IP for $REMOTE_SERVER_NAME..."
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_SYNC Remote IP: $REMOTE_SERVER"
info "$ICON_NET Remote IP: $REMOTE_SERVER"
}
# -----------------------------------------------------------------------------------------------
@@ -176,11 +207,11 @@ resolve_remote_ip() {
check_connectivity() {
log "Checking connectivity to $REMOTE_SERVER..."
if ! ping -c1 -W3 "$REMOTE_SERVER" &>/dev/null; then
error "Remote $REMOTE_SERVER ($REMOTE_SERVER_NAME) is unreachable"
error "$ICON_PING Remote $REMOTE_SERVER ($REMOTE_SERVER_NAME) is unreachable"
info "Hint: tailscale status | grep $REMOTE_SERVER_NAME"
exit 1
fi
log "Remote is reachable"
info "$ICON_PING $REMOTE_SERVER_NAME is reachable"
}
# -----------------------------------------------------------------------------------------------
@@ -204,14 +235,14 @@ check_remote_rootfs() {
if [[ "$REMOTE_USAGE" -ge "${ROOTFS_WARN:-75}" ]]; then
echo ""
error "Remote rootfs is ${REMOTE_USAGE}% full — threshold is ${ROOTFS_WARN:-75}%"
error "$ICON_HEALTH Remote rootfs is ${REMOTE_USAGE}% full — threshold is ${ROOTFS_WARN:-75}%"
warn "Array may be down or drives missing on $REMOTE_SERVER_NAME"
info "Hint: Check array status on $REMOTE_SERVER_NAME before retrying"
echo ""
exit 1
fi
success "Remote rootfs: ${REMOTE_USAGE}% used (threshold: ${ROOTFS_WARN:-75}%)"
info "$ICON_HEALTH Remote rootfs: ${REMOTE_USAGE}% used (threshold: ${ROOTFS_WARN:-75}%)"
}
# -----------------------------------------------------------------------------------------------
@@ -232,7 +263,7 @@ check_remote_share() {
if [[ "$SHARE_EXISTS" != "yes" ]]; then
echo ""
error "Remote share does not exist: $dir"
error "$ICON_HEALTH Remote share does not exist: $dir"
warn "Array may not be started or share is not configured on $REMOTE_SERVER_NAME"
info "Hint: Check shares and array status on $REMOTE_SERVER_NAME before retrying"
echo ""
@@ -244,14 +275,14 @@ check_remote_share() {
if [[ "$SHARE_EMPTY" == "yes" ]]; then
echo ""
warn "Remote share exists but is empty: $dir"
warn "$ICON_HEALTH Remote share exists but is empty: $dir"
warn "Drives may not be mounted on $REMOTE_SERVER_NAME — aborting to protect data"
info "Hint: Verify array and drive assignments on $REMOTE_SERVER_NAME before retrying"
echo ""
exit 1
fi
success "Remote share verified: $dir"
info "$ICON_HEALTH Remote share verified: $dir"
}
# -----------------------------------------------------------------------------------------------
@@ -276,7 +307,7 @@ check_remote_disks() {
if [[ -z "$DISK_PATHS" ]]; then
echo ""
error "No disks found backing share $share_name on $REMOTE_SERVER_NAME"
error "$ICON_DISK No disks found backing share $share_name on $REMOTE_SERVER_NAME"
warn "Share may not exist on any disk or array may not be started"
info "Hint: Check array and share configuration on $REMOTE_SERVER_NAME"
echo ""
@@ -286,7 +317,6 @@ check_remote_disks() {
local all_ok=true
while IFS= read -r disk_share_path; do
# Extract the disk mountpoint — e.g. /mnt/disk8 from /mnt/disk8/Movies
local disk_mount
disk_mount=$(dirname "$disk_share_path")
local disk_name
@@ -296,9 +326,9 @@ check_remote_disks() {
"mountpoint -q '$disk_mount' && echo yes || echo no" 2>/dev/null)
if [[ "$MOUNTED" == "yes" ]]; then
success "$ICON_DISK $disk_name online$share_name present"
info "$ICON_DISK $disk_name $ICON_RUNNING$share_name present"
else
error "$disk_name is not mounted$share_name may be incomplete"
error "$ICON_DISK $disk_name $ICON_STOPPED$share_name missing or incomplete"
all_ok=false
fi
done <<< "$DISK_PATHS"
@@ -347,12 +377,12 @@ stop_containers() {
RUNNING_CONTAINERS+=("$c")
if ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker stop $c" >/dev/null; then
success "$c stopped"
echo "$ICON_STOPPED $c stopped"
else
error "Failed to stop $c"
fi
else
warn "$c is not running, skipping"
echo "$ICON_NOT_RUNNING $c is not running, skipping"
fi
done
}
@@ -388,9 +418,9 @@ start_containers() {
sleep "$CONTAINER_DELAY"
fi
echo "$ICON_RUN Starting $c..."
echo "$ICON_START Starting $c..."
if ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker start $c" >/dev/null; then
success "$c started"
echo "$ICON_STARTED $c started"
else
error "Failed to start $c"
fi
@@ -421,7 +451,7 @@ get_rsync_opts() {
# Useful for verifying profile resolution and variable state before a live run.
# -----------------------------------------------------------------------------------------------
show_status() {
echo "===== STATUS ====="
echo "===== $ICON_SUMMARY STATUS ====="
echo "Local: $LOCAL_SERVER_NAME"
echo "Remote: $REMOTE_SERVER_NAME"
echo "IP: $REMOTE_SERVER"
@@ -431,5 +461,5 @@ show_status() {
echo "Containers: ${CRITICAL_CONTAINER_NAMES[*]}"
echo "Delayed: ${DELAYED_CONTAINERS[*]}"
echo "Excludes: ${EXCLUDE_DIRS[*]}"
echo "=================="
echo "========================"
}