241 lines
7.1 KiB
Bash
Executable File
241 lines
7.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# Media Archive Manager - Move content between local and Hetzner storage
|
|
# Usage: media-archive.sh [archive|restore|status|list-old]
|
|
|
|
set -e
|
|
|
|
# Configuration
|
|
LOCAL_MEDIA="/opt/media-server/media"
|
|
HETZNER_MEDIA="/mnt/hetzner-media/archive"
|
|
LOG_FILE="/opt/media-server/logs/archive.log"
|
|
DAYS_OLD=90 # Content older than this is considered for archiving
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# Ensure log directory exists
|
|
mkdir -p "$(dirname "$LOG_FILE")"
|
|
|
|
log() {
|
|
echo "[$(date -Iseconds)] $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
check_mount() {
|
|
if ! mountpoint -q "$HETZNER_MEDIA" 2>/dev/null; then
|
|
# Try to trigger automount
|
|
ls "$HETZNER_MEDIA" &>/dev/null 2>&1
|
|
sleep 2
|
|
if ! mountpoint -q "$HETZNER_MEDIA" 2>/dev/null; then
|
|
echo -e "${RED}Error: Hetzner storage not mounted at $HETZNER_MEDIA${NC}"
|
|
echo "Run: sudo systemctl start mnt-hetzner\\x2dmedia.mount"
|
|
exit 1
|
|
fi
|
|
fi
|
|
echo -e "${GREEN}Hetzner storage mounted${NC}"
|
|
}
|
|
|
|
show_status() {
|
|
echo -e "${BLUE}Storage Status${NC}"
|
|
echo "=============="
|
|
echo ""
|
|
|
|
echo -e "${YELLOW}Local Storage (/opt/media-server/media):${NC}"
|
|
if [ -d "$LOCAL_MEDIA" ]; then
|
|
du -sh "$LOCAL_MEDIA"/* 2>/dev/null || echo " (empty or not accessible)"
|
|
else
|
|
echo " Not found"
|
|
fi
|
|
echo ""
|
|
|
|
echo -e "${YELLOW}Hetzner Storage (/mnt/hetzner-media):${NC}"
|
|
if mountpoint -q "/mnt/hetzner-media" 2>/dev/null || ls "/mnt/hetzner-media" &>/dev/null 2>&1; then
|
|
df -h "/mnt/hetzner-media"
|
|
echo ""
|
|
echo "Archive contents:"
|
|
du -sh "$HETZNER_MEDIA"/* 2>/dev/null || echo " (empty)"
|
|
else
|
|
echo " Not mounted"
|
|
fi
|
|
}
|
|
|
|
list_old_content() {
|
|
echo -e "${BLUE}Content older than $DAYS_OLD days${NC}"
|
|
echo "================================"
|
|
echo ""
|
|
|
|
for media_type in movies shows music; do
|
|
echo -e "${YELLOW}$media_type:${NC}"
|
|
if [ -d "$LOCAL_MEDIA/$media_type" ]; then
|
|
find "$LOCAL_MEDIA/$media_type" -maxdepth 1 -mindepth 1 -type d -mtime +$DAYS_OLD 2>/dev/null | while read dir; do
|
|
size=$(du -sh "$dir" 2>/dev/null | cut -f1)
|
|
name=$(basename "$dir")
|
|
echo " [$size] $name"
|
|
done
|
|
fi
|
|
echo ""
|
|
done
|
|
}
|
|
|
|
archive_content() {
|
|
local media_type=$1
|
|
local name=$2
|
|
|
|
if [ -z "$media_type" ] || [ -z "$name" ]; then
|
|
echo "Usage: media-archive.sh archive <movies|shows|music> <name>"
|
|
echo " media-archive.sh archive <movies|shows|music> --older-than <days>"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " media-archive.sh archive movies 'The Matrix (1999)'"
|
|
echo " media-archive.sh archive shows --older-than 180"
|
|
exit 1
|
|
fi
|
|
|
|
check_mount
|
|
|
|
# Handle batch archival
|
|
if [ "$name" == "--older-than" ]; then
|
|
local days=${3:-$DAYS_OLD}
|
|
echo -e "${YELLOW}Archiving $media_type older than $days days...${NC}"
|
|
|
|
find "$LOCAL_MEDIA/$media_type" -maxdepth 1 -mindepth 1 -type d -mtime +$days 2>/dev/null | while read dir; do
|
|
local item_name=$(basename "$dir")
|
|
archive_single "$media_type" "$item_name"
|
|
done
|
|
return
|
|
fi
|
|
|
|
archive_single "$media_type" "$name"
|
|
}
|
|
|
|
archive_single() {
|
|
local media_type=$1
|
|
local name=$2
|
|
local source="$LOCAL_MEDIA/$media_type/$name"
|
|
local dest="$HETZNER_MEDIA/$media_type/$name"
|
|
|
|
if [ ! -d "$source" ]; then
|
|
echo -e "${RED}Error: $source not found${NC}"
|
|
return 1
|
|
fi
|
|
|
|
local size=$(du -sh "$source" 2>/dev/null | cut -f1)
|
|
echo -e "${BLUE}Archiving: $name ($size)${NC}"
|
|
|
|
# Create destination directory
|
|
mkdir -p "$HETZNER_MEDIA/$media_type"
|
|
|
|
# Use rsync for reliable transfer with progress
|
|
log "Archiving $media_type/$name ($size) to Hetzner"
|
|
rsync -avh --progress --remove-source-files "$source/" "$dest/"
|
|
|
|
# Remove empty source directory
|
|
rmdir "$source" 2>/dev/null || true
|
|
|
|
echo -e "${GREEN}Archived: $name${NC}"
|
|
log "Completed archiving $media_type/$name"
|
|
}
|
|
|
|
restore_content() {
|
|
local media_type=$1
|
|
local name=$2
|
|
|
|
if [ -z "$media_type" ] || [ -z "$name" ]; then
|
|
echo "Usage: media-archive.sh restore <movies|shows|music> <name>"
|
|
echo ""
|
|
echo "List available archives:"
|
|
echo " ls /mnt/hetzner-media/archive/<type>/"
|
|
exit 1
|
|
fi
|
|
|
|
check_mount
|
|
|
|
local source="$HETZNER_MEDIA/$media_type/$name"
|
|
local dest="$LOCAL_MEDIA/$media_type/$name"
|
|
|
|
if [ ! -d "$source" ]; then
|
|
echo -e "${RED}Error: $source not found in archive${NC}"
|
|
echo ""
|
|
echo "Available in $media_type archive:"
|
|
ls -1 "$HETZNER_MEDIA/$media_type/" 2>/dev/null || echo " (empty)"
|
|
return 1
|
|
fi
|
|
|
|
local size=$(du -sh "$source" 2>/dev/null | cut -f1)
|
|
echo -e "${BLUE}Restoring: $name ($size)${NC}"
|
|
|
|
log "Restoring $media_type/$name ($size) from Hetzner"
|
|
rsync -avh --progress "$source/" "$dest/"
|
|
|
|
echo -e "${GREEN}Restored: $name${NC}"
|
|
echo "Content available at: $dest"
|
|
log "Completed restoring $media_type/$name"
|
|
}
|
|
|
|
sync_to_hetzner() {
|
|
# One-way sync from local to Hetzner (backup mode)
|
|
check_mount
|
|
|
|
echo -e "${BLUE}Syncing local media to Hetzner (backup)...${NC}"
|
|
|
|
for media_type in movies shows music; do
|
|
if [ -d "$LOCAL_MEDIA/$media_type" ]; then
|
|
echo -e "${YELLOW}Syncing $media_type...${NC}"
|
|
mkdir -p "$HETZNER_MEDIA/$media_type"
|
|
rsync -avh --progress "$LOCAL_MEDIA/$media_type/" "$HETZNER_MEDIA/$media_type/"
|
|
fi
|
|
done
|
|
|
|
echo -e "${GREEN}Sync complete${NC}"
|
|
}
|
|
|
|
# Main command handler
|
|
case "${1:-status}" in
|
|
status)
|
|
show_status
|
|
;;
|
|
list-old|list)
|
|
list_old_content
|
|
;;
|
|
archive)
|
|
archive_content "$2" "$3" "$4"
|
|
;;
|
|
restore)
|
|
restore_content "$2" "$3"
|
|
;;
|
|
sync|backup)
|
|
sync_to_hetzner
|
|
;;
|
|
help|--help|-h)
|
|
echo "Media Archive Manager"
|
|
echo "====================="
|
|
echo ""
|
|
echo "Usage: media-archive.sh <command> [options]"
|
|
echo ""
|
|
echo "Commands:"
|
|
echo " status Show storage status and usage"
|
|
echo " list-old List content older than $DAYS_OLD days"
|
|
echo " archive <type> <name> Archive specific content to Hetzner"
|
|
echo " archive <type> --older-than <days> Archive all content older than N days"
|
|
echo " restore <type> <name> Restore content from Hetzner to local"
|
|
echo " sync Sync all local media to Hetzner (backup)"
|
|
echo ""
|
|
echo "Types: movies, shows, music"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " media-archive.sh status"
|
|
echo " media-archive.sh list-old"
|
|
echo " media-archive.sh archive movies 'The Matrix (1999)'"
|
|
echo " media-archive.sh archive shows --older-than 180"
|
|
echo " media-archive.sh restore movies 'The Matrix (1999)'"
|
|
;;
|
|
*)
|
|
echo "Unknown command: $1"
|
|
echo "Run 'media-archive.sh help' for usage"
|
|
exit 1
|
|
;;
|
|
esac
|