-
-
[SUPPORT] stephondoestech - UnraidConfigGuardian
Whats when the IP from the Docker Socket changed? I don't see an Option to set a fixed IP for that? For example actually 172.17.0.100 on the next Docker Container Restart or Server Reboot its the IP 172.17.0.50. The IP in the Guardian Config Template are the old one and no more working because of that.
-
[Plugin] Uptime Kuma monitor widget for Unraid Dashboard
Any News about that?
-
[SUPPORT] Uptime Kuma - CorneliousJD Repo
Can you added it to CA for all?
-
[SUPPORT] Uptime Kuma - CorneliousJD Repo
Can you update the Docker Container Template in the CA with the latest Changes like Version 2 and others?
-
Identifizierung von flash oder internal boot sowie Lizenzierung
Hab es gefunden und im Backup Script ergänzt, was ab 7.3.x wegen der boot, Internal Boot, ... statt flash Änderungen einer Anpassung Bedarf da es sonst nicht mehr korrekt funktioniert und das rootfs voll schreiben kann.
-
Identify Boot and License Type
The Detection and ... are include! Many Thanks for the Help!
-
Latest (super easy) method for automated flash zip backup!
The expanded and corrected versions for V7.3.x and the changes to ‘boot’, ‘Internal Boot’, … instead of ‘flash’. Older operating system versions should also work, but have not really been tested as there are currently no older versions, such as V6.x available. #!/bin/bash ############################################################################# # Flash or Boot Backup, License & Boot Analysis # Description: Automates Flash or Boot Backup Creation, Retention, License & Boot Analysis ############################################################################# # ============================================================================= # 1. CONFIGURATION & IDENTIFIERS # ============================================================================= # ----------------------------------------------------------------------------- # GENERAL SETTINGS # ----------------------------------------------------------------------------- HOST_NAME=$(hostname) MIN_DISKS=3 # ----------------------------------------------------------------------------- # CENTRALIZED IDENTIFIER # ----------------------------------------------------------------------------- SCRIPT_TITLE="Flash or Boot Backup, License & Boot Analysis" # File Naming Conventions LOG_BASENAME="Boot_Backup_Analysis" LOG_FILE_PATTERN="${LOG_BASENAME}_*.log" # ----------------------------------------------------------------------------- # RETENTION POLICIES # ----------------------------------------------------------------------------- BACKUP_RETENTION_DAYS=150 MAX_BACKUPS_TO_KEEP=15 LOG_RETENTION_DAYS=90 MAX_LOG_FILES_TO_KEEP=30 # ----------------------------------------------------------------------------- # FEATURE FLAGS # ----------------------------------------------------------------------------- ENABLE_LICENSE_CHECK=true ENABLE_BOOT_CHECK=true ENABLE_HARDWARE_CHECK=true ENABLE_SYSTEM_CHECK=true ENABLE_BACKUP_CREATE=true ENABLE_BACKUP_RETENTION=true ENABLE_LOG_RETENTION=true ENABLE_NOTIFICATION=true SHOW_CLI_OUTPUT=true # ----------------------------------------------------------------------------- # PATH DEFINITIONS # ----------------------------------------------------------------------------- BACKUP_BASE_DIR="/mnt/user/Backup_${HOST_NAME}/boot" ARCHIVE_SUBDIR="Backup_Reports" LOG_LOCAL_SUBDIR="Backup_Logs_on_Boot" ARCHIVE_LOG_DIR="${BACKUP_BASE_DIR}/${ARCHIVE_SUBDIR}" LOCAL_LOG_DIR="/boot/${LOG_LOCAL_SUBDIR}" LOG_FILE_NAME="${LOG_BASENAME}_${HOST_NAME}_$(date '+%Y-%m-%d_%H-%M-%S').log" LOCAL_LOG_PATH="${LOCAL_LOG_DIR}/${LOG_FILE_NAME}" ARCHIVE_LOG_PATH="${ARCHIVE_LOG_DIR}/${LOG_FILE_NAME}" LAST_RUN_LOG="${ARCHIVE_LOG_DIR}/Last_Run.log" LOG_FILE_PATH="$ARCHIVE_LOG_PATH" VAR_INI_PATH="/var/local/emhttp/var.ini" # ----------------------------------------------------------------------------- # MODULE NAMES # ----------------------------------------------------------------------------- MOD_TITLE_1="LICENSE STATUS" MOD_TITLE_2="BOOT MEDIUM ANALYSIS" MOD_TITLE_3="HARDWARE CHECK" MOD_TITLE_4="SYSTEM INTEGRITY CHECK" MOD_TITLE_5="CREATE BACKUP" MOD_TITLE_6="APPLY BACKUP RETENTION" MOD_TITLE_7="APPLY LOG RETENTION" MOD_TITLE_8="SEND NOTIFICATION" # ----------------------------------------------------------------------------- # MESSAGE TEXTS # ----------------------------------------------------------------------------- MSG_SUCCESS="SUCCESS" MSG_ERROR="ERROR" MSG_WARNING="WARNING" MSG_INFO="INFO" MSG_COPYING_BACKUP="Copying Backup to:" MSG_SUCCESS_COPY="Copy completed successfully." MSG_INTEGRITY_CHECK="Checking Integrity Check of" MSG_SUCCESS_INTEGRITY="Integrity Check passed." MSG_SYMLINK_REMOVED="Temporary Symlink removed." MSG_BACKUP_CREATED="Backup File created:" MSG_LOCATION="Location:" MSG_SUCCESS_ALL_STEPS="All Routine Steps completed successfully." MSG_BACKUP_ANALYSIS_MAINTENANCE_COMPLETED="Backup, Analysis & Maintenance completed." MSG_CONFIG_FILE_NOT_FOUND="Configuration File not found." MSG_VARINI_NOT_FOUND="var.ini not found." MSG_NO_TPM_DEVICE="No TPM Device available." MSG_USB_STICK_DETECTED="USB Stick detected for License." MSG_NO_USB_STICK="No USB Stick detected, but Flash License active!" MSG_TP_M_MODE="TPM Mode: No USB Stick required for License." MSG_UNZIP_NOT_FOUND="'unzip' Command not found. Integrity Check impossible." MSG_FLASH_BACKUP_FAILED="Flash Backup Tool failed." MSG_INVALID_FILENAME="Invalid Filename generated." MSG_SOURCE_FILE_MISSING="Source File does not exist." MSG_COPY_FAILED="Copying Backup File failed." MSG_BACKUP_CORRUPTED="Backup File corrupted! Removing defective File." MSG_CHANGE_DIR_FAILED="Change to Directory failed." MSG_PROCESS_ABORTED="Process aborted: Manual Cleanup required." MSG_WARNING_IGNORED="Warning ignored." MSG_NO_STALE_FILES="No stale temporary Files found." MSG_STALE_FILES_FOUND="stale temporary Files found." MSG_ARRAY_INTEGRITY_CONFIRMED="Array Integrity confirmed." MSG_NO_LICENSE_DETECTED="License Type not detected or invalid." # ============================================================================= # 2. HELPER FUNCTIONS # ============================================================================= print_header() { echo "==============================================================" echo " ${SCRIPT_TITLE}" echo "==============================================================" echo "HOST: $(hostname)" echo "TIMESTAMP: $(date '+%d.%m.%Y %H:%M')" echo "----------------------------------------" } print_section() { echo "" echo "[${1}]" echo "--------------------------------------------------------------" } print_msg() { local level="$1" msg="$2" case "$level" in SUCCESS) echo "[${MSG_SUCCESS}] $msg" ;; ERROR) echo "[${MSG_ERROR}] $msg" ;; WARNING) echo "[${MSG_WARNING}] $msg" ;; INFO) echo "[${MSG_INFO}] $msg" ;; *) echo "$msg" ;; esac } log_to_file() { local msg="$1" local timestamped_msg="[$(date '+%Y-%m-%d %H:%M:%S')] [$(hostname)] $msg" echo "$timestamped_msg" >> "$LOG_FILE_PATH" } mask_guid_format() { local guid="$1" if [[ -z "$guid" ]]; then echo "---"; return; fi local result="" sep="" IFS='-' read -ra PARTS <<< "$guid" for part in "${PARTS[@]}"; do if [[ ${#part} -gt 2 ]]; then result+="${sep}${part:0:2}-****" else result+="${sep}${part}-****"; fi sep="-" done echo "$result" } clean_vendor_name() { local raw_vendor="$1" local vendor=$(echo "$raw_vendor" | awk '{print $1}') if [[ "$vendor" == *"Cruzer"* ]]; then vendor=$(echo "$vendor" | sed 's/Cruzer$//g') elif [[ "$vendor" == *"DataTraveler"* ]]; then vendor=$(echo "$vendor" | sed 's/DataTraveler$//g') elif [[ "$vendor" == *"Flash"* ]]; then vendor=$(echo "$vendor" | sed 's/Flash$//g'); fi echo "$vendor" | xargs } clean_model_name() { local raw_model="$1" local cleaned=$(echo "$raw_model" | sed -E 's/[[:space:]]*[0-9]+\.?[0-9]*(GB|TB|MB|GiB|MiB)[[:space:]]*$//gi') if [[ -z "$cleaned" ]]; then echo "$raw_model"; else echo "$cleaned"; fi } # ============================================================================= # 3. INITIALIZATION # ============================================================================= mkdir -p "$BACKUP_BASE_DIR" || { echo "[${MSG_ERROR}] Cannot create Backup Directory."; exit 1; } mkdir -p "${ARCHIVE_LOG_DIR}" || { echo "[${MSG_ERROR}] Cannot create Archive Log Directory."; exit 1; } mkdir -p "${LOCAL_LOG_DIR}" || { echo "[${MSG_ERROR}] Cannot create Local Log Directory."; exit 1; } touch "$LOCAL_LOG_PATH" 2>/dev/null || exit 1 touch "$ARCHIVE_LOG_PATH" 2>/dev/null || exit 1 { echo "==========================================" echo "START ${SCRIPT_TITLE}" echo "Hostname: ${HOST_NAME}" echo "Backup Target: ${BACKUP_BASE_DIR}" echo "Local Log: ${LOCAL_LOG_PATH}" echo "Archive Log: ${ARCHIVE_LOG_PATH}" echo "==========================================" } > "$LOG_FILE_PATH" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_header fi # ============================================================================= # 4. MODULES # ============================================================================= # --- MODULE 1: LICENSE STATUS --- if [ "$ENABLE_LICENSE_CHECK" = true ]; then log_to_file "---[MODULE 1: ${MOD_TITLE_1}]---" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_1}"; fi SERVER_NAME="" OS_VERSION="" LICENSE_TYPE="" REGTY_RAW="" FLASH_GUID="" TPM_GUID="" REG_GUID="" if [ -f "$VAR_INI_PATH" ]; then SERVER_NAME=$(awk -F'=' '/^NAME=/ {gsub(/"/, "", $2); gsub(/ /, "_", $2); print $2}' "$VAR_INI_PATH") OS_VERSION=$(awk -F'=' '/^version=/ {gsub(/"/, "", $2); print $2}' "$VAR_INI_PATH") REGTY_RAW=$(awk -F'=' '/^regTy=/ {gsub(/"/, "", $2); print $2}' "$VAR_INI_PATH" 2>/dev/null) LICENSE_TYPE="$REGTY_RAW" FLASH_GUID=$(grep '^flashGUID=' "$VAR_INI_PATH" 2>/dev/null | cut -d'"' -f2 | tr -d '[:space:]') TPM_GUID=$(grep '^tpmGUID=' "$VAR_INI_PATH" 2>/dev/null | cut -d'"' -f2 | tr -d '[:space:]') REG_GUID=$(grep '^regGUID=' "$VAR_INI_PATH" 2>/dev/null | cut -d'"' -f2 | tr -d '[:space:]') else print_msg "$MSG_ERROR" "$MSG_CONFIG_FILE_NOT_FOUND" log_to_file "[${MSG_WARNING}] $MSG_VARINI_NOT_FOUND" fi LICENSE_STATUS="UNKNOWN" DEVICE_BINDING="NONE" if [[ "$FLASH_GUID" == "$REG_GUID" ]] && [[ "$FLASH_GUID" != "$TPM_GUID" || -z "$TPM_GUID" ]]; then LICENSE_STATUS="USB_FLASH" DEVICE_BINDING="USB Stick" if [[ -n "$TPM_GUID" ]] && [[ "$FLASH_GUID" != "$TPM_GUID" ]]; then if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_INFO" "TPM Key present, currently not used."; fi log_to_file "[${MSG_INFO}] TPM Key present, currently not used." fi elif [[ "$FLASH_GUID" == "$TPM_GUID" ]] && [[ "$FLASH_GUID" == "$REG_GUID" ]]; then LICENSE_STATUS="FULL_TPM" DEVICE_BINDING="TPM" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_SUCCESS" "System running on full TPM Basis."; fi log_to_file "Binding detected: TPM." elif [[ "$REG_GUID" == "$TPM_GUID" ]]; then LICENSE_STATUS="TPM_MIGRATION" DEVICE_BINDING="TPM" log_to_file "Binding detected: Migration to TPM." else LICENSE_STATUS="INVALID_CONFIG" DEVICE_BINDING="UNKNOWN" log_to_file "[${MSG_WARNING}] GUID Configuration could not be uniquely identified." fi FLASH_MASKED=$(mask_guid_format "$FLASH_GUID") TPM_MASKED=$(mask_guid_format "$TPM_GUID") REG_MASKED=$(mask_guid_format "$REG_GUID") if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "USB LICENSE ID: $FLASH_MASKED" echo "TPM KEY: $TPM_MASKED" echo "ACTIVE REGISTRATION: $REG_MASKED" print_section "${MOD_TITLE_1}" echo "SERVER NAME: ${SERVER_NAME:-Unavailable}" echo "OS VERSION: ${OS_VERSION:-Unavailable}" echo "LICENSE TYPE: ${LICENSE_TYPE:-$MSG_NO_LICENSE_DETECTED}" echo "DETECTED BINDING: ${DEVICE_BINDING} (${LICENSE_STATUS})" echo "----------------------------------------" echo "DETECTED MODE: $LICENSE_STATUS" echo "LICENSE DEVICE TYPE: ${DEVICE_BINDING}" fi log_to_file "Server Name: ${SERVER_NAME:-Unavailable}" log_to_file "OS Version: ${OS_VERSION:-Unavailable}" log_to_file "License Type: ${LICENSE_TYPE:-UNDETERMINED}" log_to_file "Detected Binding: ${DEVICE_BINDING} (${LICENSE_STATUS})" else log_to_file "---[MODULE 1: ${MOD_TITLE_1}]---" log_to_file "[DISABLED]" fi # --- MODULE 2: BOOT MEDIUM ANALYSIS --- if [ "$ENABLE_BOOT_CHECK" = true ]; then log_to_file "---[MODULE 2: ${MOD_TITLE_2}]---" BOOT_MEDIUM_TYPE="UNKNOWN" system_dev_final="" sys_boot_type="Unknown" sys_vendor="" sys_model_clean="" nvme_dev_global=$(lsblk -d -no NAME,TYPE 2>/dev/null | grep 'nvme' | awk '{print $1}' | head -1) sda_dev_global=$(lsblk -d -no NAME,TYPE 2>/dev/null | grep -E '^sd[a-z]$' | awk '{print $1}' | head -1) mmc_dev_global=$(lsblk -d -no NAME,TYPE 2>/dev/null | grep 'mmc' | awk '{print $1}' | head -1) if [ -e "/dev/disk/by-label/flash" ]; then REAL_LINK=$(readlink -f "/dev/disk/by-label/flash") DEVICE_NAME=$(basename "$REAL_LINK") if [[ "$DEVICE_NAME" =~ [0-9]+$ ]]; then PARENT_DEVICE="${DEVICE_NAME%[0-9]*}"; else PARENT_DEVICE="$DEVICE_NAME"; fi TRANSPORT=$(lsblk -no TRAN "$PARENT_DEVICE" 2>/dev/null | tr -d '[:space:]') case "$TRANSPORT" in usb) BOOT_MEDIUM_TYPE="USB Stick Boot" ;; *) SYS_PATH="/sys/block/$PARENT_DEVICE/device" if [ -L "$SYS_PATH" ]; then FULL_PATH=$(readlink -f "$SYS_PATH") if [[ "$FULL_PATH" =~ usb ]]; then BOOT_MEDIUM_TYPE="USB Stick Boot" else BOOT_MEDIUM_TYPE="Internal Boot" fi else BOOT_MEDIUM_TYPE="Internal Boot" fi ;; esac if [[ "$BOOT_MEDIUM_TYPE" == "Internal Boot" ]]; then if [[ -n "$nvme_dev_global" ]]; then system_dev_final="$nvme_dev_global" elif [[ -n "$sda_dev_global" ]]; then system_dev_final="$sda_dev_global" elif [[ -n "$mmc_dev_global" ]]; then system_dev_final="$mmc_dev_global"; fi sys_boot_type="Internal Boot" if [[ -n "$system_dev_final" ]] && [[ -b "/dev/$system_dev_final" ]]; then vendor_raw=$(lsblk -no VENDOR "/dev/$system_dev_final" 2>/dev/null | head -1 | xargs) model_raw=$(lsblk -no MODEL "/dev/$system_dev_final" 2>/dev/null | head -1 | xargs) if [[ -z "$vendor_raw" || "$vendor_raw" == "" ]]; then sys_vendor="(see Model)" else sys_vendor="$vendor_raw"; fi sys_model_clean=$(clean_model_name "$model_raw") fi fi log_to_file "Boot Medium Type: ${BOOT_MEDIUM_TYPE}" else log_to_file "[${MSG_WARNING}] /dev/disk/by-label/flash not found." fi if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "BOOT MEDIUM TYPE: ${BOOT_MEDIUM_TYPE}" echo "----------------------------------------" print_section "${MOD_TITLE_2}" lic_vendor="-" lic_model_clean="-" lic_type="" if [[ "$DEVICE_BINDING" == "USB Stick" ]]; then usb_line=$(lsusb 2>/dev/null | grep -iE 'Kingston|Sandisk|Lexar|Transcend|ADATA|SanDisk' | head -1) if [[ -n "$usb_line" ]]; then raw_full=$(echo "$usb_line" | sed 's/.*ID [0-9a-f:]* //' | sed 's/ *Corp\. //g' | sed 's/ *Inc\. //g' | xargs) lic_vendor=$(echo "$raw_full" | awk '{print $1}') lic_vendor=$(clean_vendor_name "$lic_vendor") if [[ "$lic_vendor" == "$raw_full" ]]; then lic_model_clean="Unknown USB Device" else mod_part=$(echo "$raw_full" | sed "s/^${lic_vendor}[[:space:]]*//"); lic_model_clean=$(clean_model_name "$mod_part"); fi fi [[ -z "$lic_vendor" ]] && lic_vendor="Unknown" [[ -z "$lic_model_clean" ]] && lic_model_clean="Unknown" lic_type="USB Stick" else lic_type="TPM" fi echo "LICENSE DEVICE:" echo " TYPE: $lic_type" echo " MANUFACTURER: $lic_vendor" echo " MODEL: $lic_model_clean" echo "" echo "SYSTEM DEVICE (OS):" echo " TYPE: $sys_boot_type" echo " MANUFACTURER: $sys_vendor" echo " MODEL: $sys_model_clean" fi else log_to_file "---[MODULE 2: ${MOD_TITLE_2}]---" log_to_file "[DISABLED]" fi # --- MODULE 3: HARDWARE CHECK --- if [ "$ENABLE_HARDWARE_CHECK" = true ]; then if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_3}"; fi log_to_file "---[MODULE 3: ${MOD_TITLE_3}]---" if [ -c /dev/tpm0 ] 2>/dev/null || [ -c /dev/tpmrm0 ] 2>/dev/null; then if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_SUCCESS" "TPM Hardware detected and usable."; fi log_to_file "[${MSG_SUCCESS}] TPM Hardware detected." else if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_WARNING" "$MSG_NO_TPM_DEVICE"; fi log_to_file "[${MSG_WARNING}] $MSG_NO_TPM_DEVICE" fi if [[ "$LICENSE_STATUS" == "USB_FLASH" ]]; then if [[ $(lsusb 2>/dev/null | grep -ciE 'Kingston|Sandisk|Lexar') -eq 0 ]]; then if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_ERROR" "$MSG_NO_USB_STICK"; fi log_to_file "[${MSG_ERROR}] $MSG_NO_USB_STICK" else if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_INFO" "$MSG_USB_STICK_DETECTED"; fi log_to_file "[${MSG_INFO}] $MSG_USB_STICK_DETECTED" fi else if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_INFO" "$MSG_TP_M_MODE"; fi log_to_file "[${MSG_INFO}] $MSG_TP_M_MODE" fi log_to_file "---[${MOD_TITLE_3} COMPLETED]---" log_to_file "" else log_to_file "---[MODULE 3: ${MOD_TITLE_3}]---" log_to_file "[DISABLED]" fi # --- MODULE 4: SYSTEM INTEGRITY CHECK --- if [ "$ENABLE_SYSTEM_CHECK" = true ]; then log_to_file "---[MODULE 4: ${MOD_TITLE_4}]---" STALE_COUNT=$(find /usr/local/emhttp/ -maxdepth 1 -name "*boot-backup*.zip" \( -type f -o -xtype l \) 2>/dev/null | wc -l) if [ "$STALE_COUNT" -gt 0 ]; then log_to_file "[${MSG_WARNING}] ${STALE_COUNT} $MSG_STALE_FILES_FOUND" HAS_STALE_FILES=true if [ -z "$SKIP_DIRTY_CHECK" ] || [ "$SKIP_DIRTY_CHECK" = false ]; then log_to_file "[${MSG_ERROR}] $MSG_PROCESS_ABORTED" exit 1 else log_to_file "[${MSG_INFO}] $MSG_WARNING_IGNORED (SKIP_DIRTY_CHECK=true)." fi else HAS_STALE_FILES=false log_to_file "[${MSG_SUCCESS}] $MSG_NO_STALE_FILES" fi if [ "$MIN_DISKS" -gt 0 ]; then DISK_COUNT=$(ls -d /mnt/disk* 2>/dev/null | wc -l) if [ "$DISK_COUNT" -lt "$MIN_DISKS" ]; then log_to_file "[${MSG_ERROR}] Only ${DISK_COUNT} Disks found. Minimum ${MIN_DISKS} required." exit 1 fi log_to_file "[${MSG_SUCCESS}] $MSG_ARRAY_INTEGRITY_CONFIRMED (${DISK_COUNT} Disks present)." fi log_to_file "---[${MOD_TITLE_4} COMPLETED]---" log_to_file "" else log_to_file "---[MODULE 4: ${MOD_TITLE_4}]---" log_to_file "[DISABLED]" fi # --- MODULE 5: CREATE BACKUP --- BACKUP_FILE="" if [ "$ENABLE_BACKUP_CREATE" = true ]; then log_to_file "---[MODULE 5: ${MOD_TITLE_5}]---" log_to_file "Target Directory: ${BACKUP_BASE_DIR}" log_to_file "Starting native Flash Backup Script..." if ! command -v unzip >/dev/null 2>&1; then log_to_file "[${MSG_ERROR}] $MSG_UNZIP_NOT_FOUND" exit 1 fi BACKUP_RAW_OUTPUT=$(/usr/bin/php -q /usr/local/emhttp/webGui/scripts/flash_backup 2>&1) PHP_EXIT_CODE=$? if [ $PHP_EXIT_CODE -ne 0 ]; then log_to_file "[${MSG_ERROR}] $MSG_FLASH_BACKUP_FAILED (Exit Code: ${PHP_EXIT_CODE})." log_to_file "[DEBUG] PHP Output: ${BACKUP_RAW_OUTPUT}" exit 1 fi BACKUP_FILE=$(echo "$BACKUP_RAW_OUTPUT" | tail -n 1 | xargs) if [ -z "$BACKUP_FILE" ]; then log_to_file "[${MSG_ERROR}] Invalid Filename generated (Empty output)." log_to_file "[DEBUG] PHP Output: ${BACKUP_RAW_OUTPUT}" exit 1 fi SYMLINK_PATH="/usr/local/emhttp/${BACKUP_FILE}" if [ ! -f "$SYMLINK_PATH" ] && [ ! -L "$SYMLINK_PATH" ]; then log_to_file "[${MSG_ERROR}] Source File does not exist: ${SYMLINK_PATH}" exit 1 fi SOURCE_FILE=$(readlink -f "$SYMLINK_PATH" 2>/dev/null || echo "$SYMLINK_PATH") DEST_FILE="${BACKUP_BASE_DIR}/${BACKUP_FILE}" if [ ! -f "$SOURCE_FILE" ]; then log_to_file "[${MSG_ERROR}] Resolved Source File missing: ${SOURCE_FILE}" exit 1 fi if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_INFO}] ${MSG_COPYING_BACKUP} ${DEST_FILE}" fi cp -v "$SOURCE_FILE" "$DEST_FILE" > /dev/null 2>&1 COPY_EXIT=$? if [ $COPY_EXIT -ne 0 ]; then log_to_file "[${MSG_ERROR}] $MSG_COPY_FAILED" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_ERROR" "$MSG_COPY_FAILED"; fi exit 1 fi if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_SUCCESS}] ${MSG_SUCCESS_COPY}" fi log_to_file "Copied Backup to: ${DEST_FILE}" if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_INFO}] ${MSG_INTEGRITY_CHECK} ${BACKUP_FILE}..." fi if ! unzip -t -q "$DEST_FILE" >/dev/null 2>&1; then log_to_file "[${MSG_ERROR}] $MSG_BACKUP_CORRUPTED" rm -f "$DEST_FILE" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_ERROR" "$MSG_BACKUP_CORRUPTED"; fi exit 1 fi log_to_file "[${MSG_SUCCESS}] ${MSG_SUCCESS_INTEGRITY}" if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_SUCCESS}] ${MSG_SUCCESS_INTEGRITY}" fi if [ -L "$SYMLINK_PATH" ]; then rm -f "$SYMLINK_PATH" log_to_file "[${MSG_SUCCESS}] ${MSG_SYMLINK_REMOVED}" if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_SUCCESS}] ${MSG_SYMLINK_REMOVED}" fi fi log_to_file "---[BACKUP CREATION COMPLETED]---" log_to_file "" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_5} COMPLETED" echo "${MSG_BACKUP_CREATED} ${BACKUP_FILE}" echo "${MSG_LOCATION} ${DEST_FILE}" fi log_to_file "---[UPDATE ARCHIVE LOG]---" { echo "=== LAST RUN: ${HOST_NAME} ===" echo "Timestamp: $(date '+%Y-%m-%d %H:%M:%S')" echo "Backup File: ${BACKUP_FILE}" echo "Backup Path: ${DEST_FILE}" echo "Archive Log Path: ${ARCHIVE_LOG_PATH}" echo "Status: SUCCESSFUL" [ -n "$LICENSE_TYPE" ] && echo "License Type: ${LICENSE_TYPE}" [ "${HAS_STALE_FILES:-false}" = true ] && echo "WARNING: Stale Files present" echo "===============================" } > "$LAST_RUN_LOG" cp "$LOCAL_LOG_PATH" "$ARCHIVE_LOG_PATH" log_to_file "Status Log saved: ${LAST_RUN_LOG}" log_to_file "Session Log archived: ${ARCHIVE_LOG_PATH}" log_to_file "---[ARCHIVE LOG UPDATED]---" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "ARCHIVE LOG UPDATED" echo "Log saved to: ${LAST_RUN_LOG}" fi else log_to_file "---[MODULE 5: ${MOD_TITLE_5}]---" log_to_file "[DISABLED]" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_5} SKIPPED" fi fi # --- MODULE 6: APPLY BACKUP RETENTION --- if [ "$ENABLE_BACKUP_RETENTION" = true ]; then log_to_file "---[MODULE 6: ${MOD_TITLE_6}]---" cd "$BACKUP_BASE_DIR" || { log_to_file "[${MSG_ERROR}] $MSG_CHANGE_DIR_FAILED"; exit 1; } DELETED_BY_AGE=$(find . -maxdepth 1 -name "*boot-backup*.zip" -type f -mtime +"${BACKUP_RETENTION_DAYS}" -print 2>/dev/null | wc -l) if [ "$DELETED_BY_AGE" -gt 0 ]; then log_to_file "[${MSG_INFO}] ${DELETED_BY_AGE} Backups older than ${BACKUP_RETENTION_DAYS} days removed." find . -maxdepth 1 -name "*boot-backup*.zip" -type f -mtime +"${BACKUP_RETENTION_DAYS}" -delete 2>/dev/null if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_INFO}] Removed ${DELETED_BY_AGE} old Backups (older than ${BACKUP_RETENTION_DAYS} days)." fi fi if [ -n "$MAX_BACKUPS_TO_KEEP" ] && [ "$MAX_BACKUPS_TO_KEEP" -gt 0 ]; then CURRENT_COUNT=$(ls -1 *boot-backup*.zip 2>/dev/null | wc -l) if [ "$CURRENT_COUNT" -gt "$MAX_BACKUPS_TO_KEEP" ]; then TO_DELETE=$((CURRENT_COUNT - MAX_BACKUPS_TO_KEEP)) log_to_file "[${MSG_INFO}] Current Backups: ${CURRENT_COUNT} | Max: ${MAX_BACKUPS_TO_KEEP} → Deleting ${TO_DELETE} Files." ls -t *boot-backup*.zip 2>/dev/null | tail -n +$((MAX_BACKUPS_TO_KEEP + 1)) | while read -r old_backup; do rm -f "$old_backup" log_to_file "[${MSG_INFO}] Deleted: $(basename "$old_backup")" done if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_INFO}] Deleted ${TO_DELETE} old Backups to stay within Limit of ${MAX_BACKUPS_TO_KEEP}." fi else if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_INFO}] Backup Count (${CURRENT_COUNT}) is within Limit (${MAX_BACKUPS_TO_KEEP})." fi fi fi FINAL_COUNT=$(ls -1 *boot-backup*.zip 2>/dev/null | wc -l) log_to_file "[${MSG_INFO}] Result: ${FINAL_COUNT} Flash or Boot Backups remaining." log_to_file "---[${MOD_TITLE_6} COMPLETED]---" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_6} COMPLETED" echo "Total Backups remaining: ${FINAL_COUNT}" fi else log_to_file "---[MODULE 6: ${MOD_TITLE_6}]---" log_to_file "[DISABLED]" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_6} SKIPPED" fi fi # --- MODULE 7: APPLY LOG RETENTION --- if [ "$ENABLE_LOG_RETENTION" = true ]; then log_to_file "---[MODULE 7: ${MOD_TITLE_7}]---" cd "$ARCHIVE_LOG_DIR" || { log_to_file "[${MSG_ERROR}] $MSG_CHANGE_DIR_FAILED"; exit 1; } DELETED_LOGS_BY_AGE=$(find . -maxdepth 1 -name "*.log" -type f ! -name "last_run.log" -mtime +"${LOG_RETENTION_DAYS}" -print 2>/dev/null | wc -l) if [ "$DELETED_LOGS_BY_AGE" -gt 0 ]; then log_to_file "[${MSG_INFO}] ${DELETED_LOGS_BY_AGE} Log Files older than ${LOG_RETENTION_DAYS} Days removed." find . -maxdepth 1 -name "*.log" -type f ! -name "last_run.log" -mtime +"${LOG_RETENTION_DAYS}" -delete 2>/dev/null if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_INFO}] Removed ${DELETED_LOGS_BY_AGE} old Logs (older than ${LOG_RETENTION_DAYS} Days)." fi fi if [ -n "$MAX_LOG_FILES_TO_KEEP" ] && [ "$MAX_LOG_FILES_TO_KEEP" -gt 0 ]; then LOG_FILE_COUNT=$(find . -maxdepth 1 -name "${LOG_FILE_PATTERN}" -type f 2>/dev/null | wc -l) if [ "$LOG_FILE_COUNT" -gt "$MAX_LOG_FILES_TO_KEEP" ]; then TO_DELETE_COUNT=$((LOG_FILE_COUNT - MAX_LOG_FILES_TO_KEEP)) log_to_file "[${MSG_INFO}] Current Logs: ${LOG_FILE_COUNT} | Max: ${MAX_LOG_FILES_TO_KEEP} → Deleting ${TO_DELETE_COUNT} Files." mapfile -t files_to_delete < <( for f in $(find . -maxdepth 1 -name "${LOG_FILE_PATTERN}" -type f); do ts=$(stat -c '%Y' "$f" 2>/dev/null || stat -f '%m' "$f" 2>/dev/null) printf '%s %s\n' "$ts" "$f" done | sort -n | head -n "$TO_DELETE_COUNT" | awk '{print $2}' ) for old_log in "${files_to_delete[@]}"; do if [ -n "$old_log" ]; then rm -f "$old_log" log_to_file "[${MSG_INFO}] Deleted: $(basename "$old_log")" fi done if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_INFO}] Deleted ${TO_DELETE_COUNT} old Logs to stay within Limit of ${MAX_LOG_FILES_TO_KEEP}." fi else if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "[${MSG_INFO}] Log Count (${LOG_FILE_COUNT}) is within Limit (${MAX_LOG_FILES_TO_KEEP})." fi fi fi FINAL_LOG_COUNT=$(find . -maxdepth 1 -name "${LOG_FILE_PATTERN}" -type f | wc -l) log_to_file "[${MSG_INFO}] Result: ${FINAL_LOG_COUNT} Log Files remaining (excl. last_run.log)." log_to_file "---[${MOD_TITLE_7} COMPLETED]---" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_7} COMPLETED" echo "Total Logs remaining: ${FINAL_LOG_COUNT}" fi else log_to_file "---[MODULE 7: ${MOD_TITLE_7}]---" log_to_file "[DISABLED]" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_7} SKIPPED" fi fi # --- MODULE 8: SEND NOTIFICATION --- if [ "$ENABLE_NOTIFICATION" = true ]; then log_to_file "---[MODULE 8: ${MOD_TITLE_8}]---" NOTIFY_TITLE="Flash or Boot Backup Completed - ${HOST_NAME}" NOTIFY_MSG="Flash or Boot Backup '${BACKUP_FILE}' successfully created." DETAIL_MSG="" if [ "$ENABLE_LICENSE_CHECK" = true ]; then case "$DEVICE_BINDING" in "USB Stick") DETAIL_MSG="License: ${LICENSE_TYPE:-Unknown} (USB)" ;; "TPM") DETAIL_MSG="License: ${LICENSE_TYPE:-Unknown} (TPM)" ;; esac fi if [ "$ENABLE_BOOT_CHECK" = true ] && [ "$BOOT_MEDIUM_TYPE" != "UNKNOWN" ]; then DETAIL_MSG="${DETAIL_MSG:+${DETAIL_MSG} | }Boot: ${BOOT_MEDIUM_TYPE}" fi if [ "${HAS_STALE_FILES:-false}" = true ]; then DETAIL_MSG="${DETAIL_MSG:+${DETAIL_MSG} | }WARNING: Stale Files" fi /usr/local/emhttp/webGui/scripts/notify -e "$NOTIFY_TITLE" \ -s "Flash or Boot Backup Success" \ -d "${NOTIFY_MSG} - ${DETAIL_MSG}" \ -i "normal" log_to_file "[${MSG_INFO}] Notification sent." log_to_file "---[${MOD_TITLE_8} COMPLETED]---" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_8} SENT" echo "Notification sent successfully." fi else log_to_file "---[MODULE 8: ${MOD_TITLE_8}]---" log_to_file "[DISABLED]" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_section "${MOD_TITLE_8} SKIPPED" fi fi # Final Output if [ "$SHOW_CLI_OUTPUT" = true ]; then echo "" echo "==============================================================" echo " ${MSG_BACKUP_ANALYSIS_MAINTENANCE_COMPLETED}" echo "==============================================================" fi log_to_file "[${MSG_SUCCESS}] ${MSG_SUCCESS_ALL_STEPS}" if [ "$SHOW_CLI_OUTPUT" = true ]; then print_msg "$MSG_SUCCESS" "${MSG_SUCCESS_ALL_STEPS}" fi exit 0
-
Identify Boot and License Type
That was an Option. It the boot device always the same path/name ...? So we can find this with the same command on any system. Or have the Boot device a one command to identify it? Than list partitions with for example lsblk or fdisk -l?
-
Identify Boot and License Type
How I can find this characters per Terminal or a Script or is that an Entry on a Config File? And how I can check flash or the new internal Boot Mode on the same Ways?
-
Identify Boot and License Type
Hello, how I can identify the Boot and License Type through Terminal or Script like flash, internal boot, TPM, flash licensed, ... It's that a Config File Entry? From German: https://forums.unraid.net/topic/199455-identifizierung-von-flash-oder-internal-boot-sowie-lizenzierung/ Many Thanks! Many Greetings Revan335
-
Identifizierung von flash oder internal boot sowie Lizenzierung
Hallo, gibt es eine Möglichkeit per Terminal/Script auszugeben bzw. prüfen zu können ob man flash als Boot Device unter 7.3.x nutzt oder ob internal boot genutzt wird? Vor 7.3 gab es noch kein internal boot, nur flash als Boot Device. Das gleiche gilt für die Lizenzierung per TPM oder USB Stick. Steht das ggf. in einer der Konfig Dateien? Vielen Dank! Viele Liebe Grüße Revan335
-
Latest (super easy) method for automated flash zip backup!
Whats Script Version working on 7.3.1+?
-
[Plugin] Appdata.Backup
It this working on 7.3.x include Backup the Internal Boot, Docker/AppData, ...?
-
[Plugin] CA Fix Common Problems
The Maintainer Answer: https://forums.unraid.net/topic/100511-plugin-usb_manager/page/24/#findComment-1627484 And the Discussion about this.
-
[Plugin] USB_Manager
Than its that the Issue and need a CA Release or Update of the FCP Plugin and his Exclusions?
Revan335
Members
-
Joined