diff --git a/Master.conf b/Master.conf index 7cd568c..4db225b 100644 --- a/Master.conf +++ b/Master.conf @@ -2,67 +2,21 @@ #----------------------------------------------------------------------------------------------- #----------------------------- Master Variables for unRAID scripts ----------------------------- #----------------------------------------------------------------------------------------------- -#----------------- User Variables, Please adjust here in Master.conf as needed ----------------- -#----------------------------------------------------------------------------------------------- -# This is the master.conf file, it contains all the variables used by -# all scripts. It is sourced by each script at runtime, so any changes here will -# affect all scripts immediately. This is where you should adjust any settings or variables -# that you want to apply globally across all your scripts -# -#This allows for one centralized location for all your configurations, making it easier to manage -# and maintain your scripts. You can adjust the variables below as needed. -# -#----------------------------------------------------------------------------------------------- -#---------------End Of User Variables, Please adjust here in Master.conf as needed ------------- -#----------------------------------------------------------------------------------------------- -# Host and Remote Detection -# Define the hostnames of both servers +# Hostnames of both servers, used for SSH key mapping and remote detection (Actual UunRAID's Host Names) HOST1="unRAID-Gmer4Lfe" HOST2="unRAID-Jayred365" -# Detect local hostname -LOCAL_HOSTNAME="$(hostname)" -if [[ "$LOCAL_HOSTNAME" == "$HOST1" ]]; then - LOCAL_SERVER_NAME="$HOST1" - REMOTE_SERVER_NAME="$HOST2" -elif [[ "$LOCAL_HOSTNAME" == "$HOST2" ]]; then - LOCAL_SERVER_NAME="$HOST2" - REMOTE_SERVER_NAME="$HOST1" -else - echo "Error: Local hostname ($LOCAL_HOSTNAME) not recognized." - exit 1 -fi -echo "Local server: $LOCAL_SERVER_NAME" -echo "Remote server: $REMOTE_SERVER_NAME" - -# Remote Server Ip Resolution -# Resolve Tailscale IP dynamically -REMOTE_SERVER=$(tailscale ip -4 "$REMOTE_SERVER_NAME" 2>/dev/null) -if [[ -z "$REMOTE_SERVER" ]]; then - echo "Error: Could not resolve Tailscale IP for $REMOTE_SERVER_NAME" - exit 1 -fi - - -# SSH Key Mapping -SSH_KEYS["$HOST1|$HOST2"]="/root/.ssh/Gmer4Lfe-rsync-key" -SSH_KEYS["$HOST2|$HOST1"]="/root/.ssh/Jayred365-rsync-key" - -KEY_ID="$LOCAL_SERVER_NAME|$REMOTE_SERVER_NAME" -if [[ -n "${SSH_KEYS[$KEY_ID]}" ]]; then - SSH_KEY="${SSH_KEYS[$KEY_ID]}" -else - echo "Error: No SSH key defined for $LOCAL_SERVER_NAME โ†’ $REMOTE_SERVER_NAME" - exit 1 -fi -echo "Using SSH key: $SSH_KEY" +# SSH Key Mapping (used for rsync scripts to determine which SSH key to use based on source and destination) +declare -A SSH_KEYS +SSH_KEYS["unRAID-Gmer4Lfe|unRAID-Jayred365"]="/root/.ssh/Gmer4Lfe-rsync-key" +SSH_KEYS["unRAID-Jayred365|unRAID-Gmer4Lfe"]="/root/.ssh/Jayred365-rsync-key" #----------------------------------------------------------------------------------------------- -#----------------------------- Global Defaults -------------------------------------------------- +#----------------- User Variables, Please adjust here in Master.conf as needed ----------------- #----------------------------------------------------------------------------------------------- -# Used when a profile does not match +#--------------------Rsync Script Defaults----------------------- # Network speed limit (KB/s) BW_LIMIT=12500 # Retry logic @@ -79,60 +33,76 @@ DELAYED_CONTAINERS=("") CONTAINER_DELAY=5 # Not include logs during transfer EXCLUDE_DIRS=("") + +#-------------------- unRAID essentail scripts ------------------ +# unRAID reboot script user warning time (seconds) +REBOOT_SLEEP=300 +# unRAID mover stop script timeout (seconds) +MOVER_STOP_TIMEOUT=300 +# docker_syslog_filter.sh filter file path +FILTER_FILE="/etc/rsyslog.d/ignore-docker-veth.conf" +# php_fpm_max_children.sh php-fpm config file path +PHP_CONF="/etc/php-fpm.d/www.conf" +# php_fpm_max_children.sh max children value +PHP_MAX_CHILDREN=250 + +#---------------------------------------------------------------------------------------------- +#----------------------------------- Profile System ------------------------------------------- +#---------------------------------------------------------------------------------------------- +# Profiles are mainly used for rsync operations, but can be used for any variable that needs +# to be different based on the source or destination. # -# Profile System # Profiles are inferred from the directory basename (lowercased) -# Max rsync processes per profile declare -A PROFILE_MAX_PROCS PROFILE_MAX_PROCS["arrs_stack"]=2 PROFILE_MAX_PROCS["critical-data"]=2 PROFILE_MAX_PROCS["gmer4lfe"]=1 PROFILE_MAX_PROCS["important-data"]=2 PROFILE_MAX_PROCS["emby"]=1 -# Bandwidth limits per profile (KB/s, 0 = unlimited) + declare -A PROFILE_BW_LIMIT PROFILE_BW_LIMIT["arrs_stack"]=5000 PROFILE_BW_LIMIT["critical-data"]=9500 PROFILE_BW_LIMIT["gmer4lfe"]=8000 PROFILE_BW_LIMIT["important-data"]=9500 PROFILE_BW_LIMIT["emby"]=8000 -# Retry logic per profile + declare -A PROFILE_RETRY_COUNT PROFILE_RETRY_COUNT["arrs_stack"]=3 PROFILE_RETRY_COUNT["critical-data"]=3 PROFILE_RETRY_COUNT["gmer4lfe"]=3 PROFILE_RETRY_COUNT["important-data"]=3 PROFILE_RETRY_COUNT["emby"]=3 -# Sleep between retries per profile (seconds) + declare -A PROFILE_SLEEP PROFILE_SLEEP["arrs_stack"]=300 PROFILE_SLEEP["critical-data"]=300 PROFILE_SLEEP["gmer4lfe"]=300 PROFILE_SLEEP["important-data"]=300 PROFILE_SLEEP["emby"]=300 -# Containers to stop/start per profile (space-separated strings) + declare -A PROFILE_CRITICAL_CONTAINER_NAMES PROFILE_CRITICAL_CONTAINER_NAMES["arrs_stack"]="Sonarr Lidarr Readarr Radarr Prowlarr Bazarr Pinchflat" PROFILE_CRITICAL_CONTAINER_NAMES["critical-data"]="Mariadb-Authelia Redis-Authelia Lldap-Gmer4Lfe NginxProxyManager Authelia" PROFILE_CRITICAL_CONTAINER_NAMES["gmer4lfe"]="Organizrv2-Gmer4Lfe UptimeKuma-Gmer4Lfe VaultWarden-Gmer4Lfe" PROFILE_CRITICAL_CONTAINER_NAMES["important-data"]="Postgres-NextCloud NextCloud" PROFILE_CRITICAL_CONTAINER_NAMES["emby"]="" -# Delayed containers per profile (space-separated strings) + declare -A PROFILE_DELAYED_CONTAINERS PROFILE_DELAYED_CONTAINERS["arrs_stack"]="" PROFILE_DELAYED_CONTAINERS["critical-data"]="Authelia" PROFILE_DELAYED_CONTAINERS["gmer4lfe"]="" PROFILE_DELAYED_CONTAINERS["important-data"]="NextCloud" PROFILE_DELAYED_CONTAINERS["emby"]="" -# Delay in seconds before starting delayed containers per profile (seconds) + declare -A PROFILE_CONTAINER_DELAY PROFILE_CONTAINER_DELAY["arrs_stack"]=5 PROFILE_CONTAINER_DELAY["critical-data"]=10 PROFILE_CONTAINER_DELAY["gmer4lfe"]=5 PROFILE_CONTAINER_DELAY["important-data"]=10 PROFILE_CONTAINER_DELAY["emby"]=5 -# Not include logs or other file types during transfer per profile + declare -A PROFILE_EXCLUDE_DIRS PROFILE_EXCLUDE_DIRS["arrs_stack"]="logs *.tmp" PROFILE_EXCLUDE_DIRS["critical-data"]="logs *.tmp" @@ -140,5 +110,5 @@ PROFILE_EXCLUDE_DIRS["gmer4lfe"]="logs *.tmp" PROFILE_EXCLUDE_DIRS["important-data"]="logs *.tmp" PROFILE_EXCLUDE_DIRS["emby"]="logs *.tmp" #----------------------------------------------------------------------------------------------- -#----------------------------- End of Master Config --------------------------------------------- +#---------------End Of User Variables, Please adjust here in Master.conf as needed ------------- #----------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/common.sh b/common.sh index ccaaf60..e1940f6 100644 --- a/common.sh +++ b/common.sh @@ -17,11 +17,10 @@ #---------------End Of User Variables, Please adjust in Master.conf as needed ------------------ #----------------------------------------------------------------------------------------------- -# Load Master.conf relative to calling script +# Load Master.conf load_master_conf() { local script_dir script_dir="$(cd "$(dirname "${BASH_SOURCE[1]}")" && pwd)" - local master_conf="$script_dir/../Master.conf" if [ -f "$master_conf" ]; then @@ -33,7 +32,7 @@ load_master_conf() { fi } -# Parse CLI arguments (flags + VAR=value overrides) +# Parse CLI args parse_args() { DRY_RUN=${DRY_RUN:-false} @@ -43,48 +42,75 @@ parse_args() { local VAR_VALUE="${ARG#*=}" if declare -p "$VAR_NAME" &>/dev/null; then - if [[ "$VAR_NAME" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then - printf -v "$VAR_NAME" '%s' "$VAR_VALUE" - echo "Overriding $VAR_NAME -> $VAR_VALUE" - else - echo "Warning: Invalid variable name $VAR_NAME" - fi + printf -v "$VAR_NAME" '%s' "$VAR_VALUE" + echo "Overriding $VAR_NAME -> $VAR_VALUE" else echo "Warning: Unknown variable $VAR_NAME, ignoring." fi else case "$ARG" in - --dry-run|-n) - DRY_RUN=true - ;; + --dry-run|-n) DRY_RUN=true ;; --help|-h) echo "Usage: script [--dry-run|-n] [VAR=value ...]" - exit 0 - ;; + exit 0 ;; *) - echo "Warning: Unknown argument $ARG" - ;; + echo "Warning: Unknown argument $ARG" ;; esac fi done } -# Validate integer (non-negative) +# Validate integer validate_int() { local name="$1" local value="$2" - if ! [[ "${value:-}" =~ ^[0-9]+$ ]]; then echo "Error: $name must be a non-negative integer." exit 1 fi } -# Optional: require variable to be set +# Require variable to be set require_var() { local var="$1" if [[ -z "${!var:-}" ]]; then echo "Error: Required variable $var is not set." exit 1 fi +} + +# Host and Remote Detection +detect_hosts() { + LOCAL_HOSTNAME="$(hostname)" + + if [[ "$LOCAL_HOSTNAME" == "$HOST1" ]]; then + LOCAL_SERVER_NAME="$HOST1" + REMOTE_SERVER_NAME="$HOST2" + elif [[ "$LOCAL_HOSTNAME" == "$HOST2" ]]; then + LOCAL_SERVER_NAME="$HOST2" + REMOTE_SERVER_NAME="$HOST1" + else + echo "Error: Local hostname ($LOCAL_HOSTNAME) not recognized." + exit 1 + fi + + echo "Local server: $LOCAL_SERVER_NAME" + echo "Remote server: $REMOTE_SERVER_NAME" + + # Resolve Tailscale IP dynamically + REMOTE_SERVER=$(tailscale ip -4 "$REMOTE_SERVER_NAME" 2>/dev/null) + if [[ -z "$REMOTE_SERVER" ]]; then + echo "Error: Could not resolve Tailscale IP for $REMOTE_SERVER_NAME" + exit 1 + fi + + # Determine SSH Key + KEY_ID="$LOCAL_SERVER_NAME|$REMOTE_SERVER_NAME" + if [[ -n "${SSH_KEYS[$KEY_ID]}" ]]; then + SSH_KEY="${SSH_KEYS[$KEY_ID]}" + else + echo "Error: No SSH key defined for $LOCAL_SERVER_NAME โ†’ $REMOTE_SERVER_NAME" + exit 1 + fi + echo "Using SSH key: $SSH_KEY" } \ 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..7d696ff --- /dev/null +++ b/unRAID Essentials/clear_logs.sh @@ -0,0 +1,79 @@ +#!/bin/bash +set -e + +#----------------------------------------------------------------------------------------------- +# Clear Unraid system logs and Docker container logs safely +#----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../common.sh" + +# Load central config +load_master_conf + +# Parse CLI args (supports --dry-run) +parse_args "$@" + +# Colors for output +RED="\033[0;31m" +GREEN="\033[0;32m" +YELLOW="\033[1;33m" +RESET="\033[0m" + +# Log files to clear (can also be overridden in Master.conf) +LOG_FILES=("${LOG_FILES[@]:-/var/log/syslog /var/log/messages /var/log/dmesg}") + +# Require root +if [ "$EUID" -ne 0 ]; then + printf "${RED}โŒ Please run as root.${RESET}\n" + exit 1 +fi + +echo -e "${YELLOW}Starting log cleanup...${RESET}\n" + +# Functions +clear_file() { + local file="$1" + if [ ! -f "$file" ]; then + printf "${RED}Not found:${RESET} %s\n" "$file" + return + fi + + if [ "$DRY_RUN" = true ]; then + printf "${YELLOW}Would clear:${RESET} %s\n" "$file" + else + : > "$file" + printf "${GREEN}Cleared:${RESET} %s\n" "$file" + fi +} + +clear_docker_logs() { + if [ ! -d /var/lib/docker/containers ]; then + printf "${RED}Docker containers directory not found. Skipping Docker log cleanup.${RESET}\n" + return + fi + + local files + files=$(find /var/lib/docker/containers/ -name "*-json.log" 2>/dev/null) + for file in $files; do + if [ "$DRY_RUN" = true ]; then + printf "${YELLOW}Would clear Docker log:${RESET} %s\n" "$file" + else + : > "$file" + printf "${GREEN}Cleared Docker log:${RESET} %s\n" "$file" + fi + done +} + +# MAIN +for log in "${LOG_FILES[@]}"; do + clear_file "$log" +done + +clear_docker_logs + +if [ "$DRY_RUN" = true ]; then + printf "\n${YELLOW}๐Ÿงช Dry run complete. No files were cleared.${RESET}\n" +else + printf "\n${GREEN}๐ŸŽ‰ Done clearing logs.${RESET}\n" +fi \ 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..4a40834 --- /dev/null +++ b/unRAID Essentials/docker_syslog_filter.sh @@ -0,0 +1,55 @@ +#!/bin/bash +set -e + +#----------------------------------------------------------------------------------------------- +# Suppress noisy Docker veth/docker0 syslog messages on Unraid boot +#----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../common.sh" + +# Load central config +load_master_conf + +# Parse CLI args (supports --dry-run) +parse_args "$@" + +# Filter file location (can also be overridden in Master.conf) +FILTER_FILE=${FILTER_FILE:-"/etc/rsyslog.d/ignore-docker-veth.conf"} + +# Require root +if [ "$EUID" -ne 0 ]; then + echo -e "\033[0;31mโŒ Please run as root.${RESET}\n" + exit 1 +fi + +# Functions +create_filter() { + if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would create rsyslog filter file at $FILTER_FILE" + else + echo "Creating rsyslog filter file at $FILTER_FILE" + cat <<'EOF' > "$FILTER_FILE" +if ($msg contains "veth" or $msg contains "docker0") then { + stop +} +EOF + fi +} + +restart_rsyslog() { + if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would restart rsyslog: /etc/rc.d/rc.rsyslogd restart" + else + echo "Restarting rsyslog..." + /etc/rc.d/rc.rsyslogd restart + fi +} + +# MAIN +echo "==== Docker Syslog Filter Script Started: $(date) ====" + +create_filter +restart_rsyslog + +echo "โœ… Docker veth/docker0 syslog filter applied." \ 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..740c01f --- /dev/null +++ b/unRAID Essentials/mover-stop.sh @@ -0,0 +1,64 @@ +#!/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/../common.sh" + +# Load central config +load_master_conf + +# Parse CLI args (flags + VAR=value) +parse_args "$@" + +# Optional: MOVER_STOP_TIMEOUT in seconds (default from Master.conf or 30s) +MOVER_STOP_TIMEOUT=${MOVER_STOP_TIMEOUT:-30} +validate_int MOVER_STOP_TIMEOUT "$MOVER_STOP_TIMEOUT" + +# Functions + +notify_users() { + wall "โš ๏ธ Unraid Mover will stop in ${MOVER_STOP_TIMEOUT} second(s)." +} + +check_mover_running() { + pgrep -f "emhttp.*Mover" >/dev/null 2>&1 +} + +stop_mover() { + if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would stop the Mover process" + else + echo "Stopping Mover..." + # Unraid native way: kill the mover process gracefully + pkill -f "emhttp.*Mover" + fi +} + +# MAIN + +echo "==== Mover Stop Script Started: $(date) ====" + +if check_mover_running; then + notify_users + sleep "$MOVER_STOP_TIMEOUT" + stop_mover + echo "Mover stopped." +else + echo "Mover is not running." +fi \ 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..a719d6b --- /dev/null +++ b/unRAID Essentials/php_fpm_max_children.sh @@ -0,0 +1,50 @@ +#!/bin/bash +set -e + +#----------------------------------------------------------------------------------------------- +# Persistently set PHP-FPM pm.max_children on Unraid +#----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../common.sh" + +# Load central config +load_master_conf + +# Parse CLI args (supports --dry-run) +parse_args "$@" + +# Require root +if [ "$EUID" -ne 0 ]; then + echo -e "\033[0;31mโŒ Please run as root.${RESET}\n" + exit 1 +fi + +validate_int PHP_MAX_CHILDREN "$PHP_MAX_CHILDREN" + +# Functions +apply_php_max_children() { + local target="pm.max_children = $PHP_MAX_CHILDREN" + + if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would set PHP-FPM max_children to $PHP_MAX_CHILDREN in $PHP_CONF" + echo "[DRY-RUN] Would restart PHP-FPM service" + else + echo "Applying persistent PHP-FPM max_children = $PHP_MAX_CHILDREN" + sed -i "s/^pm\.max_children.*/$target/" "$PHP_CONF" + + # Restart PHP-FPM + /etc/rc.d/rc.php-fpm restart + + local current + current=$(grep -E "^pm\.max_children" "$PHP_CONF") + logger "Userscript: php-fpm setting applied: $current" + + echo "PHP-FPM max_children persistently set to: $current" + echo "PHP-FPM restarted successfully." + fi +} + +# MAIN +echo "==== PHP-FPM Max Children Script Started: $(date) ====" +apply_php_max_children \ 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..ffbabbc --- /dev/null +++ b/unRAID Essentials/rsync_stop.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e + +#----------------------------------------------------------------------------------------------- +# Stop all running Rsync processes for Unraid +#----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../common.sh" + +# Load central config +load_master_conf + +# Parse CLI args (supports --dry-run) +parse_args "$@" + +# Functions + +stop_rsync_processes() { + if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would stop all running rsync processes" + else + echo "Stopping all rsync processes..." + if pkill -f rsync; then + echo "All rsync processes stopped successfully." + else + echo "No rsync processes found or failed to stop." + fi + fi +} + +# MAIN +echo "==== Rsync Stop Script Started: $(date) ====" + +stop_rsync_processes \ No newline at end of file diff --git a/unRAID Essentials/server-reboot.sh b/unRAID Essentials/server-reboot.sh index e162976..d753285 100644 --- a/unRAID Essentials/server-reboot.sh +++ b/unRAID Essentials/server-reboot.sh @@ -7,7 +7,6 @@ #----------------------------------------------------------------------------------------------- # # User variables can be adjusted in Master.conf -# This script is using the SLEEP Variable from Master.conf for the delay before reboot # # Scripts now just contain runtime logic # @@ -27,23 +26,25 @@ load_master_conf # Parse CLI args (flags + VAR=value) parse_args "$@" -# Validate SLEEP -validate_int SLEEP "$SLEEP" +# Validate REBOOT_SLEEP +validate_int REBOOT_SLEEP "$REBOOT_SLEEP" # --- Functions - notify_users() { - wall "โš ๏ธ Unraid server will reboot in ${SLEEP} second(s). Save your work." + wall "โš ๏ธ Unraid server will reboot in ${REBOOT_SLEEP} second(s). Save your work." } # --- MAIN - echo "==== Scheduled Reboot Script Started: $(date) ====" # Optional warning before reboot -if [ "$SLEEP" -gt 0 ]; then +if [ "$REBOOT_SLEEP" -gt 0 ]; then notify_users - sleep "$SLEEP" + sleep "$REBOOT_SLEEP" + + + + fi # Stop Docker diff --git a/unRAID Essentials/user_scripts_stop.sh b/unRAID Essentials/user_scripts_stop.sh new file mode 100644 index 0000000..8aae97e --- /dev/null +++ b/unRAID Essentials/user_scripts_stop.sh @@ -0,0 +1,44 @@ +#!/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/../common.sh" + +# Load central config +load_master_conf + +# Parse CLI args (supports --dry-run) +parse_args "$@" + +# Functions + +stop_user_scripts() { + # Get PIDs of running user scripts + local pids + pids=$(/usr/bin/ps -eo pid,cmd | grep "/tmp/user.scripts" | grep -v grep | awk '{print $1}') + + if [ -z "$pids" ]; then + echo "No running user scripts found." + return + fi + + for pid in $pids; do + if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would kill user script with PID $pid" + else + echo "Killing user script with PID $pid" + kill "$pid" + fi + done + + echo "All user scripts stopped." +} + +# MAIN +echo "==== User Scripts Stop Script Started: $(date) ====" + +stop_user_scripts \ 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..b94fb1d --- /dev/null +++ b/unRAID Essentials/zfs_memory_snapshot.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -e + +#----------------------------------------------------------------------------------------------- +# ZFS ARC & Memory Snapshot for Unraid +#----------------------------------------------------------------------------------------------- + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../common.sh" + +# Load central config +load_master_conf + +# Parse CLI args (supports --dry-run) +parse_args "$@" + +# Functions +show_zfs_arc() { + echo "--- ARC / Metadata Stats ---" + grep -iE '^(c|meta|arc_meta_used|demand_metadata_misses|mru_ghost_metadata|mfu_ghost_metadata)' /proc/spl/kstat/zfs/arcstats +} + +show_memory_status() { + echo "--- Memory Status ---" + free -h | awk 'NR==1 || /Mem:/' +} + +# MAIN +echo "===== ZFS ARC & Memory Snapshot: $(date) =====" + +if [ "$DRY_RUN" = true ]; then + echo "[DRY-RUN] Would display ARC and memory stats" +else + echo "" + show_zfs_arc + echo "" + show_memory_status +fi + +echo "==============================================" \ No newline at end of file