#!/bin/bash # ----------------------------------------------------------------------------------------------- # --------------------------------- Ramdisk Setup Script --------------------------------------- # ----------------------------------------------------------------------------------------------- # Creates a tmpfs ramdisk for Emby transcodes and points the transcode symlink at it. # Run once at array start via User Scripts plugin — scheduled as "At Startup of Array". # If ramdisk already mounted reports status and exits cleanly without remounting. # # Creates: # RAMDISK_PATH — tmpfs mount point (fast, in-memory transcode location) # TRANSCODE_SSD — SSD fallback directory (created if missing) # TRANSCODE_LINK — symlink pointing at ramdisk by default # # All configuration in Master.conf under Transcode Manager section. # Supports --dry-run to preview what would be created 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 ━━━" 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_RAM Ramdisk path: $RAMDISK_PATH" echo "$ICON_RAM Ramdisk size: $RAMDISK_SIZE" echo "$ICON_LINK Transcode link: $TRANSCODE_LINK" echo "$ICON_DISK SSD fallback: $TRANSCODE_SSD" echo "$ICON_GEAR Owner: $TRANSCODE_OWNER" echo "$ICON_GEAR Mode: $TRANSCODE_MODE" echo "$ICON_GEAR Dry Run: $DRY_RUN" # Show current mount state if mountpoint -q "$RAMDISK_PATH" 2>/dev/null; then CURRENT_USAGE=$(df -BG "$RAMDISK_PATH" | awk 'NR==2 {print $3}') CURRENT_AVAIL=$(df -BG "$RAMDISK_PATH" | awk 'NR==2 {print $4}') echo "$ICON_RAM Current usage: $CURRENT_USAGE used / $CURRENT_AVAIL available" else echo "$ICON_RAM Ramdisk: not mounted" fi if [[ -L "$TRANSCODE_LINK" ]]; then echo "$ICON_LINK Current target: $(readlink "$TRANSCODE_LINK")" else echo "$ICON_LINK Symlink: not set" fi echo "━━━━━━━━━━━━━━━━━━━━━━━" exit 0 fi [[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made" # ----------------------------------------------------------------------------------------------- # ━━━ $ICON_RAM Ramdisk Setup ━━━ # ----------------------------------------------------------------------------------------------- echo "" echo "━━━ $ICON_RAM Ramdisk Setup ━━━" echo "$ICON_RAM Path: $RAMDISK_PATH" echo "$ICON_RAM Size: $RAMDISK_SIZE" echo "" START=$(date +%s) SETUP_SUCCESS=true # Check if ramdisk already mounted if mountpoint -q "$RAMDISK_PATH" 2>/dev/null; then CURRENT_USAGE=$(df -BG "$RAMDISK_PATH" | awk 'NR==2 {print $3}') CURRENT_AVAIL=$(df -BG "$RAMDISK_PATH" | awk 'NR==2 {print $4}') info "$ICON_RAM Ramdisk already mounted — $CURRENT_USAGE used / $CURRENT_AVAIL available" info "Skipping mount — verifying symlink and permissions" else # Create mount point if [[ "$DRY_RUN" == true ]]; then warn "DRY RUN — would create $RAMDISK_PATH" warn "DRY RUN — would mount tmpfs ${RAMDISK_SIZE} at $RAMDISK_PATH" else info "Creating ramdisk mount point: $RAMDISK_PATH" mkdir -p "$RAMDISK_PATH" || { error "Failed to create $RAMDISK_PATH" notify "Ramdisk setup failed on $(hostname) — could not create mount point" "Ramdisk Setup" "warning" exit 1 } info "$ICON_RAM Mounting tmpfs ${RAMDISK_SIZE} at $RAMDISK_PATH..." if mount -t tmpfs -o size="$RAMDISK_SIZE" tmpfs "$RAMDISK_PATH"; then success "Ramdisk mounted — ${RAMDISK_SIZE} at $RAMDISK_PATH" else error "Failed to mount ramdisk at $RAMDISK_PATH" notify "Ramdisk setup failed on $(hostname) — mount failed" "Ramdisk Setup" "warning" exit 1 fi fi fi # ----------------------------------------------------------------------------------------------- # ━━━ $ICON_DISK SSD Fallback ━━━ # ----------------------------------------------------------------------------------------------- echo "" echo "━━━ $ICON_DISK SSD Fallback ━━━" if [[ "$DRY_RUN" == true ]]; then warn "DRY RUN — would create SSD fallback: $TRANSCODE_SSD" else if [[ -d "$TRANSCODE_SSD" ]]; then info "$ICON_DISK SSD fallback already exists: $TRANSCODE_SSD" else info "Creating SSD fallback directory: $TRANSCODE_SSD" if mkdir -p "$TRANSCODE_SSD"; then success "SSD fallback created: $TRANSCODE_SSD" else error "Failed to create SSD fallback: $TRANSCODE_SSD" SETUP_SUCCESS=false fi fi fi # ----------------------------------------------------------------------------------------------- # ━━━ $ICON_LINK Symlink ━━━ # ----------------------------------------------------------------------------------------------- echo "" echo "━━━ $ICON_LINK Symlink ━━━" if [[ "$DRY_RUN" == true ]]; then warn "DRY RUN — would set $TRANSCODE_LINK → $RAMDISK_PATH" else # Remove existing symlink or directory at link path if [[ -L "$TRANSCODE_LINK" ]]; then CURRENT_TARGET=$(readlink "$TRANSCODE_LINK") if [[ "$CURRENT_TARGET" == "$RAMDISK_PATH" ]]; then info "$ICON_LINK Symlink already points to ramdisk — no change needed" else info "$ICON_LINK Updating symlink: $CURRENT_TARGET → $RAMDISK_PATH" ln -sfn "$RAMDISK_PATH" "$TRANSCODE_LINK" || { error "Failed to update symlink" SETUP_SUCCESS=false } fi elif [[ -e "$TRANSCODE_LINK" ]]; then warn "$TRANSCODE_LINK exists but is not a symlink — removing and replacing" rm -rf "$TRANSCODE_LINK" ln -sfn "$RAMDISK_PATH" "$TRANSCODE_LINK" || { error "Failed to create symlink" SETUP_SUCCESS=false } else info "Creating symlink: $TRANSCODE_LINK → $RAMDISK_PATH" # Ensure parent directory exists mkdir -p "$(dirname "$TRANSCODE_LINK")" ln -sfn "$RAMDISK_PATH" "$TRANSCODE_LINK" || { error "Failed to create symlink" SETUP_SUCCESS=false } fi if [[ "$SETUP_SUCCESS" == true ]]; then success "$ICON_LINK $TRANSCODE_LINK → $RAMDISK_PATH" fi fi # ----------------------------------------------------------------------------------------------- # ━━━ $ICON_GEAR Transcoding-temp Directory ━━━ # Creates the transcoding-temp folder on the ramdisk proactively. # If this folder doesn't exist on the ramdisk Emby creates it wherever it finds # a writable path first — which may be the SSD fallback — locking all sessions # onto SSD even when the symlink points at the ramdisk. # Creating it here guarantees Emby always finds it on the ramdisk at session start. # ----------------------------------------------------------------------------------------------- echo "" echo "━━━ $ICON_GEAR Transcoding Temp Directory ━━━" TRANSCODE_TEMP_DIR="${RAMDISK_PATH}/transcoding-temp" if [[ "$DRY_RUN" == true ]]; then warn "DRY RUN — would create $TRANSCODE_TEMP_DIR" else if [[ -d "$TRANSCODE_TEMP_DIR" ]]; then info "transcoding-temp already exists on ramdisk" else mkdir -p "$TRANSCODE_TEMP_DIR" && \ success "Created transcoding-temp on ramdisk: $TRANSCODE_TEMP_DIR" || \ { error "Failed to create transcoding-temp on ramdisk"; SETUP_SUCCESS=false; } fi # Apply correct permissions so Emby (abc/nobody:users) can write to it if [[ -d "$TRANSCODE_TEMP_DIR" ]]; then chmod "$TRANSCODE_CHMOD" "$TRANSCODE_TEMP_DIR" chown "$TRANSCODE_OWNER" "$TRANSCODE_TEMP_DIR" success "Permissions set on transcoding-temp" fi fi # ----------------------------------------------------------------------------------------------- # ━━━ $ICON_GEAR Permissions ━━━ # ----------------------------------------------------------------------------------------------- echo "" echo "━━━ $ICON_GEAR Permissions ━━━" if [[ "$DRY_RUN" == true ]]; then warn "DRY RUN — would apply $TRANSCODE_MODE $TRANSCODE_OWNER to $RAMDISK_PATH and $TRANSCODE_SSD" else for path in "$RAMDISK_PATH" "$TRANSCODE_SSD"; do if [[ -d "$path" ]]; then chmod "$TRANSCODE_MODE" "$path" chown "$TRANSCODE_OWNER" "$path" success "Permissions set: $path" fi done fi # ----------------------------------------------------------------------------------------------- # Initialise state file # ----------------------------------------------------------------------------------------------- if [[ "$DRY_RUN" == false ]]; then STATE_FILE="/tmp/transcode_state.db" NOW=$(date +%s) cat > "$STATE_FILE" <