diff --git a/du_setup.sh b/du_setup.sh index aa1ed29..76bbfbb 100644 --- a/du_setup.sh +++ b/du_setup.sh @@ -4879,153 +4879,220 @@ test_backup() { } configure_swap() { - if [[ $IS_CONTAINER == true ]]; then + if [[ "$IS_CONTAINER" == true ]]; then print_info "Swap configuration skipped in container." return 0 fi print_section "Swap Configuration" - # Check for existing swap partition + + # Check for existing swap partition entries in fstab for awareness if lsblk -r | grep -q '\[SWAP\]'; then - print_warning "Existing swap partition found. Verify with 'lsblk -f'. Proceed with caution." + print_warning "Existing swap partition found on disk." fi - local existing_swap - existing_swap=$(swapon --show --noheadings | awk '{print $1}' || true) + + # Detect active swap + local existing_swap swap_type + + # --show=NAME,TYPE,SIZE ensures consistent column order + existing_swap=$(swapon --show=NAME,TYPE,SIZE --noheadings --bytes 2>/dev/null | head -n 1 | awk '{print $1}' || true) + if [[ -n "$existing_swap" ]]; then - local current_size - current_size=$(du -h "$existing_swap" | awk '{print $1}') - print_info "Existing swap file found: $existing_swap ($current_size)" - if confirm "Modify existing swap file size?"; then - local SWAP_SIZE - while true; do - read -rp "$(printf '%s' "${CYAN}Enter new swap size (e.g., 2G, 512M) [current: $current_size]: ${NC}")" SWAP_SIZE - SWAP_SIZE=${SWAP_SIZE:-$current_size} - if validate_swap_size "$SWAP_SIZE"; then - break - else - print_error "Invalid size. Use format like '2G' or '512M'." + swap_type=$(swapon --show=NAME,TYPE,SIZE --noheadings | head -n 1 | awk '{print $2}') + + # Get human readable size for display using du (disk usage) + local display_size + display_size=$(du -h "$existing_swap" 2>/dev/null | awk '{print $1}' || echo "Unknown") + + print_info "Existing swap detected: $existing_swap (Type: $swap_type, Size: $display_size)" + + # --- Case 1: Partition detected --- + if [[ "$swap_type" == "partition" ]] || [[ "$existing_swap" =~ ^/dev/ ]]; then + print_warning "The detected swap is a disk partition, which cannot be resized by this script." + + if confirm "Disable this swap partition and create a standard /swapfile instead?" "n"; then + print_info "Disabling swap partition $existing_swap..." + if ! swapoff "$existing_swap"; then + print_error "Failed to disable swap partition. Keeping it active." + return 0 fi - done - local REQUIRED_SPACE - REQUIRED_SPACE=$(convert_to_bytes "$SWAP_SIZE") - local AVAILABLE_SPACE - AVAILABLE_SPACE=$(df -k / | tail -n 1 | awk '{print $4}') - if (( AVAILABLE_SPACE < REQUIRED_SPACE / 1024 )); then - print_error "Insufficient disk space for $SWAP_SIZE swap file. Available: $((AVAILABLE_SPACE / 1024))MB" - exit 1 + + # Comment out the partition in fstab to prevent it mounting on reboot + sed -i "s|^$existing_swap|#$existing_swap|" /etc/fstab + sed -i "s|^UUID=.*swap|#&|" /etc/fstab + print_success "Swap partition disabled and removed from fstab." + + # Clear variable to trigger new file creation below + existing_swap="" + else + print_info "Keeping existing swap partition." + configure_swap_settings + return 0 fi - print_info "Disabling existing swap file..." - swapoff "$existing_swap" || { print_error "Failed to disable swap file."; exit 1; } - print_info "Resizing swap file to $SWAP_SIZE..." - if ! fallocate -l "$SWAP_SIZE" "$existing_swap" || ! chmod 600 "$existing_swap" || ! mkswap "$existing_swap" || ! swapon "$existing_swap"; then - print_error "Failed to resize or enable swap file." - exit 1 - fi - print_success "Swap file resized to $SWAP_SIZE." else - print_info "Keeping existing swap file." + # --- Case 2: Swap File detected --- + if confirm "Modify existing swap file size?"; then + local SWAP_SIZE + while true; do + read -rp "$(printf '%s' "${CYAN}Enter new swap size (e.g., 2G, 512M) [current: $display_size]: ${NC}")" SWAP_SIZE + SWAP_SIZE=${SWAP_SIZE:-$display_size} + if validate_swap_size "$SWAP_SIZE"; then break; else print_error "Invalid size. Use format like '2G' or '512M'."; fi + done + + # Disk space check + local REQUIRED_SPACE AVAILABLE_SPACE + REQUIRED_SPACE=$(convert_to_bytes "$SWAP_SIZE") + AVAILABLE_SPACE=$(df -k / | tail -n 1 | awk '{print $4}') + # Convert available to bytes for comparison (df output is 1K blocks) + if (( (AVAILABLE_SPACE * 1024) < REQUIRED_SPACE )); then + print_error "Insufficient disk space. Required: $SWAP_SIZE, Available: $(numfmt --to=iec $((AVAILABLE_SPACE * 1024)))" + exit 1 + fi + + print_info "Disabling existing swap file..." + swapoff "$existing_swap" || { print_error "Failed to disable swap file."; exit 1; } + + print_info "Resizing swap file to $SWAP_SIZE..." + # Try fallocate first (fast), fallback to dd (compatible) + if ! fallocate -l "$SWAP_SIZE" "$existing_swap" 2>/dev/null; then + print_warning "fallocate failed (filesystem might not support it). Using dd (slower)..." + rm -f "$existing_swap" + # Quoted command substitution for ShellCheck compliance + if ! dd if=/dev/zero of="$existing_swap" bs=1M count="$(convert_to_mb "$SWAP_SIZE")" status=progress; then + print_error "Failed to create swap file with dd." + exit 1 + fi + fi + + if ! chmod 600 "$existing_swap" || ! mkswap "$existing_swap" >/dev/null || ! swapon "$existing_swap"; then + print_error "Failed to configure swap file." + exit 1 + fi + print_success "Swap file resized to $SWAP_SIZE." + else + print_info "Keeping existing swap file." + fi + configure_swap_settings return 0 fi - else + fi + + # --- Case 3: Create New Swap (No swap exists, or partition was disabled above) --- + if [[ -z "$existing_swap" ]]; then if ! confirm "Configure a swap file (recommended for < 4GB RAM)?"; then print_info "Skipping swap configuration." return 0 fi + local SWAP_SIZE while true; do read -rp "$(printf '%s' "${CYAN}Enter swap file size (e.g., 2G, 512M) [2G]: ${NC}")" SWAP_SIZE SWAP_SIZE=${SWAP_SIZE:-2G} - if validate_swap_size "$SWAP_SIZE"; then - break - else - print_error "Invalid size. Use format like '2G' or '512M'." - fi + if validate_swap_size "$SWAP_SIZE"; then break; else print_error "Invalid size. Use format like '2G' or '512M'."; fi done - local REQUIRED_SPACE + + local REQUIRED_SPACE AVAILABLE_SPACE REQUIRED_SPACE=$(convert_to_bytes "$SWAP_SIZE") - local AVAILABLE_SPACE AVAILABLE_SPACE=$(df -k / | tail -n 1 | awk '{print $4}') - if (( AVAILABLE_SPACE < REQUIRED_SPACE / 1024 )); then - print_error "Insufficient disk space for $SWAP_SIZE swap file. Available: $((AVAILABLE_SPACE / 1024))MB" + + if (( (AVAILABLE_SPACE * 1024) < REQUIRED_SPACE )); then + print_error "Insufficient disk space. Required: $SWAP_SIZE, Available: $(numfmt --to=iec $((AVAILABLE_SPACE * 1024)))" exit 1 fi - print_info "Creating $SWAP_SIZE swap file..." - if ! fallocate -l "$SWAP_SIZE" /swapfile || ! chmod 600 /swapfile || ! mkswap /swapfile || ! swapon /swapfile; then - print_error "Failed to create or enable swap file." + + print_info "Creating $SWAP_SIZE swap file at /swapfile..." + if ! fallocate -l "$SWAP_SIZE" /swapfile 2>/dev/null; then + print_warning "fallocate failed. Using dd (slower)..." + # Quoted command substitution for ShellCheck compliance + if ! dd if=/dev/zero of=/swapfile bs=1M count="$(convert_to_mb "$SWAP_SIZE")" status=progress; then + print_error "Failed to create swap file." + rm -f /swapfile || true + exit 1 + fi + fi + + if ! chmod 600 /swapfile || ! mkswap /swapfile >/dev/null || ! swapon /swapfile; then + print_error "Failed to enable swap file." rm -f /swapfile || true exit 1 fi - # Check for existing swap entry in /etc/fstab to prevent duplicates - if grep -q '^/swapfile ' /etc/fstab; then - print_info "Swap entry already exists in /etc/fstab. Skipping." - else + + # Add to fstab if missing + if ! grep -q '^/swapfile ' /etc/fstab; then echo '/swapfile none swap sw 0 0' >> /etc/fstab print_success "Swap entry added to /etc/fstab." + else + print_info "Swap entry already exists in /etc/fstab." fi print_success "Swap file created: $SWAP_SIZE" fi + + configure_swap_settings +} + +# Helper: Apply Sysctl Settings for Swap +configure_swap_settings() { print_info "Configuring swap settings..." local SWAPPINESS=10 local CACHE_PRESSURE=50 + if confirm "Customize swap settings (vm.swappiness and vm.vfs_cache_pressure)?"; then while true; do - read -rp "$(printf '%s' "${CYAN}Enter vm.swappiness (0-100) [default: $SWAPPINESS]: ${NC}")" INPUT_SWAPPINESS - INPUT_SWAPPINESS=${INPUT_SWAPPINESS:-$SWAPPINESS} - if [[ "$INPUT_SWAPPINESS" =~ ^[0-9]+$ && "$INPUT_SWAPPINESS" -ge 0 && "$INPUT_SWAPPINESS" -le 100 ]]; then - SWAPPINESS=$INPUT_SWAPPINESS - break - else - print_error "Invalid value for vm.swappiness. Must be between 0 and 100." - fi + read -rp "$(printf '%s' "${CYAN}Enter vm.swappiness (0-100) [default: $SWAPPINESS]: ${NC}")" INPUT + INPUT=${INPUT:-$SWAPPINESS} + if [[ "$INPUT" =~ ^[0-9]+$ && "$INPUT" -ge 0 && "$INPUT" -le 100 ]]; then SWAPPINESS=$INPUT; break; fi + print_error "Invalid value (0-100)." done while true; do - read -rp "$(printf '%s' "${CYAN}Enter vm.vfs_cache_pressure (1-1000) [default: $CACHE_PRESSURE]: ${NC}")" INPUT_CACHE_PRESSURE - INPUT_CACHE_PRESSURE=${INPUT_CACHE_PRESSURE:-$CACHE_PRESSURE} - if [[ "$INPUT_CACHE_PRESSURE" =~ ^[0-9]+$ && "$INPUT_CACHE_PRESSURE" -ge 1 && "$INPUT_CACHE_PRESSURE" -le 1000 ]]; then - CACHE_PRESSURE=$INPUT_CACHE_PRESSURE - break - else - print_error "Invalid value for vm.vfs_cache_pressure. Must be between 1 and 1000." - fi + read -rp "$(printf '%s' "${CYAN}Enter vm.vfs_cache_pressure (1-1000) [default: $CACHE_PRESSURE]: ${NC}")" INPUT + INPUT=${INPUT:-$CACHE_PRESSURE} + if [[ "$INPUT" =~ ^[0-9]+$ && "$INPUT" -ge 1 && "$INPUT" -le 1000 ]]; then CACHE_PRESSURE=$INPUT; break; fi + print_error "Invalid value (1-1000)." done else print_info "Using default swap settings (vm.swappiness=$SWAPPINESS, vm.vfs_cache_pressure=$CACHE_PRESSURE)." fi + local NEW_SWAP_CONFIG NEW_SWAP_CONFIG=$(mktemp) tee "$NEW_SWAP_CONFIG" > /dev/null <