Initial commit: combine nas_tool, nas_webdav, sync-utils
This commit is contained in:
Executable
+148
@@ -0,0 +1,148 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Aggressive Free System Data (351GB)
|
||||||
|
# When normal methods don't work
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Aggressive Free System Data (351GB) ==="
|
||||||
|
echo ""
|
||||||
|
echo "Since normal methods didn't work, we need to be more aggressive."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 Checking Time Machine configuration..."
|
||||||
|
TM_DEST=$(defaults read /Library/Preferences/com.apple.TimeMachine LastDestinationID 2>/dev/null || echo "NONE")
|
||||||
|
if [ "$TM_DEST" != "NONE" ]; then
|
||||||
|
echo " ⚠️ Time Machine destination still configured: $TM_DEST"
|
||||||
|
echo " This means snapshots may still be created!"
|
||||||
|
echo ""
|
||||||
|
echo " You MUST remove it in System Settings:"
|
||||||
|
echo " System Settings → Time Machine → Remove backup disk"
|
||||||
|
echo ""
|
||||||
|
read -p " Have you removed it? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo " ⚠️ Please remove it first!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✅ Time Machine destination removed"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Method 1: Force delete all local snapshots..."
|
||||||
|
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
if [ -n "$SNAPSHOTS" ]; then
|
||||||
|
echo "$SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
if [ -n "$SNAP_DATE" ]; then
|
||||||
|
echo " Deleting: $snapshot"
|
||||||
|
sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>&1 || echo " ⚠️ Failed (ghost entry)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " No snapshots found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Method 2: Aggressive thinning (keep only 1GB, 1 day)..."
|
||||||
|
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1
|
||||||
|
echo " ✓ Completed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Method 3: Disable Time Machine completely..."
|
||||||
|
sudo tmutil disable 2>/dev/null || echo " ⚠️ Could not disable (may already be disabled)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Method 4: Clear Time Machine database..."
|
||||||
|
echo " ⚠️ This will clear Time Machine's local database"
|
||||||
|
read -p " Proceed? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
# Backup first
|
||||||
|
sudo cp -r /Library/Preferences/com.apple.TimeMachine.plist /Library/Preferences/com.apple.TimeMachine.plist.backup 2>/dev/null || true
|
||||||
|
echo " Backed up preferences"
|
||||||
|
|
||||||
|
# Clear local snapshots database
|
||||||
|
sudo rm -rf /System/Volumes/Data/.timemachine/* 2>/dev/null || true
|
||||||
|
echo " ✓ Cleared Time Machine local data"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Method 5: Force filesystem sync and purge..."
|
||||||
|
sync
|
||||||
|
if command -v purge &> /dev/null; then
|
||||||
|
sudo purge
|
||||||
|
echo " ✓ Purged"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Method 6: Use macOS storage optimization..."
|
||||||
|
echo ""
|
||||||
|
echo " ⚠️ CRITICAL: You need to use macOS's built-in tool:"
|
||||||
|
echo ""
|
||||||
|
echo " 1. Apple Menu → About This Mac → Storage"
|
||||||
|
echo " 2. Click 'Manage...'"
|
||||||
|
echo " 3. Look for 'Optimize Storage' or similar option"
|
||||||
|
echo " 4. This will release purgeable space"
|
||||||
|
echo ""
|
||||||
|
echo " OR use Terminal:"
|
||||||
|
echo " sudo tmutil thinlocalsnapshots / 1000000000 1"
|
||||||
|
echo " sudo purge"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "⏳ Waiting for system to update..."
|
||||||
|
sleep 15
|
||||||
|
|
||||||
|
# Check results
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 100" | bc -l) )); then
|
||||||
|
echo " ✅ Successfully freed: ${FREED_GB}GB!"
|
||||||
|
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No space freed yet"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== If Still No Change ==="
|
||||||
|
echo ""
|
||||||
|
echo "The 351GB in System Data is likely:"
|
||||||
|
echo " 1. Purgeable space that macOS won't release until needed"
|
||||||
|
echo " 2. APFS snapshot overhead (the OS update snapshot)"
|
||||||
|
echo " 3. Reserved space for system operations"
|
||||||
|
echo ""
|
||||||
|
echo "Try these:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Create a large file to force purge**:"
|
||||||
|
echo " This forces macOS to release purgeable space:"
|
||||||
|
echo " dd if=/dev/zero of=~/test_large_file bs=1g count=50"
|
||||||
|
echo " (This creates a 50GB file, forcing purge)"
|
||||||
|
echo " Then delete it: rm ~/test_large_file"
|
||||||
|
echo ""
|
||||||
|
echo "2. **Use Activity Monitor**:"
|
||||||
|
echo " Open Activity Monitor → Disk tab"
|
||||||
|
echo " Look for 'Purgeable' space"
|
||||||
|
echo ""
|
||||||
|
echo "3. **Check Storage Management again**:"
|
||||||
|
echo " The System Data may show as 'Purgeable'"
|
||||||
|
echo " macOS will release it when space is actually needed"
|
||||||
|
echo ""
|
||||||
|
echo "4. **The space may already be available**:"
|
||||||
|
echo " Even though System Data shows 351GB, the space"
|
||||||
|
echo " may be purgeable and available when needed"
|
||||||
|
echo ""
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# Apple Support Issue Summary
|
||||||
|
|
||||||
|
## Problem Description
|
||||||
|
|
||||||
|
**Main Issue:** Cannot free disk space to install macOS update due to OS update snapshot preserving all deleted/moved files.
|
||||||
|
|
||||||
|
## Symptoms
|
||||||
|
|
||||||
|
1. **System Data is 351GB** (should be ~20-30GB)
|
||||||
|
2. **Disk is 99.8% full** (only 800MB free out of 494GB)
|
||||||
|
3. **macOS update requires 17.64GB** but cannot free space
|
||||||
|
4. **Every file deletion/move makes System Data grow** instead of freeing space
|
||||||
|
|
||||||
|
## Root Cause
|
||||||
|
|
||||||
|
**OS Update Snapshot is blocking space recovery:**
|
||||||
|
- Snapshot name: `com.apple.os.update-C6AB179000F92C4C211177BC5C840A511D1AA2A227C324AA9C14FC599E9873`
|
||||||
|
- Status: **NOT purgeable**
|
||||||
|
- Note: "This snapshot limits the minimum size of APFS Container"
|
||||||
|
- The snapshot preserves ALL deleted/moved files, preventing space recovery
|
||||||
|
|
||||||
|
## What I've Tried (All Failed)
|
||||||
|
|
||||||
|
1. ✅ Moved files to NAS (Synology DS224plus) - Files moved but space not freed
|
||||||
|
2. ✅ Moved files to external drive - Files moved but space not freed
|
||||||
|
3. ✅ Cleaned caches (`~/Library/Caches`, `~/.cache`, npm cache) - No effect
|
||||||
|
4. ✅ Deleted local Time Machine snapshots - Ghost entry, can't delete
|
||||||
|
5. ✅ Attempted `tmutil deletelocalsnapshots` - Error: "Stale NFS file handle"
|
||||||
|
6. ✅ Attempted `tmutil thinlocalsnapshots` - No effect
|
||||||
|
7. ✅ Restarted Mac multiple times - No effect
|
||||||
|
8. ✅ Tried `softwareupdate --download --all` - Failed: "Not enough free disk space: 17.64 GB required"
|
||||||
|
|
||||||
|
## Current System Status
|
||||||
|
|
||||||
|
- **macOS Version:** macOS Tahoe (need to update to 26.2)
|
||||||
|
- **Disk:** 494.4GB APFS container, 99.8% full
|
||||||
|
- **Free Space:** 800MB (need 17.64GB for update)
|
||||||
|
- **System Data:** 351GB (should be ~20-30GB)
|
||||||
|
- **Snapshot:** OS update snapshot, NOT purgeable, cannot be deleted manually
|
||||||
|
|
||||||
|
## The Catch-22
|
||||||
|
|
||||||
|
- **Need:** 17.64GB free space to install macOS update
|
||||||
|
- **Problem:** Cannot free space because OS update snapshot preserves all deleted/moved files
|
||||||
|
- **Result:** Stuck - cannot update, cannot free space
|
||||||
|
|
||||||
|
## What I Need from Apple Support
|
||||||
|
|
||||||
|
1. **Tool to force-clear the OS update snapshot** (it's blocking space recovery)
|
||||||
|
2. **Alternative method to install macOS update** with limited space
|
||||||
|
3. **Recovery options** to break out of this catch-22 situation
|
||||||
|
4. **System-level intervention** to release the 351GB in System Data
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
- **Snapshot UUID:** F63E39F3-D495-4586-88A4-A1406A7EF46A
|
||||||
|
- **Snapshot XID:** 6557111
|
||||||
|
- **Container:** disk3 (494.4GB)
|
||||||
|
- **Volume:** Macintosh HD (disk3s3)
|
||||||
|
- **Snapshot Disk:** disk3s3s1
|
||||||
|
|
||||||
|
## Files Are Safe
|
||||||
|
|
||||||
|
- Files have been moved to NAS and external drive
|
||||||
|
- Data is safe, but space cannot be recovered until snapshot is cleared
|
||||||
|
- The issue is purely about freeing space, not data loss
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Request:** Please provide system-level tools or recovery methods to clear the OS update snapshot so I can free space and install the macOS update.
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# Cellular Data Proxy Solution
|
||||||
|
|
||||||
|
## The Problem
|
||||||
|
- ✅ Wi-Fi proxy works (configured in Wi-Fi settings)
|
||||||
|
- ❌ Cellular data proxy doesn't work (iOS doesn't allow HTTP proxy for cellular)
|
||||||
|
- ❌ Can't disable Tailscale VPN (proxy only listens on Tailscale IP: 100.70.115.1)
|
||||||
|
|
||||||
|
## Solution Options
|
||||||
|
|
||||||
|
### Solution 1: Use Shadowrocket VPN Mode (Recommended)
|
||||||
|
|
||||||
|
Shadowrocket's VPN mode works on **both Wi-Fi and cellular**, and can route through Tailscale's network.
|
||||||
|
|
||||||
|
**Setup:**
|
||||||
|
1. **Keep Tailscale VPN ON** (needed to reach 100.70.115.1)
|
||||||
|
2. In Shadowrocket:
|
||||||
|
- Go to **Home** tab
|
||||||
|
- Add server: `100.70.115.1:7890` (HTTP)
|
||||||
|
- Enable Shadowrocket VPN mode
|
||||||
|
3. Shadowrocket will:
|
||||||
|
- Intercept all traffic (Wi-Fi + cellular)
|
||||||
|
- Route through Tailscale network to reach proxy
|
||||||
|
- Forward to server2's proxy
|
||||||
|
|
||||||
|
**Wait - iOS only allows one VPN!** This won't work...
|
||||||
|
|
||||||
|
### Solution 2: Make Clash Listen on Public IP (Less Secure)
|
||||||
|
|
||||||
|
Configure Clash to also listen on the public IP, then use Shadowrocket VPN mode.
|
||||||
|
|
||||||
|
**Pros:** Works on cellular, Shadowrocket can use it
|
||||||
|
**Cons:** Less secure (exposed to public internet, but firewall should protect)
|
||||||
|
|
||||||
|
### Solution 3: Use Tailscale's Built-in Proxy Feature
|
||||||
|
|
||||||
|
Tailscale has a built-in proxy feature that might work better.
|
||||||
|
|
||||||
|
### Solution 4: Use Shadowrocket with Tailscale Subnet Router
|
||||||
|
|
||||||
|
Configure server2 as a Tailscale subnet router, then use Shadowrocket.
|
||||||
|
|
||||||
|
## Recommended: Solution 2 (Make Clash Listen on Public IP with Firewall)
|
||||||
|
|
||||||
|
Since you need cellular access, let's make Clash accessible via public IP but keep it secure with firewall rules.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+80
@@ -0,0 +1,80 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check Real Disk Space - Verify what's actually using space
|
||||||
|
# Sometimes the snapshot is a ghost but space is actually available
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Real Disk Space Analysis ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Multiple methods to check space
|
||||||
|
echo "Method 1: df command:"
|
||||||
|
df -h / | tail -1
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Method 2: diskutil info:"
|
||||||
|
diskutil info / | grep -E "Volume (Free|Used|Total) Space" | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if snapshot actually exists
|
||||||
|
echo "Method 3: APFS Snapshot Check:"
|
||||||
|
APFS_TM_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -i "timemachine" || echo "None")
|
||||||
|
if [ "$APFS_TM_SNAPS" = "None" ]; then
|
||||||
|
echo " ✅ No Time Machine snapshot in APFS (ghost entry only)"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Found: $APFS_TM_SNAPS"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check Time Machine status
|
||||||
|
echo "Method 4: Time Machine Status:"
|
||||||
|
TM_RUNNING=$(tmutil status 2>/dev/null | grep "Running" | awk '{print $3}' | tr -d ';')
|
||||||
|
if [ "$TM_RUNNING" = "1" ]; then
|
||||||
|
echo " ⚠️ Time Machine is running (may be creating new snapshots)"
|
||||||
|
else
|
||||||
|
echo " ✅ Time Machine is not running"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Calculate actual space
|
||||||
|
FREE_KB=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_GB=$(echo "scale=2; $FREE_KB / 1024 / 1024" | bc)
|
||||||
|
|
||||||
|
echo "=== Summary ==="
|
||||||
|
echo " Current free space: ${FREE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if (( $(echo "$FREE_GB < 5" | bc -l) )); then
|
||||||
|
echo "⚠️ Still low on space. The ghost snapshot entry is not the issue."
|
||||||
|
echo ""
|
||||||
|
echo "The real issue: Your disk is actually full (or nearly full)."
|
||||||
|
echo ""
|
||||||
|
echo "The 20GB from deleted files may have been:"
|
||||||
|
echo " 1. Used by Time Machine creating a new snapshot"
|
||||||
|
echo " 2. Used by other processes/files"
|
||||||
|
echo " 3. Actually freed but macOS hasn't updated the count yet"
|
||||||
|
echo ""
|
||||||
|
echo "Solutions:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Restart your Mac** - This will:"
|
||||||
|
echo " - Release any held snapshots"
|
||||||
|
echo " - Update disk space accounting"
|
||||||
|
echo " - Clear stuck processes"
|
||||||
|
echo ""
|
||||||
|
echo "2. Check what's really using space:"
|
||||||
|
echo " du -h -d 1 ~ | sort -hr | head -20"
|
||||||
|
echo ""
|
||||||
|
echo "3. Clean up large files:"
|
||||||
|
echo " - Downloads folder: $(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo " - Library/Caches: $(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo ""
|
||||||
|
echo "4. The ghost snapshot entry is harmless - ignore it."
|
||||||
|
echo " It will clear when Time Machine successfully backs up."
|
||||||
|
else
|
||||||
|
echo "✅ You have ${FREE_GB}GB free - this should be enough!"
|
||||||
|
echo ""
|
||||||
|
echo "The ghost snapshot entry can be ignored - it's not using space."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+115
@@ -0,0 +1,115 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check Snapshot Size
|
||||||
|
# Determine how much space the snapshot is actually using
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Check Snapshot Size ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Current disk space
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
USED_SPACE=$(df / | tail -1 | awk '{print $3}')
|
||||||
|
USED_SPACE_GB=$(echo "scale=2; $USED_SPACE / 1024 / 1024" | bc)
|
||||||
|
|
||||||
|
echo "📊 Current Disk Status:"
|
||||||
|
echo " Used: ${USED_SPACE_GB}GB"
|
||||||
|
echo " Free: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if snapshot exists in APFS
|
||||||
|
echo "🔍 Checking if snapshot exists in APFS..."
|
||||||
|
APFS_CHECK=$(diskutil apfs listSnapshots / 2>/dev/null | grep -i "timemachine" || echo "NOT_FOUND")
|
||||||
|
if [ "$APFS_CHECK" = "NOT_FOUND" ]; then
|
||||||
|
echo " ❌ Snapshot NOT found in APFS"
|
||||||
|
echo " This means it's a GHOST ENTRY - not taking any space!"
|
||||||
|
echo ""
|
||||||
|
echo " The snapshot entry you see is just a stale database record."
|
||||||
|
echo " It's not actually consuming disk space."
|
||||||
|
echo ""
|
||||||
|
echo " ✅ Your space is already available!"
|
||||||
|
echo " The ghost entry will clear on restart."
|
||||||
|
else
|
||||||
|
echo " ✅ Snapshot found in APFS"
|
||||||
|
echo " $APFS_CHECK"
|
||||||
|
echo ""
|
||||||
|
echo " This snapshot IS taking up space."
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Try to get snapshot size
|
||||||
|
SNAPSHOT=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | head -1)
|
||||||
|
if [ -n "$SNAPSHOT" ]; then
|
||||||
|
echo "📸 Snapshot Details:"
|
||||||
|
echo " Name: $SNAPSHOT"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo " Attempting to calculate snapshot size..."
|
||||||
|
SNAP_DATE=$(echo "$SNAPSHOT" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
|
||||||
|
# Try calculatedrift
|
||||||
|
DRIFT_OUTPUT=$(sudo tmutil calculatedrift "$SNAPSHOT" 2>&1 || echo "ERROR")
|
||||||
|
if echo "$DRIFT_OUTPUT" | grep -qi "size\|bytes\|GB\|MB"; then
|
||||||
|
echo " Size information:"
|
||||||
|
echo "$DRIFT_OUTPUT" | grep -i "size\|bytes\|GB\|MB" | head -5 | sed 's/^/ /'
|
||||||
|
else
|
||||||
|
echo " ⚠️ Could not calculate size (snapshot may be corrupted/stuck)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Container vs Volume analysis
|
||||||
|
echo "📦 Container Analysis:"
|
||||||
|
CONTAINER_TOTAL=$(diskutil info / | grep 'Container Total' | awk '{print $4, $5}')
|
||||||
|
CONTAINER_FREE=$(diskutil info / | grep 'Container Free' | awk '{print $4, $5}')
|
||||||
|
VOLUME_USED=$(diskutil info / | grep 'Volume Used Space' | awk '{print $4, $5, $6}')
|
||||||
|
|
||||||
|
echo " Container Total: $CONTAINER_TOTAL"
|
||||||
|
echo " Container Free: $CONTAINER_FREE"
|
||||||
|
echo " Volume Used: $VOLUME_USED"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Calculate if there's unaccounted space
|
||||||
|
CONTAINER_TOTAL_GB=$(diskutil info / | grep 'Container Total' | awk '{print $3}' | tr -d 'GB')
|
||||||
|
CONTAINER_FREE_GB=$(diskutil info / | grep 'Container Free' | awk '{print $3}' | tr -d 'GB')
|
||||||
|
VOLUME_USED_GB=$(diskutil info / | grep 'Volume Used Space' | awk '{print $4}' | tr -d 'GB')
|
||||||
|
|
||||||
|
CONTAINER_USED_GB=$(echo "$CONTAINER_TOTAL_GB - $CONTAINER_FREE_GB" | bc)
|
||||||
|
DISCREPANCY=$(echo "$CONTAINER_USED_GB - $VOLUME_USED_GB" | bc)
|
||||||
|
|
||||||
|
echo " Container Used: ~${CONTAINER_USED_GB}GB"
|
||||||
|
echo " Volume Used: ~${VOLUME_USED_GB}GB"
|
||||||
|
if (( $(echo "$DISCREPANCY > 1" | bc -l) )); then
|
||||||
|
echo " ⚠️ Unaccounted: ~${DISCREPANCY}GB"
|
||||||
|
echo " This could be:"
|
||||||
|
echo " - APFS snapshots"
|
||||||
|
echo " - Other volumes"
|
||||||
|
echo " - Reserved space"
|
||||||
|
else
|
||||||
|
echo " ✅ Space accounting looks normal"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
echo "=== Summary ==="
|
||||||
|
echo ""
|
||||||
|
if [ "$APFS_CHECK" = "NOT_FOUND" ]; then
|
||||||
|
echo "✅ The snapshot is a GHOST ENTRY - it's NOT taking any space!"
|
||||||
|
echo ""
|
||||||
|
echo " Your disk space is already available."
|
||||||
|
echo " The entry will clear on restart."
|
||||||
|
echo ""
|
||||||
|
echo " If 'System Data' is still growing when you delete files,"
|
||||||
|
echo " it's because Time Machine is creating NEW snapshots,"
|
||||||
|
echo " not because of this old ghost entry."
|
||||||
|
else
|
||||||
|
echo "⚠️ The snapshot IS in APFS and may be taking space."
|
||||||
|
echo ""
|
||||||
|
echo " To free the space, you need to:"
|
||||||
|
echo " 1. Remove Time Machine destination"
|
||||||
|
echo " 2. Restart your Mac"
|
||||||
|
echo " 3. The snapshot should be cleared"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
Executable
+64
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Check Space After Unmounting Photo Volume
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Space Check After Unmounting Photo Volume ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
CONTAINER_FREE=$(diskutil info / | grep 'Container Free' | awk '{print $4, $5}')
|
||||||
|
CONTAINER_USED=$(diskutil apfs list 2>/dev/null | grep "Capacity In Use" | awk '{print $6, $7}')
|
||||||
|
|
||||||
|
echo "📊 Current Status:"
|
||||||
|
echo " Free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo " Container free: $CONTAINER_FREE"
|
||||||
|
echo " Container used: $CONTAINER_USED"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if photo is still mounted
|
||||||
|
if mount | grep -q photo; then
|
||||||
|
echo "⚠️ Photo volume is still mounted"
|
||||||
|
else
|
||||||
|
echo "✅ Photo volume is unmounted"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 What's Actually Using Space:"
|
||||||
|
echo ""
|
||||||
|
echo "Top directories in /System/Volumes/Data:"
|
||||||
|
sudo du -h -d 1 /System/Volumes/Data 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Your home directory:"
|
||||||
|
du -h -d 1 ~ 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Analysis ==="
|
||||||
|
echo ""
|
||||||
|
if (( $(echo "$FREE_SPACE_GB < 5" | bc -l) )); then
|
||||||
|
echo "⚠️ Still critically low on space!"
|
||||||
|
echo ""
|
||||||
|
echo " The photo volume unmount didn't free space because:"
|
||||||
|
echo " - Those files were on the NAS (network), not local"
|
||||||
|
echo " - The 179GB was just the size of the network mount"
|
||||||
|
echo " - It wasn't actually consuming local disk space"
|
||||||
|
echo ""
|
||||||
|
echo " Your REAL space usage:"
|
||||||
|
echo " - Container: 492.9GB used (99.7% full)"
|
||||||
|
echo " - Your home: 130GB"
|
||||||
|
echo " - Other system files: ~360GB"
|
||||||
|
echo ""
|
||||||
|
echo " To free space, you need to:"
|
||||||
|
echo " 1. Clean Downloads: 8.7GB"
|
||||||
|
echo " 2. Clean Library/Caches: ~6GB"
|
||||||
|
echo " 3. Review Documents: 40GB (move large files to NAS)"
|
||||||
|
echo " 4. Review .ollama: 17GB (remove unused models)"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo "✅ You have ${FREE_SPACE_GB}GB free - this should be enough!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
# Clash Proxy Server Configuration
|
||||||
|
|
||||||
|
## Server Details
|
||||||
|
- **Server:** server2 (oracle-tokyo)
|
||||||
|
- **Tailscale IP:** 100.70.115.1
|
||||||
|
- **Status:** ✅ Running
|
||||||
|
|
||||||
|
## Proxy Endpoints
|
||||||
|
|
||||||
|
### HTTP Proxy
|
||||||
|
- **Type:** HTTP
|
||||||
|
- **Server:** 100.70.115.1
|
||||||
|
- **Port:** 7890
|
||||||
|
|
||||||
|
### SOCKS5 Proxy
|
||||||
|
- **Type:** SOCKS5
|
||||||
|
- **Server:** 100.70.115.1
|
||||||
|
- **Port:** 7891
|
||||||
|
|
||||||
|
### Mixed Port (Recommended)
|
||||||
|
- **Type:** HTTP/SOCKS5 (auto-detected)
|
||||||
|
- **Server:** 100.70.115.1
|
||||||
|
- **Port:** 7892
|
||||||
|
|
||||||
|
### Web Dashboard
|
||||||
|
- **URL:** http://100.70.115.1:9090/ui
|
||||||
|
- Use this to monitor traffic and manage settings
|
||||||
|
|
||||||
|
## Client Configuration
|
||||||
|
|
||||||
|
### For Clash Clients (Clash for Windows, ClashX, Clash Verge, etc.)
|
||||||
|
|
||||||
|
#### Option 1: Direct Proxy Configuration
|
||||||
|
In your Clash client settings, add a proxy:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
proxies:
|
||||||
|
- name: "server2-proxy"
|
||||||
|
type: http
|
||||||
|
server: 100.70.115.1
|
||||||
|
port: 7890
|
||||||
|
# Or use mixed port:
|
||||||
|
# port: 7892
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option 2: Use as Upstream Proxy
|
||||||
|
If you want to route through server2:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
proxies:
|
||||||
|
- name: "server2"
|
||||||
|
type: http
|
||||||
|
server: 100.70.115.1
|
||||||
|
port: 7892
|
||||||
|
```
|
||||||
|
|
||||||
|
Then add it to your proxy groups:
|
||||||
|
```yaml
|
||||||
|
proxy-groups:
|
||||||
|
- name: "Proxy"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- server2
|
||||||
|
- DIRECT
|
||||||
|
```
|
||||||
|
|
||||||
|
### For System-Wide Proxy (macOS/Windows)
|
||||||
|
|
||||||
|
#### macOS:
|
||||||
|
1. System Settings → Network → Advanced → Proxies
|
||||||
|
2. Check "Web Proxy (HTTP)" and "Secure Web Proxy (HTTPS)"
|
||||||
|
3. Server: 100.70.115.1
|
||||||
|
4. Port: 7890 (or 7892 for mixed)
|
||||||
|
|
||||||
|
#### Windows:
|
||||||
|
1. Settings → Network & Internet → Proxy
|
||||||
|
2. Manual proxy setup
|
||||||
|
3. Address: 100.70.115.1
|
||||||
|
4. Port: 7890
|
||||||
|
|
||||||
|
### For Mobile Apps (iOS/Android)
|
||||||
|
|
||||||
|
Most apps support HTTP/SOCKS5 proxy:
|
||||||
|
- **Type:** HTTP or SOCKS5
|
||||||
|
- **Host:** 100.70.115.1
|
||||||
|
- **Port:** 7890 (HTTP) or 7891 (SOCKS5) or 7892 (Mixed)
|
||||||
|
|
||||||
|
## Testing the Connection
|
||||||
|
|
||||||
|
### Test HTTP Proxy:
|
||||||
|
```bash
|
||||||
|
curl -x http://100.70.115.1:7890 https://api.ipify.org
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test SOCKS5 Proxy:
|
||||||
|
```bash
|
||||||
|
curl --socks5 100.70.115.1:7891 https://api.ipify.org
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check if proxy is working:
|
||||||
|
Visit http://100.70.115.1:9090/ui in your browser to see the Clash dashboard.
|
||||||
|
|
||||||
|
## Management Commands
|
||||||
|
|
||||||
|
### Check Status:
|
||||||
|
```bash
|
||||||
|
ssh server2 'sudo systemctl status clash-meta'
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Logs:
|
||||||
|
```bash
|
||||||
|
ssh server2 'sudo journalctl -u clash-meta -f'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart Service:
|
||||||
|
```bash
|
||||||
|
ssh server2 'sudo systemctl restart clash-meta'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop Service:
|
||||||
|
```bash
|
||||||
|
ssh server2 'sudo systemctl stop clash-meta'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- All traffic routed through server2 will use server2's internet connection
|
||||||
|
- The proxy is accessible only via Tailscale network (secure)
|
||||||
|
- No authentication required (protected by Tailscale)
|
||||||
|
- The proxy uses "direct" mode - all traffic goes directly through server2's connection
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+142
@@ -0,0 +1,142 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Clean Time Machine System Files
|
||||||
|
# This script safely removes Time Machine files from system locations
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Time Machine System Files Cleanup ==="
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ WARNING: This script will delete Time Machine system files."
|
||||||
|
echo " Make sure you understand what will be deleted."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check current free space
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Ask for confirmation
|
||||||
|
read -p "Do you want to proceed? This will delete Time Machine system files. (yes/no) " -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
||||||
|
echo "Cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🧹 Cleaning Time Machine system files..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREED_TOTAL=0
|
||||||
|
|
||||||
|
# 1. Delete local snapshots
|
||||||
|
echo "1. Deleting local snapshots..."
|
||||||
|
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
if [ -n "$SNAPSHOTS" ]; then
|
||||||
|
echo "$SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
echo " Deleting snapshot: $snapshot"
|
||||||
|
sudo tmutil deletelocalsnapshots "$snapshot" 2>/dev/null || {
|
||||||
|
echo " ⚠️ Could not delete $snapshot (may require different method)"
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo " ✓ Local snapshots deleted"
|
||||||
|
else
|
||||||
|
echo " ✓ No local snapshots to delete"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. Disable local snapshots temporarily (they'll recreate but this helps)
|
||||||
|
echo "2. Disabling local snapshots (to prevent immediate recreation)..."
|
||||||
|
sudo tmutil disablelocal 2>/dev/null || echo " ⚠️ Could not disable local snapshots"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. Clean MobileBackups (if they exist and are safe to remove)
|
||||||
|
echo "3. Checking MobileBackups..."
|
||||||
|
if [ -d "/.MobileBackups" ] || [ -d "/System/Volumes/Data/.MobileBackups" ]; then
|
||||||
|
echo " ⚠️ MobileBackups directory found."
|
||||||
|
echo " These are APFS snapshots. They're usually managed automatically."
|
||||||
|
echo " Deleting them manually can cause issues."
|
||||||
|
echo " Recommendation: Let macOS manage these automatically."
|
||||||
|
echo " They will be deleted when space is needed."
|
||||||
|
read -p " Do you want to try deleting MobileBackups? (yes/no) " -r
|
||||||
|
if [[ $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
||||||
|
if [ -d "/.MobileBackups" ]; then
|
||||||
|
echo " Attempting to delete /.MobileBackups..."
|
||||||
|
sudo rm -rf /.MobileBackups/* 2>/dev/null || echo " ⚠️ Could not delete (may be in use)"
|
||||||
|
fi
|
||||||
|
if [ -d "/System/Volumes/Data/.MobileBackups" ]; then
|
||||||
|
echo " Attempting to delete /System/Volumes/Data/.MobileBackups..."
|
||||||
|
sudo rm -rf /System/Volumes/Data/.MobileBackups/* 2>/dev/null || echo " ⚠️ Could not delete (may be in use)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✓ No MobileBackups directory found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 4. Find and remove orphaned sparse bundles
|
||||||
|
echo "4. Searching for orphaned Time Machine sparse bundles..."
|
||||||
|
find /private/var -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | while read bundle; do
|
||||||
|
if [ -e "$bundle" ]; then
|
||||||
|
SIZE=$(sudo du -sh "$bundle" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Found: $bundle ($SIZE)"
|
||||||
|
read -p " Delete this bundle? (yes/no) " -r
|
||||||
|
if [[ $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
||||||
|
sudo rm -rf "$bundle" 2>/dev/null && echo " ✓ Deleted" || echo " ⚠️ Could not delete"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 5. Clean Time Machine logs (safe, will regenerate)
|
||||||
|
echo "5. Cleaning Time Machine logs..."
|
||||||
|
sudo rm -rf /private/var/log/com.apple.TimeMachine* 2>/dev/null || true
|
||||||
|
echo " ✓ Logs cleaned"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 6. Re-enable local snapshots (they're useful, just need space first)
|
||||||
|
echo "6. Re-enabling local snapshots..."
|
||||||
|
sudo tmutil enablelocal 2>/dev/null || echo " ⚠️ Could not re-enable (may already be enabled)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check new free space
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " Freed: 0GB (files may be in use or protected)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if (( $(echo "$FREE_SPACE_GB_AFTER < 10" | bc -l) )); then
|
||||||
|
echo "⚠️ Still low on space. The 100GB+ may be in a protected location."
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo "1. Check macOS Storage Management:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Manage"
|
||||||
|
echo " Look for 'System Files' and see what's taking space"
|
||||||
|
echo ""
|
||||||
|
echo "2. The files may be APFS snapshots that need special handling:"
|
||||||
|
echo " sudo tmutil listlocalsnapshots /"
|
||||||
|
echo " # Then delete each one:"
|
||||||
|
echo " sudo tmutil deletelocalsnapshots <snapshot-name>"
|
||||||
|
echo ""
|
||||||
|
echo "3. Check for large files in system locations:"
|
||||||
|
echo " sudo du -h -d 1 /System/Volumes/Data | sort -hr | head -20"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo "✅ Good! You should have enough space for Time Machine now."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+93
@@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Cleanup Ghost Time Machine Snapshot
|
||||||
|
# Sometimes snapshots appear in the list but don't actually exist or take space
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Cleanup Ghost Time Machine Snapshot ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check current free space
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# List snapshots
|
||||||
|
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
if [ -z "$SNAPSHOTS" ]; then
|
||||||
|
echo "✅ No snapshots found - all clean!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Found snapshot(s):"
|
||||||
|
echo "$SNAPSHOTS" | sed 's/^/ - /'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# The snapshot might be a ghost entry. Let's try several methods:
|
||||||
|
|
||||||
|
echo "Attempting cleanup methods..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Method 1: Try deleting with date format
|
||||||
|
echo "Method 1: Delete by date..."
|
||||||
|
echo "$SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
# Extract date: com.apple.TimeMachine.2025-12-31-101235.backup -> 2025-12-31-101235
|
||||||
|
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
if [ -n "$SNAP_DATE" ]; then
|
||||||
|
echo " Trying: sudo tmutil deletelocalsnapshots $SNAP_DATE"
|
||||||
|
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
||||||
|
echo " ✅ Success!"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Failed (may be ghost entry)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Method 2: Thin all snapshots (aggressive)
|
||||||
|
echo "Method 2: Aggressive thinning..."
|
||||||
|
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1 || true
|
||||||
|
echo " ✓ Thinning completed"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Method 3: Check if it's actually taking space
|
||||||
|
echo "Method 3: Checking if snapshot actually exists..."
|
||||||
|
APFS_SNAPSHOTS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -i "timemachine" || echo "")
|
||||||
|
if [ -z "$APFS_SNAPSHOTS" ]; then
|
||||||
|
echo " ℹ️ Snapshot not found in APFS snapshot list"
|
||||||
|
echo " This confirms it's likely a ghost entry in Time Machine's database"
|
||||||
|
echo ""
|
||||||
|
echo " The snapshot entry may persist in Time Machine's database but:"
|
||||||
|
echo " - It's not taking up space (space was already freed)"
|
||||||
|
echo " - It will likely clear when Time Machine successfully backs up"
|
||||||
|
echo " - Or it may clear on the next macOS update/restart"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Final check
|
||||||
|
sleep 2
|
||||||
|
REMAINING=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
||||||
|
|
||||||
|
if [ "$REMAINING" -gt 0 ]; then
|
||||||
|
echo "⚠️ Snapshot still listed, but this is likely a ghost entry."
|
||||||
|
echo ""
|
||||||
|
echo "✅ Good news: Your space was already freed (${FREE_SPACE_GB}GB free)!"
|
||||||
|
echo ""
|
||||||
|
echo "The ghost entry should clear when:"
|
||||||
|
echo " 1. Time Machine successfully completes a backup"
|
||||||
|
echo " 2. macOS updates"
|
||||||
|
echo " 3. Or it may persist but won't cause issues"
|
||||||
|
echo ""
|
||||||
|
echo "You can safely ignore it - it's not taking up space."
|
||||||
|
else
|
||||||
|
echo "✅ Snapshot successfully removed!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+67
@@ -0,0 +1,67 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# EnConvo Settings Crash Debug Script
|
||||||
|
# Run this script, then click Settings in EnConvo to capture the crash
|
||||||
|
|
||||||
|
echo "=== EnConvo Settings Crash Debugger ==="
|
||||||
|
echo ""
|
||||||
|
echo "This script will:"
|
||||||
|
echo "1. Monitor crash logs"
|
||||||
|
echo "2. Capture Console output"
|
||||||
|
echo "3. Show process info"
|
||||||
|
echo ""
|
||||||
|
echo "Press Ctrl+C to stop monitoring"
|
||||||
|
echo ""
|
||||||
|
echo "Starting monitoring... (Now click Settings in EnConvo)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get the current time for filtering logs
|
||||||
|
START_TIME=$(date +"%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
# Function to check for crash reports
|
||||||
|
check_crashes() {
|
||||||
|
echo "=== Checking for Crash Reports ==="
|
||||||
|
CRASH_DIR="$HOME/Library/Logs/DiagnosticReports"
|
||||||
|
if [ -d "$CRASH_DIR" ]; then
|
||||||
|
echo "Recent EnConvo crash reports:"
|
||||||
|
find "$CRASH_DIR" -name "*EnConvo*" -type f -mmin -5 2>/dev/null | head -5
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to monitor Console logs
|
||||||
|
monitor_console() {
|
||||||
|
echo "=== Monitoring Console Logs (last 20 lines) ==="
|
||||||
|
log show --predicate 'process == "EnConvo"' --last 1m --style compact 2>/dev/null | tail -20
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check running processes
|
||||||
|
check_processes() {
|
||||||
|
echo "=== EnConvo Processes ==="
|
||||||
|
ps aux | grep -i enconvo | grep -v grep
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run initial checks
|
||||||
|
check_processes
|
||||||
|
|
||||||
|
# Monitor in a loop
|
||||||
|
while true; do
|
||||||
|
sleep 2
|
||||||
|
check_crashes
|
||||||
|
monitor_console
|
||||||
|
check_processes
|
||||||
|
echo "--- Waiting for crash (click Settings now if you haven't) ---"
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+104
@@ -0,0 +1,104 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Deep Space Analysis - Find where the 20GB actually went
|
||||||
|
# When deleted files don't free space even after restart
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Deep Space Analysis ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Container vs Volume space
|
||||||
|
echo "📊 Container vs Volume Space:"
|
||||||
|
echo " Container Total: $(diskutil info / | grep 'Container Total' | awk '{print $4, $5}')"
|
||||||
|
echo " Container Free: $(diskutil info / | grep 'Container Free' | awk '{print $4, $5}')"
|
||||||
|
echo " Volume Used: $(diskutil info / | grep 'Volume Used Space' | awk '{print $4, $5, $6}')"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Calculate discrepancy
|
||||||
|
CONTAINER_TOTAL=$(diskutil info / | grep 'Container Total' | awk '{print $3}' | tr -d 'GB')
|
||||||
|
CONTAINER_FREE=$(diskutil info / | grep 'Container Free' | awk '{print $3}' | tr -d 'GB')
|
||||||
|
VOLUME_USED=$(diskutil info / | grep 'Volume Used Space' | awk '{print $4}' | tr -d 'GB')
|
||||||
|
|
||||||
|
CONTAINER_USED=$(echo "$CONTAINER_TOTAL - $CONTAINER_FREE" | bc)
|
||||||
|
DISCREPANCY=$(echo "$CONTAINER_USED - $VOLUME_USED" | bc)
|
||||||
|
|
||||||
|
echo " Container Used: ~${CONTAINER_USED}GB"
|
||||||
|
echo " Volume Used: ~${VOLUME_USED}GB"
|
||||||
|
if (( $(echo "$DISCREPANCY > 5" | bc -l) )); then
|
||||||
|
echo " ⚠️ Discrepancy: ~${DISCREPANCY}GB unaccounted for!"
|
||||||
|
echo " This space may be in:"
|
||||||
|
echo " - Other APFS volumes"
|
||||||
|
echo " - APFS snapshots"
|
||||||
|
echo " - Reserved space"
|
||||||
|
echo " - System files"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check all APFS volumes
|
||||||
|
echo "📦 APFS Volumes:"
|
||||||
|
diskutil apfs list 2>/dev/null | grep -E "Volume Name|Used Space|Free Space" | head -20 | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check snapshots
|
||||||
|
echo "📸 APFS Snapshots:"
|
||||||
|
SNAP_COUNT=$(diskutil apfs listSnapshots / 2>/dev/null | grep -c "Name:" || echo "0")
|
||||||
|
echo " Found $SNAP_COUNT snapshot(s)"
|
||||||
|
if [ "$SNAP_COUNT" -gt 0 ]; then
|
||||||
|
diskutil apfs listSnapshots / 2>/dev/null | grep -E "Name|Purgeable" | head -6 | sed 's/^/ /'
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for large directories that might have been missed
|
||||||
|
echo "🔍 Large Directories Check:"
|
||||||
|
echo " Home directory: $(du -sh ~ 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo " Documents: $(du -sh ~/Documents 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo " Library: $(du -sh ~/Library 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo " Downloads: $(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo " Movies: $(du -sh ~/Movies 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if files were actually deleted
|
||||||
|
echo "❓ Verification:"
|
||||||
|
echo " You mentioned deleting 20GB from Movies/Videos folder"
|
||||||
|
echo " Current Movies folder: $(du -sh ~/Movies 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo ""
|
||||||
|
echo " Questions:"
|
||||||
|
echo " 1. Did you delete from ~/Movies or another location?"
|
||||||
|
echo " 2. Did you empty Trash after deleting?"
|
||||||
|
echo " 3. Are the files still in Trash?"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check trash
|
||||||
|
TRASH_SIZE=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " Trash size: $TRASH_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
echo "=== Analysis ==="
|
||||||
|
echo ""
|
||||||
|
if (( $(echo "$DISCREPANCY > 15" | bc -l) )); then
|
||||||
|
echo "⚠️ Found ${DISCREPANCY}GB+ unaccounted space in container!"
|
||||||
|
echo ""
|
||||||
|
echo " This suggests:"
|
||||||
|
echo " 1. Files may not have been actually deleted"
|
||||||
|
echo " 2. Space is in another APFS volume"
|
||||||
|
echo " 3. APFS snapshots are holding space"
|
||||||
|
echo " 4. System reserved space"
|
||||||
|
echo ""
|
||||||
|
echo " Next steps:"
|
||||||
|
echo " 1. Verify files were actually deleted (not just moved to Trash)"
|
||||||
|
echo " 2. Empty Trash: rm -rf ~/.Trash/*"
|
||||||
|
echo " 3. Check other volumes: diskutil apfs list"
|
||||||
|
echo " 4. Check for large files: find ~ -size +1G -type f 2>/dev/null"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo " Space accounting looks normal."
|
||||||
|
echo " The 20GB may have been:"
|
||||||
|
echo " - Used by other files growing"
|
||||||
|
echo " - Actually still present (not deleted)"
|
||||||
|
echo " - In Trash (not emptied)"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+81
@@ -0,0 +1,81 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Delete Local Snapshot to Free Space
|
||||||
|
# Since files are on NAS, it's safe to remove the snapshot
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Delete Local Snapshot to Free Space ==="
|
||||||
|
echo ""
|
||||||
|
echo "Since your files are safely backed up on NAS, we can delete"
|
||||||
|
echo "the local snapshot to free up space."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check snapshot
|
||||||
|
SNAPSHOT=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | head -1)
|
||||||
|
if [ -z "$SNAPSHOT" ]; then
|
||||||
|
echo "✅ No snapshot found - you're all set!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Found snapshot: $SNAPSHOT"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Extract date
|
||||||
|
SNAP_DATE=$(echo "$SNAPSHOT" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
|
||||||
|
if [ -z "$SNAP_DATE" ]; then
|
||||||
|
echo "⚠️ Could not parse snapshot date"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Attempting to delete snapshot: $SNAP_DATE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Try to delete
|
||||||
|
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
||||||
|
echo "✅ Successfully deleted snapshot!"
|
||||||
|
echo ""
|
||||||
|
echo "⏳ Waiting for space to be released..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "⚠️ Could not delete snapshot (Stale NFS file handle error)"
|
||||||
|
echo ""
|
||||||
|
echo "This is a known issue. The snapshot is stuck because:"
|
||||||
|
echo " - Time Machine had a stale connection to NAS"
|
||||||
|
echo " - The snapshot reference is corrupted"
|
||||||
|
echo ""
|
||||||
|
echo "=== Solutions ==="
|
||||||
|
echo ""
|
||||||
|
echo "Option 1: Restart your Mac (Recommended)"
|
||||||
|
echo " This will release the stuck snapshot and free the space."
|
||||||
|
echo " After restart, the snapshot should be gone."
|
||||||
|
echo ""
|
||||||
|
echo "Option 2: Wait for macOS to auto-clean"
|
||||||
|
echo " macOS will eventually clean up stuck snapshots, but this"
|
||||||
|
echo " can take hours or days."
|
||||||
|
echo ""
|
||||||
|
echo "The good news: The snapshot is a GHOST ENTRY (not in APFS)."
|
||||||
|
echo "This means the space may already be available - the entry"
|
||||||
|
echo "is just a stale database record that will clear on restart."
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+69
@@ -0,0 +1,69 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Diagnose Synology USB Copy Issue
|
||||||
|
# Connects to NAS and checks USB device status
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Synology USB Copy Diagnosis ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if nas alias works
|
||||||
|
if ! command -v nas &> /dev/null; then
|
||||||
|
echo "⚠️ 'nas' alias not found. Using SSH directly."
|
||||||
|
echo " Please provide: ssh user@nas-ip"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🔍 Checking USB device status on NAS..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "1. USB Devices Connected:"
|
||||||
|
nas "lsusb 2>/dev/null || echo 'lsusb not available, checking dmesg...' && dmesg | grep -i usb | tail -5" || echo " ⚠️ Could not check USB devices"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "2. USB Mount Points:"
|
||||||
|
nas "mount | grep -i usb || echo ' No USB devices mounted'" || echo " ⚠️ Could not check mounts"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "3. USB Volumes:"
|
||||||
|
nas "ls -la /volumeUSB*/ 2>/dev/null || echo ' No /volumeUSB* directories found'" || echo " ⚠️ Could not check USB volumes"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "4. Disk Partitions:"
|
||||||
|
nas "cat /proc/partitions | grep -v '^major' | head -10" || echo " ⚠️ Could not check partitions"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "5. Disk Usage (USB devices):"
|
||||||
|
nas "df -h | grep -i usb || echo ' No USB devices in df output'" || echo " ⚠️ Could not check disk usage"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "6. USB Copy Service Status:"
|
||||||
|
nas "synoservice --status pkgctl-USB-Copy 2>/dev/null || echo ' Could not check USB Copy service status'" || echo " ⚠️ Could not check service"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "7. USB Copy Configuration:"
|
||||||
|
nas "cat /usr/syno/etc/packages/USB-Copy/usbcopy.conf 2>/dev/null | head -20 || echo ' Could not read USB Copy config'" || echo " ⚠️ Could not read config"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "8. Check for USB devices in /dev:"
|
||||||
|
nas "ls -la /dev/sd* /dev/hd* 2>/dev/null | head -10 || echo ' No USB block devices found'" || echo " ⚠️ Could not check devices"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Diagnosis Summary ==="
|
||||||
|
echo ""
|
||||||
|
echo "Common issues to check:"
|
||||||
|
echo ""
|
||||||
|
echo "1. If no USB devices found:"
|
||||||
|
echo " - USB device not connected to front port"
|
||||||
|
echo " - USB device not recognized by Synology"
|
||||||
|
echo " - Try different USB device"
|
||||||
|
echo ""
|
||||||
|
echo "2. If USB device mounted but USB Copy shows 'Unavailable':"
|
||||||
|
echo " - USB device mounted as shared folder"
|
||||||
|
echo " - Another task using the USB device"
|
||||||
|
echo " - Need to unmount from other uses"
|
||||||
|
echo ""
|
||||||
|
echo "3. If USB Copy service not running:"
|
||||||
|
echo " - Package Center → USB Copy → Start"
|
||||||
|
echo ""
|
||||||
Executable
+104
@@ -0,0 +1,104 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Emergency Free Space - When Time Machine is stuck and consuming space
|
||||||
|
# This script provides the quickest way to free space
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Emergency Free Space Fix ==="
|
||||||
|
echo ""
|
||||||
|
echo "Time Machine is stuck and holding your deleted file space."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Solution: Remove Time Machine destination to free the stuck snapshot"
|
||||||
|
echo ""
|
||||||
|
echo "The snapshot is stuck because Time Machine can't connect to your NAS."
|
||||||
|
echo "Removing the destination will allow the snapshot to be deleted."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Have you removed the Time Machine destination in System Settings? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "Please do this now:"
|
||||||
|
echo "1. Open System Settings → General → Time Machine"
|
||||||
|
echo "2. Click the '-' button to remove the backup disk"
|
||||||
|
echo "3. Confirm removal"
|
||||||
|
echo ""
|
||||||
|
echo "Then run this script again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "⏳ Waiting for Time Machine to fully disconnect..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Kill any remaining backup processes
|
||||||
|
echo "🛑 Stopping any remaining Time Machine processes..."
|
||||||
|
sudo killall backupd 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Try to delete the snapshot now
|
||||||
|
echo ""
|
||||||
|
echo "🗑️ Attempting to delete stuck snapshot..."
|
||||||
|
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
if [ -n "$SNAPSHOTS" ]; then
|
||||||
|
echo "$SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
if [ -n "$SNAP_DATE" ]; then
|
||||||
|
echo " Deleting: $snapshot"
|
||||||
|
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
||||||
|
echo " ✅ Successfully deleted!"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Still stuck. Try restarting your Mac."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " ✅ No snapshots found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Checking results..."
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 15" | bc -l) )); then
|
||||||
|
echo " ✅ Successfully freed: ${FREED_GB}GB"
|
||||||
|
echo ""
|
||||||
|
echo " Your 20GB from deleted files should now be available!"
|
||||||
|
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
echo " (May need restart to free remaining space)"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Space not freed yet"
|
||||||
|
echo ""
|
||||||
|
echo " Try restarting your Mac - this often releases stuck snapshots."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Next Steps ==="
|
||||||
|
echo ""
|
||||||
|
echo "1. After space is freed, fix Time Machine connection:"
|
||||||
|
echo " See: time_machine_troubleshooting.md"
|
||||||
|
echo ""
|
||||||
|
echo "2. Common fixes for NAS connection:"
|
||||||
|
echo " - Clear credentials: Keychain Access → search 'DS224plus' → delete"
|
||||||
|
echo " - Re-add Time Machine: System Settings → Time Machine → Add Backup Disk"
|
||||||
|
echo ""
|
||||||
|
echo "3. Once connection is fixed, Time Machine will work properly."
|
||||||
|
echo ""
|
||||||
Executable
+84
@@ -0,0 +1,84 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Emergency Options - When Update Can't Download
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Emergency Options ==="
|
||||||
|
echo ""
|
||||||
|
echo "Update download failed: Need 17.64GB, have less."
|
||||||
|
echo "You're in a catch-22 situation."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo "Needed: 17.64GB"
|
||||||
|
echo "Shortfall: ~$(echo "17.64 - $FREE_SPACE_GB" | bc)GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 OPTIONS:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "1. **Use External Drive** (BEST OPTION)"
|
||||||
|
echo ""
|
||||||
|
echo " If you have an external USB drive:"
|
||||||
|
echo " a) Connect it"
|
||||||
|
echo " b) Move large files there (not NAS - external drive):"
|
||||||
|
echo " - Downloads (8.7GB)"
|
||||||
|
echo " - .ollama (17GB)"
|
||||||
|
echo " - .local (18GB)"
|
||||||
|
echo " c) Install macOS update"
|
||||||
|
echo " d) After update clears snapshot, move files back"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "2. **Contact Apple Support** (RECOMMENDED)"
|
||||||
|
echo ""
|
||||||
|
echo " Phone: 1-800-275-2273"
|
||||||
|
echo " Explain: 'OS update snapshot preventing space recovery'"
|
||||||
|
echo " They may:"
|
||||||
|
echo " - Have tools to force-clear snapshot"
|
||||||
|
echo " - Help with update process"
|
||||||
|
echo " - Provide other solutions"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "3. **Try System Settings Update** (Sometimes works differently)"
|
||||||
|
echo ""
|
||||||
|
echo " System Settings → General → Software Update"
|
||||||
|
echo " Click 'Update Now'"
|
||||||
|
echo " Sometimes GUI works when command line doesn't"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "4. **Check for External Storage**"
|
||||||
|
echo ""
|
||||||
|
echo " Do you have:"
|
||||||
|
echo " - USB drive?"
|
||||||
|
echo " - SD card?"
|
||||||
|
echo " - Another Mac you can network to?"
|
||||||
|
echo " - Cloud storage (iCloud, Dropbox, etc.)?"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "5. **Last Resort: Clean Install** (Loses data, not recommended)"
|
||||||
|
echo ""
|
||||||
|
echo " ⚠️ Only if you have everything backed up"
|
||||||
|
echo " - Create bootable installer"
|
||||||
|
echo " - Fresh install macOS"
|
||||||
|
echo " - Restore from Time Machine"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== What You CAN Do Right Now ==="
|
||||||
|
echo ""
|
||||||
|
echo "Even though space isn't freed, your files ARE safe on NAS."
|
||||||
|
echo ""
|
||||||
|
echo "The space WILL be freed after updating macOS."
|
||||||
|
echo ""
|
||||||
|
echo "The blocker is: You need space to update, but can't free space"
|
||||||
|
echo "because the snapshot preserves everything."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🎯 IMMEDIATE ACTION:"
|
||||||
|
echo ""
|
||||||
|
echo "1. Check if you have external drive"
|
||||||
|
echo "2. If yes: Use it to temporarily move files"
|
||||||
|
echo "3. If no: Contact Apple Support (1-800-275-2273)"
|
||||||
|
echo ""
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
EnConvo Settings Crash Report
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
- Device: MacBook Air (M1)
|
||||||
|
- macOS Version: Ventura 13.x
|
||||||
|
- App Version: 2.2.22
|
||||||
|
- Issue: App crashes when clicking Settings sidebar button
|
||||||
|
|
||||||
|
Error Output:
|
||||||
|
-------------
|
||||||
|
PostHog -> Error not initialized due to missing API key or host
|
||||||
|
|
||||||
|
[SwiftCPUDetect] Detected CPU type number: 16777228
|
||||||
|
[SwiftCPUDetect] Detected CPU subtype number: 2
|
||||||
|
[SwiftCPUDetect] Detected CPU family number: 458787763
|
||||||
|
[SwiftCPUDetect] Detected cpu architecture of the current process is: arm64
|
||||||
|
|
||||||
|
WARNING: The sun_len field of a sockaddr_un structure passed to CFSocketSetAddress was not set correctly using the SUN_LEN macro.
|
||||||
|
|
||||||
|
(node) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
|
||||||
|
|
||||||
|
zsh: trace trap /Applications/EnConvo.app/Contents/MacOS/EnConvo
|
||||||
|
|
||||||
|
Crash Type:
|
||||||
|
-----------
|
||||||
|
"trace trap" indicates the app received a SIGTRAP signal, typically from:
|
||||||
|
- Breakpoint hit
|
||||||
|
- Assertion failure
|
||||||
|
- Debugger attachment
|
||||||
|
- Memory access violation
|
||||||
|
|
||||||
|
Note: This works fine on macOS 15 (MBP) with version 2.2.21
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
EnConvo Settings Crash Report - macOS Ventura
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
-----------
|
||||||
|
- Device: MacBook Air (M1)
|
||||||
|
- macOS Version: Ventura 13.6.4 (22G513)
|
||||||
|
- App Version: 2.2.22 (Build 252)
|
||||||
|
- Bundle ID: com.frostyeve.enconvo
|
||||||
|
- Issue: App crashes when clicking Settings sidebar button
|
||||||
|
|
||||||
|
Note: Works fine on macOS 15 (MBP) with version 2.2.21
|
||||||
|
|
||||||
|
Crash Details:
|
||||||
|
--------------
|
||||||
|
Exception Type: EXC_BREAKPOINT
|
||||||
|
Signal: SIGTRAP
|
||||||
|
Termination Reason: Trace/BPT trap: 5
|
||||||
|
Faulting Thread: 0 (Main Thread)
|
||||||
|
|
||||||
|
Crash Location:
|
||||||
|
---------------
|
||||||
|
The crash occurs in AttributeGraph framework during SwiftUI layout operations:
|
||||||
|
|
||||||
|
Stack Trace (Key Frames):
|
||||||
|
- AG::Graph::UpdateStack::update() [AttributeGraph]
|
||||||
|
- AG::Graph::update_attribute() [AttributeGraph]
|
||||||
|
- AG::Graph::input_value_ref_slow() [AttributeGraph]
|
||||||
|
- AGGraphGetValue [AttributeGraph]
|
||||||
|
- NSView layout operations [AppKit]
|
||||||
|
- NSWindow layoutIfNeeded [AppKit]
|
||||||
|
- CATransaction commit [QuartzCore]
|
||||||
|
- CFRunLoopRun [CoreFoundation]
|
||||||
|
- NSApplicationMain [AppKit]
|
||||||
|
|
||||||
|
The crash happens during the layout phase when opening Settings, specifically in:
|
||||||
|
- NSView _layoutSubtreeWithOldSize
|
||||||
|
- NSWindow _layoutViewTree
|
||||||
|
- AttributeGraph update cycle
|
||||||
|
|
||||||
|
Error Description:
|
||||||
|
-----------------
|
||||||
|
The app triggers a breakpoint (EXC_BREAKPOINT) during SwiftUI/AttributeGraph layout
|
||||||
|
operations when the Settings view is being rendered. This suggests a compatibility
|
||||||
|
issue between the SwiftUI/AttributeGraph version in macOS Ventura (13.6.4) and
|
||||||
|
the app's layout code.
|
||||||
|
|
||||||
|
Possible Causes:
|
||||||
|
---------------
|
||||||
|
1. SwiftUI/AttributeGraph API incompatibility between macOS 13 and 15
|
||||||
|
2. Layout constraint or view hierarchy issue specific to macOS 13
|
||||||
|
3. Memory access issue during layout pass on Ventura
|
||||||
|
|
||||||
|
Reproduction Steps:
|
||||||
|
------------------
|
||||||
|
1. Launch EnConvo on macOS Ventura 13.6.4
|
||||||
|
2. Click Settings button in sidebar
|
||||||
|
3. App immediately crashes
|
||||||
|
|
||||||
|
Additional Info:
|
||||||
|
---------------
|
||||||
|
- App runs fine until Settings is clicked
|
||||||
|
- No error dialog shown to user (silent crash)
|
||||||
|
- Crash report generated: EnConvo-2025-11-28-002456.ips
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
EnConvo Pricing & Feature Clarification
|
||||||
|
========================================
|
||||||
|
|
||||||
|
I'm trying to understand the differences between the free and paid versions of EnConvo, particularly regarding API usage and feature limitations.
|
||||||
|
|
||||||
|
Current Understanding:
|
||||||
|
----------------------
|
||||||
|
1. The paid version appears to cover:
|
||||||
|
- API usage fees (for EnConvo's cloud plan)
|
||||||
|
- App updates/maintenance
|
||||||
|
|
||||||
|
2. Free version limitations:
|
||||||
|
- 10 uses/day limit (presumably for EnConvo's cloud plan API)
|
||||||
|
|
||||||
|
Questions:
|
||||||
|
----------
|
||||||
|
|
||||||
|
1. **Using Own API Keys in Free Version:**
|
||||||
|
If I use my own API keys (e.g., OpenAI, Anthropic, etc.) in the free version:
|
||||||
|
- Are there any feature limitations or restrictions?
|
||||||
|
- Does the 10 uses/day limit apply to my own API keys, or only to EnConvo's cloud plan?
|
||||||
|
- Can I use unlimited requests with my own API keys on the free version?
|
||||||
|
|
||||||
|
2. **10 Uses/Day Limit Clarification:**
|
||||||
|
My understanding is that the 10 uses/day limit applies only to EnConvo's cloud plan API usage, not to requests made with my own API keys. Is this correct?
|
||||||
|
|
||||||
|
3. **Cloud Plan vs Own API Keys:**
|
||||||
|
- What are the advantages of using EnConvo's cloud plan (points system) versus using my own API keys?
|
||||||
|
- Does the cloud plan provide access to multiple models that might not be available through direct API access?
|
||||||
|
- Are there any models or features exclusive to the cloud plan?
|
||||||
|
|
||||||
|
4. **Paid Version Benefits:**
|
||||||
|
Beyond covering API costs and updates, are there any additional features, capabilities, or benefits exclusive to the paid version when using your own API keys?
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
--------
|
||||||
|
I want to clarify whether the free version with my own API keys provides full functionality (unlimited usage), or if there are still limitations/restrictions that would require upgrading to the paid version.
|
||||||
|
|
||||||
|
Thank you for your clarification!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
EnConvo Pricing Question - Free vs Paid
|
||||||
|
========================================
|
||||||
|
|
||||||
|
I'm trying to clarify the differences between free and paid versions, especially regarding API usage.
|
||||||
|
|
||||||
|
My Understanding:
|
||||||
|
-----------------
|
||||||
|
- Paid version covers: API usage fees (EnConvo cloud plan) + app updates
|
||||||
|
- Free version: 10 uses/day limit (for EnConvo's cloud plan API)
|
||||||
|
|
||||||
|
Questions:
|
||||||
|
----------
|
||||||
|
|
||||||
|
1. **Using My Own API Keys:**
|
||||||
|
If I use my own API keys (OpenAI, Anthropic, etc.) in the free version:
|
||||||
|
- Is the 10 uses/day limit still applied, or does it only apply to EnConvo's cloud plan?
|
||||||
|
- Are there any feature limitations when using my own keys?
|
||||||
|
- Can I use unlimited requests with my own API keys on the free version?
|
||||||
|
|
||||||
|
2. **Cloud Plan Benefits:**
|
||||||
|
What advantages does EnConvo's cloud plan offer over using my own API keys directly? (e.g., access to multiple models, better pricing, exclusive features?)
|
||||||
|
|
||||||
|
3. **Paid Version Benefits:**
|
||||||
|
Beyond API costs and updates, are there additional features exclusive to the paid version when using my own API keys?
|
||||||
|
|
||||||
|
In summary: Does the free version with my own API keys provide full, unlimited functionality, or are there still restrictions that require upgrading?
|
||||||
|
|
||||||
|
Thanks!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+86
@@ -0,0 +1,86 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Explain Why Moving Files Doesn't Free Space
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Why Moving Files Doesn't Free Space ==="
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ THE PROBLEM:"
|
||||||
|
echo ""
|
||||||
|
echo "When you move/delete files, the OS update snapshot preserves them."
|
||||||
|
echo "This means:"
|
||||||
|
echo " - Files are moved to NAS ✅"
|
||||||
|
echo " - But space isn't freed on Mac ❌"
|
||||||
|
echo " - System Data grows instead 📈"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📸 The OS Update Snapshot:"
|
||||||
|
SNAPSHOT=$(diskutil apfs listSnapshots / 2>/dev/null | grep "Name:" | head -1)
|
||||||
|
if [ -n "$SNAPSHOT" ]; then
|
||||||
|
echo "$SNAPSHOT" | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
echo " This snapshot:"
|
||||||
|
echo " - Is NOT purgeable"
|
||||||
|
echo " - Preserves all deleted/moved files"
|
||||||
|
echo " - Can't be deleted manually"
|
||||||
|
echo " - Will only clear when you update macOS"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 What's Happening:"
|
||||||
|
echo ""
|
||||||
|
echo "1. You move files → Files go to NAS ✅"
|
||||||
|
echo "2. macOS snapshot preserves them → System Data grows 📈"
|
||||||
|
echo "3. Space isn't freed → Still full ❌"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== THE ONLY SOLUTION ==="
|
||||||
|
echo ""
|
||||||
|
echo "You MUST install the macOS update to clear the snapshot."
|
||||||
|
echo ""
|
||||||
|
echo "But you need space to install the update (17.64GB needed)."
|
||||||
|
echo ""
|
||||||
|
echo "This is a catch-22 situation:"
|
||||||
|
echo " - Need space to update"
|
||||||
|
echo " - Can't get space because snapshot preserves deleted files"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== WORKAROUND ==="
|
||||||
|
echo ""
|
||||||
|
echo "Option 1: Free space from sources that DON'T trigger snapshots:"
|
||||||
|
echo " - Clean caches: rm -rf ~/Library/Caches/* (~6GB)"
|
||||||
|
echo " - Clean user cache: rm -rf ~/.cache/* (~3GB)"
|
||||||
|
echo " - Clean npm: npm cache clean --force (~1GB)"
|
||||||
|
echo " Total: ~10GB (still not enough for 17.64GB update)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Option 2: Try downloading update with less space:"
|
||||||
|
echo " sudo softwareupdate --download --all"
|
||||||
|
echo " (Sometimes works with less than required space)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Option 3: Use external drive temporarily:"
|
||||||
|
echo " - Move files to external drive (not NAS)"
|
||||||
|
echo " - Install update"
|
||||||
|
echo " - Move files back after snapshot clears"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Option 4: Contact Apple Support:"
|
||||||
|
echo " They may have tools to force-clear the snapshot"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Current Status ==="
|
||||||
|
echo ""
|
||||||
|
echo "Files moved to NAS: ✅ (they're safe)"
|
||||||
|
echo "Space freed on Mac: ❌ (snapshot preserving them)"
|
||||||
|
echo "System Data: 📈 (growing because of snapshot)"
|
||||||
|
echo ""
|
||||||
|
echo "The files ARE moved, but the space won't be freed"
|
||||||
|
echo "until the snapshot is cleared by updating macOS."
|
||||||
|
echo ""
|
||||||
Executable
+93
@@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Final Explanation - Why Nothing Works
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== FINAL EXPLANATION ==="
|
||||||
|
echo ""
|
||||||
|
echo "You've tried everything:"
|
||||||
|
echo " ✅ Moved files to NAS"
|
||||||
|
echo " ✅ Moved files to external drive"
|
||||||
|
echo " ✅ Cleaned caches"
|
||||||
|
echo " ❌ Still no space freed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "❌ WHY NOTHING WORKS:"
|
||||||
|
echo ""
|
||||||
|
echo "The OS update snapshot preserves EVERYTHING:"
|
||||||
|
echo " - Deleted files → Preserved in snapshot"
|
||||||
|
echo " - Moved files → Preserved in snapshot"
|
||||||
|
echo " - Files on NAS → Still preserved in snapshot"
|
||||||
|
echo " - Files on external drive → Still preserved in snapshot"
|
||||||
|
echo ""
|
||||||
|
echo "The snapshot doesn't care WHERE files went."
|
||||||
|
echo "It preserves them regardless of destination."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📸 The Snapshot:"
|
||||||
|
SNAPSHOT=$(diskutil apfs listSnapshots / 2>/dev/null | grep "Name:" | head -1)
|
||||||
|
if [ -n "$SNAPSHOT" ]; then
|
||||||
|
echo "$SNAPSHOT" | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
echo " - NOT purgeable"
|
||||||
|
echo " - Preserves ALL file operations"
|
||||||
|
echo " - Can't be deleted"
|
||||||
|
echo " - Only clears when macOS updates"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔒 THE CATCH-22:"
|
||||||
|
echo ""
|
||||||
|
echo " Need: 17.64GB to install macOS update"
|
||||||
|
echo " Problem: Can't free space (snapshot preserves everything)"
|
||||||
|
echo " Result: Stuck"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "✅ YOUR ONLY OPTIONS:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Contact Apple Support** (RECOMMENDED)"
|
||||||
|
echo " Phone: 1-800-275-2273"
|
||||||
|
echo " Explain: 'OS update snapshot preventing space recovery'"
|
||||||
|
echo " They have system-level tools we don't have access to"
|
||||||
|
echo ""
|
||||||
|
echo "2. **Try GUI Update** (Sometimes works differently)"
|
||||||
|
echo " System Settings → General → Software Update"
|
||||||
|
echo " Click 'Update Now'"
|
||||||
|
echo " GUI sometimes bypasses space checks"
|
||||||
|
echo ""
|
||||||
|
echo "3. **Boot from Recovery** (Advanced)"
|
||||||
|
echo " - Restart holding Command+R"
|
||||||
|
echo " - Try updating from Recovery Mode"
|
||||||
|
echo " - May have different space requirements"
|
||||||
|
echo ""
|
||||||
|
echo "4. **Wait for Automatic Cleanup** (Unreliable)"
|
||||||
|
echo " macOS may eventually clear old snapshots"
|
||||||
|
echo " But this can take weeks/months"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📊 Current Situation:"
|
||||||
|
echo ""
|
||||||
|
echo " Files moved: ✅ (Safe on NAS/external drive)"
|
||||||
|
echo " Space freed: ❌ (Snapshot preserving them)"
|
||||||
|
echo " System Data: 📈 (351GB+ and growing)"
|
||||||
|
echo " Free space: ${FREE_SPACE_GB}GB (not enough)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "⚠️ IMPORTANT:"
|
||||||
|
echo ""
|
||||||
|
echo "Your files ARE safe. The space WILL be freed after updating."
|
||||||
|
echo "But you're in a system-level catch-22 that requires"
|
||||||
|
echo "Apple Support intervention or advanced recovery methods."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🎯 NEXT STEP:"
|
||||||
|
echo ""
|
||||||
|
echo "Call Apple Support: 1-800-275-2273"
|
||||||
|
echo "They can help with this specific issue."
|
||||||
|
echo ""
|
||||||
Executable
+94
@@ -0,0 +1,94 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Final Solution Summary - Why Moving Files Doesn't Free Space
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== FINAL SOLUTION SUMMARY ==="
|
||||||
|
echo ""
|
||||||
|
echo "You've moved files (Music, Documents, etc.) to NAS,"
|
||||||
|
echo "but space isn't being freed. Here's why and what to do:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "❌ THE PROBLEM:"
|
||||||
|
echo ""
|
||||||
|
echo "The OS update snapshot is preserving ALL moved/deleted files."
|
||||||
|
echo ""
|
||||||
|
echo "What happens:"
|
||||||
|
echo " 1. You move Music folder → Files go to NAS ✅"
|
||||||
|
echo " 2. Snapshot preserves them → System Data grows 📈"
|
||||||
|
echo " 3. Space NOT freed → Still full ❌"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📸 The Snapshot:"
|
||||||
|
SNAPSHOT=$(diskutil apfs listSnapshots / 2>/dev/null | grep "Name:" | head -1)
|
||||||
|
if [ -n "$SNAPSHOT" ]; then
|
||||||
|
echo "$SNAPSHOT" | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
echo " - NOT purgeable"
|
||||||
|
echo " - Preserves all deleted/moved files"
|
||||||
|
echo " - Can't be deleted manually"
|
||||||
|
echo " - Only clears when you update macOS"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "✅ THE ONLY SOLUTION:"
|
||||||
|
echo ""
|
||||||
|
echo "You MUST install the macOS update to clear the snapshot."
|
||||||
|
echo ""
|
||||||
|
echo "But you need 17.64GB to install, and you can't free space"
|
||||||
|
echo "because the snapshot preserves everything you delete/move."
|
||||||
|
echo ""
|
||||||
|
echo "This is a SYSTEM-LEVEL CATCH-22."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 WORKAROUNDS:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Try downloading update anyway** (may work with less space):"
|
||||||
|
echo " sudo softwareupdate --download --all"
|
||||||
|
echo ""
|
||||||
|
echo "2. **Use external drive** (if available):"
|
||||||
|
echo " - Connect external drive"
|
||||||
|
echo " - Move large files there (not NAS)"
|
||||||
|
echo " - Install update"
|
||||||
|
echo " - Move files back after snapshot clears"
|
||||||
|
echo ""
|
||||||
|
echo "3. **Contact Apple Support**:"
|
||||||
|
echo " - They may have tools to force-clear snapshot"
|
||||||
|
echo " - Or can help with update process"
|
||||||
|
echo " - Phone: 1-800-275-2273"
|
||||||
|
echo ""
|
||||||
|
echo "4. **Try restarting, then immediately download update**:"
|
||||||
|
echo " - Restart Mac"
|
||||||
|
echo " - Immediately run: sudo softwareupdate --download --all"
|
||||||
|
echo " - Sometimes releases temporary space"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📊 Current Status:"
|
||||||
|
echo ""
|
||||||
|
echo " Files moved to NAS: ✅ (they're safe)"
|
||||||
|
echo " Space freed on Mac: ❌ (snapshot preserving them)"
|
||||||
|
echo " System Data: 📈 (351GB+ and growing)"
|
||||||
|
echo " Free space: ${FREE_SPACE_GB}GB (not enough for update)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "⚠️ IMPORTANT:"
|
||||||
|
echo ""
|
||||||
|
echo " - Your files ARE safely on NAS"
|
||||||
|
echo " - The space WILL be freed after updating macOS"
|
||||||
|
echo " - But you need space to update (catch-22)"
|
||||||
|
echo " - This requires external storage or Apple Support"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🎯 RECOMMENDED ACTION:"
|
||||||
|
echo ""
|
||||||
|
echo " 1. Try: sudo softwareupdate --download --all"
|
||||||
|
echo " (May work even with current space)"
|
||||||
|
echo ""
|
||||||
|
echo " 2. If that fails, use external drive or contact Apple Support"
|
||||||
|
echo ""
|
||||||
Executable
+108
@@ -0,0 +1,108 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Find ANY Freeable Space - Check everything
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Find Any Freeable Space ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 Checking all possible sources of space:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
TOTAL_POTENTIAL=0
|
||||||
|
|
||||||
|
# 1. Caches
|
||||||
|
echo "1. Caches:"
|
||||||
|
CACHE_SIZE=$(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " Library/Caches: $CACHE_SIZE"
|
||||||
|
if [ "$CACHE_SIZE" != "0" ] && [ -n "$CACHE_SIZE" ]; then
|
||||||
|
CACHE_GB=$(echo "$CACHE_SIZE" | sed 's/G//' | awk '{if ($1 ~ /[0-9]/) print $1; else print "0"}')
|
||||||
|
TOTAL_POTENTIAL=$(echo "$TOTAL_POTENTIAL + $CACHE_GB" | bc 2>/dev/null || echo "$TOTAL_POTENTIAL")
|
||||||
|
fi
|
||||||
|
|
||||||
|
USER_CACHE=$(du -sh ~/.cache 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " .cache: $USER_CACHE"
|
||||||
|
|
||||||
|
NPM_CACHE=$(du -sh ~/.npm 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " .npm: $NPM_CACHE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. Downloads
|
||||||
|
DOWNLOADS=$(du -sh ~/Downloads 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo "2. Downloads: $DOWNLOADS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. Trash
|
||||||
|
TRASH=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo "3. Trash: $TRASH"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 4. Virtual memory
|
||||||
|
VM_SIZE=$(sudo du -sh /private/var/vm 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo "4. Virtual Memory (swap): $VM_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 5. System temp
|
||||||
|
TEMP_SIZE=$(sudo du -sh /private/var/folders 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo "5. System Temp: $TEMP_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 6. Large directories
|
||||||
|
echo "6. Large Directories:"
|
||||||
|
OLLAMA=$(du -sh ~/.ollama 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " .ollama: $OLLAMA"
|
||||||
|
|
||||||
|
LOCAL=$(du -sh ~/.local 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " .local: $LOCAL"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 7. Documents remaining
|
||||||
|
DOCS=$(du -sh ~/Documents 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo "7. Documents remaining: $DOCS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Analysis ==="
|
||||||
|
echo ""
|
||||||
|
echo "The problem: Even if we free space, the OS snapshot will preserve"
|
||||||
|
echo "deleted files, making System Data grow instead."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Desperate Measures ==="
|
||||||
|
echo ""
|
||||||
|
echo "Since normal methods don't work, try:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Restart your Mac**"
|
||||||
|
echo " Sometimes releases some purgeable space temporarily"
|
||||||
|
echo ""
|
||||||
|
echo "2. **Try downloading update with current space**"
|
||||||
|
echo " sudo softwareupdate --download --all"
|
||||||
|
echo " (May work even with less than 17.64GB)"
|
||||||
|
echo ""
|
||||||
|
echo "3. **Check if update can install incrementally**"
|
||||||
|
echo " System Settings → General → Software Update"
|
||||||
|
echo " Click 'More Info' to see if it can download in parts"
|
||||||
|
echo ""
|
||||||
|
echo "4. **Use external drive** (if available)"
|
||||||
|
echo " - Connect external drive"
|
||||||
|
echo " - Move large files there (not NAS)"
|
||||||
|
echo " - Install update"
|
||||||
|
echo " - Move files back"
|
||||||
|
echo ""
|
||||||
|
echo "5. **Contact Apple Support**"
|
||||||
|
echo " They may have tools to force-clear the snapshot"
|
||||||
|
echo " Or can help with the update process"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== The Real Issue ==="
|
||||||
|
echo ""
|
||||||
|
echo "The OS update snapshot is blocking everything."
|
||||||
|
echo "You need to update macOS, but need space to update."
|
||||||
|
echo "This is a system-level catch-22 that may require"
|
||||||
|
echo "Apple Support intervention or external storage."
|
||||||
|
echo ""
|
||||||
Executable
+79
@@ -0,0 +1,79 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Find Large Files - Help locate where space is actually being used
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Find Large Files ==="
|
||||||
|
echo ""
|
||||||
|
echo "Your container is 99.8% full (493.5GB used, 847MB free)"
|
||||||
|
echo "Let's find where the space is actually being used..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📊 Top Space Users:"
|
||||||
|
echo ""
|
||||||
|
echo "Home directory breakdown:"
|
||||||
|
du -h -d 1 ~ 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 Large Files (>1GB) in Home:"
|
||||||
|
echo " Searching... (this may take a moment)"
|
||||||
|
find ~ -size +1G -type f 2>/dev/null | head -10 | while read file; do
|
||||||
|
SIZE=$(du -h "$file" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " $SIZE $file"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📁 Large Directories in Documents (40GB):"
|
||||||
|
du -h -d 1 ~/Documents 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📚 Large Directories in Library (33GB):"
|
||||||
|
du -h -d 1 ~/Library 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "💾 Other Large Locations:"
|
||||||
|
echo " .local: $(du -sh ~/.local 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo " .ollama: $(du -sh ~/.ollama 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo " Downloads: $(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Questions ==="
|
||||||
|
echo ""
|
||||||
|
echo "1. Where exactly did you delete the 20GB from?"
|
||||||
|
echo " - Was it from ~/Movies? (currently 6.7GB)"
|
||||||
|
echo " - Or another location?"
|
||||||
|
echo ""
|
||||||
|
echo "2. Did you verify the files were actually deleted?"
|
||||||
|
echo " - Check the original location"
|
||||||
|
echo " - Check Trash (currently empty)"
|
||||||
|
echo ""
|
||||||
|
echo "3. The container shows 493.5GB used:"
|
||||||
|
echo " - Data volume: 471.8GB"
|
||||||
|
echo " - System volume: 12.2GB"
|
||||||
|
echo " - Preboot: 8.1GB"
|
||||||
|
echo " - Recovery: 1.2GB"
|
||||||
|
echo ""
|
||||||
|
echo " Your home directory is 130GB, but the Data volume is 471.8GB"
|
||||||
|
echo " This means there are other users or system files using space."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Recommendations ==="
|
||||||
|
echo ""
|
||||||
|
echo "To free space immediately:"
|
||||||
|
echo ""
|
||||||
|
echo "1. Clean Downloads: $(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')"
|
||||||
|
echo " rm -rf ~/Downloads/*"
|
||||||
|
echo ""
|
||||||
|
echo "2. Clean Library Caches:"
|
||||||
|
echo " rm -rf ~/Library/Caches/*"
|
||||||
|
echo ""
|
||||||
|
echo "3. Review Documents folder (40GB):"
|
||||||
|
echo " Move large files to NAS"
|
||||||
|
echo ""
|
||||||
|
echo "4. Review .ollama folder (17GB):"
|
||||||
|
echo " Remove unused AI models"
|
||||||
|
echo ""
|
||||||
|
echo "5. Use macOS Storage Management:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Manage"
|
||||||
|
echo ""
|
||||||
Executable
+110
@@ -0,0 +1,110 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Find Real 351GB Usage in System Data
|
||||||
|
# Since purgeable space test failed, the space is actually being used
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Find Real 351GB Usage in System Data ==="
|
||||||
|
echo ""
|
||||||
|
echo "The 50GB file creation FAILED, which means:"
|
||||||
|
echo " - The 351GB is NOT purgeable"
|
||||||
|
echo " - It's actually being used"
|
||||||
|
echo " - We need to find what's using it"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📊 Container Analysis:"
|
||||||
|
CONTAINER_TOTAL=$(diskutil info / | grep 'Container Total' | awk '{print $4, $5}')
|
||||||
|
CONTAINER_FREE=$(diskutil info / | grep 'Container Free' | awk '{print $4, $5}')
|
||||||
|
CONTAINER_USED=$(diskutil apfs list 2>/dev/null | grep "Capacity In Use" | awk '{print $6, $7}')
|
||||||
|
|
||||||
|
echo " Container Total: $CONTAINER_TOTAL"
|
||||||
|
echo " Container Free: $CONTAINER_FREE"
|
||||||
|
echo " Container Used: $CONTAINER_USED"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📦 APFS Volume Breakdown:"
|
||||||
|
diskutil apfs list 2>/dev/null | grep -E "Volume|Capacity Consumed" | while read line; do
|
||||||
|
if echo "$line" | grep -q "Volume"; then
|
||||||
|
VOL_NAME=$(echo "$line" | sed 's/.*Name: *\([^(]*\).*/\1/')
|
||||||
|
echo " Volume: $VOL_NAME"
|
||||||
|
elif echo "$line" | grep -q "Capacity Consumed"; then
|
||||||
|
SIZE=$(echo "$line" | awk '{print $3, $4}')
|
||||||
|
echo " Size: $SIZE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📸 APFS Snapshots:"
|
||||||
|
APFS_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null)
|
||||||
|
if [ -n "$APFS_SNAPS" ]; then
|
||||||
|
echo "$APFS_SNAPS" | head -20 | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
echo " ⚠️ The OS update snapshot may be holding space"
|
||||||
|
echo " This snapshot is NOT purgeable and can't be deleted"
|
||||||
|
else
|
||||||
|
echo " No snapshots found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 Large System Directories:"
|
||||||
|
echo " /System:"
|
||||||
|
sudo du -h -d 2 /System/Volumes/Data/System 2>/dev/null | sort -hr | head -5 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
echo ""
|
||||||
|
echo " /Library:"
|
||||||
|
sudo du -h -d 2 /System/Volumes/Data/Library 2>/dev/null | sort -hr | head -5 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 Searching for large files (>10GB)..."
|
||||||
|
echo " (This may take a moment)"
|
||||||
|
LARGE_FILES=$(sudo find /System/Volumes/Data -type f -size +10G 2>/dev/null | head -5)
|
||||||
|
if [ -n "$LARGE_FILES" ]; then
|
||||||
|
echo "$LARGE_FILES" | while read file; do
|
||||||
|
SIZE=$(sudo du -h "$file" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " $SIZE $file"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " No files >10GB found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Analysis ==="
|
||||||
|
echo ""
|
||||||
|
echo "The 351GB in System Data is likely:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **APFS Snapshot Overhead** (Most Likely)"
|
||||||
|
echo " - The OS update snapshot (12.2GB visible)"
|
||||||
|
echo " - May be holding 300+ GB of deleted file space"
|
||||||
|
echo " - APFS snapshots preserve deleted files"
|
||||||
|
echo " - This space is NOT purgeable until snapshot is deleted"
|
||||||
|
echo ""
|
||||||
|
echo "2. **Time Machine Local Snapshots**"
|
||||||
|
echo " - The stuck snapshot entry"
|
||||||
|
echo " - May be holding space even though it's a 'ghost'"
|
||||||
|
echo ""
|
||||||
|
echo "3. **System Reserved Space**"
|
||||||
|
echo " - macOS reserves space for operations"
|
||||||
|
echo " - Shown in System Data but not easily identifiable"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Solution ==="
|
||||||
|
echo ""
|
||||||
|
echo "The OS update snapshot CANNOT be deleted (it's required)."
|
||||||
|
echo "However, you can try:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Update macOS** (if available):"
|
||||||
|
echo " System Settings → General → Software Update"
|
||||||
|
echo " Installing updates may clear old snapshots"
|
||||||
|
echo ""
|
||||||
|
echo "2. **Check for macOS Install Data** (11GB found):"
|
||||||
|
echo " sudo rm -rf /System/Volumes/Data/macOS\ Install\ Data"
|
||||||
|
echo " (Safe to delete after installation completes)"
|
||||||
|
echo ""
|
||||||
|
echo "3. **The space may be in APFS snapshot overhead**:"
|
||||||
|
echo " This is space held by the OS update snapshot"
|
||||||
|
echo " It will be released when you update macOS"
|
||||||
|
echo ""
|
||||||
|
echo "4. **Check Storage Management for details**:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage"
|
||||||
|
echo " Hover over 'System Data' for more details"
|
||||||
|
echo ""
|
||||||
Executable
+78
@@ -0,0 +1,78 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Find Real Space Usage
|
||||||
|
# The snapshot is a ghost - find what's actually using space
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Find Real Space Usage ==="
|
||||||
|
echo ""
|
||||||
|
echo "Your container is 99.8% full (493.4GB used, 995MB free)"
|
||||||
|
echo "The snapshot is a ghost entry (0GB)."
|
||||||
|
echo "Let's find what's ACTUALLY using the space..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📊 Container Breakdown:"
|
||||||
|
echo " Container Total: 494.4GB"
|
||||||
|
echo " Container Used: 493.4GB (99.8%)"
|
||||||
|
echo " Container Free: 995MB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 Large Directories in /System/Volumes/Data:"
|
||||||
|
sudo du -h -d 1 /System/Volumes/Data 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check the suspicious Volumes directory
|
||||||
|
VOLUMES_SIZE=$(sudo du -sh /System/Volumes/Data/Volumes 2>/dev/null | awk '{print $1}')
|
||||||
|
echo "⚠️ CRITICAL FINDING:"
|
||||||
|
echo " /System/Volumes/Data/Volumes: $VOLUMES_SIZE"
|
||||||
|
echo ""
|
||||||
|
echo " This directory is HUGE and likely contains:"
|
||||||
|
echo " - Old Time Machine backup volumes"
|
||||||
|
echo " - Mounted disk images"
|
||||||
|
echo " - Stale mount points"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 Checking what's in /System/Volumes/Data/Volumes:"
|
||||||
|
ls -la /System/Volumes/Data/Volumes/ 2>/dev/null | head -20 | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for old backup volumes
|
||||||
|
echo "📦 Checking for old Time Machine backup volumes:"
|
||||||
|
BACKUP_VOLS=$(ls -d "/System/Volumes/Data/Volumes/Backups of"* 2>/dev/null || echo "")
|
||||||
|
if [ -n "$BACKUP_VOLS" ]; then
|
||||||
|
echo " Found old backup volumes:"
|
||||||
|
echo "$BACKUP_VOLS" | while read vol; do
|
||||||
|
SIZE=$(sudo du -sh "$vol" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " - $vol ($SIZE)"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
echo " ⚠️ These are likely old Time Machine backups taking up space!"
|
||||||
|
else
|
||||||
|
echo " No obvious backup volumes found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check home directory
|
||||||
|
echo "📁 Your Home Directory:"
|
||||||
|
du -h -d 1 ~ 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
echo "=== Summary ==="
|
||||||
|
echo ""
|
||||||
|
echo "The snapshot is NOT the problem (it's a ghost, 0GB)."
|
||||||
|
echo ""
|
||||||
|
echo "The REAL problem:"
|
||||||
|
echo " - Container is 99.8% full"
|
||||||
|
echo " - /System/Volumes/Data/Volumes is $VOLUMES_SIZE (likely old backups)"
|
||||||
|
echo " - Your home: 130GB"
|
||||||
|
echo ""
|
||||||
|
echo "To free space, you need to:"
|
||||||
|
echo " 1. Check what's in /System/Volumes/Data/Volumes"
|
||||||
|
echo " 2. Remove old backup volumes if found"
|
||||||
|
echo " 3. Clean up your home directory:"
|
||||||
|
echo " - Downloads: 8.7GB"
|
||||||
|
echo " - Documents: 40GB"
|
||||||
|
echo " - Library: 33GB"
|
||||||
|
echo ""
|
||||||
Executable
+129
@@ -0,0 +1,129 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Find What's in System Data (351GB)
|
||||||
|
# System Data includes snapshots, caches, logs, VM files, etc.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Find System Data Usage (351GB) ==="
|
||||||
|
echo ""
|
||||||
|
echo "System Data on macOS includes:"
|
||||||
|
echo " - APFS snapshots"
|
||||||
|
echo " - Time Machine local snapshots"
|
||||||
|
echo " - Virtual memory swap files"
|
||||||
|
echo " - System caches"
|
||||||
|
echo " - Log files"
|
||||||
|
echo " - Purgeable space"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
TOTAL_FOUND=0
|
||||||
|
|
||||||
|
echo "🔍 Checking System Data Components:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. Check APFS snapshots
|
||||||
|
echo "1. APFS Snapshots:"
|
||||||
|
APFS_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -c "Name:" || echo "0")
|
||||||
|
echo " Found: $APFS_SNAPS snapshot(s)"
|
||||||
|
if [ "$APFS_SNAPS" -gt 0 ]; then
|
||||||
|
diskutil apfs listSnapshots / 2>/dev/null | grep -E "Name|Purgeable" | head -4 | sed 's/^/ /'
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. Check Time Machine local snapshots
|
||||||
|
echo "2. Time Machine Local Snapshots:"
|
||||||
|
TM_SNAPS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
||||||
|
echo " Found: $TM_SNAPS snapshot(s)"
|
||||||
|
if [ "$TM_SNAPS" -gt 0 ]; then
|
||||||
|
tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | sed 's/^/ - /'
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. Check virtual memory (swap files)
|
||||||
|
echo "3. Virtual Memory (Swap Files):"
|
||||||
|
VM_SIZE=$(sudo du -sh /private/var/vm 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " /private/var/vm: $VM_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 4. Check system caches
|
||||||
|
echo "4. System Caches:"
|
||||||
|
CACHE_SIZE=$(sudo du -sh /private/var/folders 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " /private/var/folders: $CACHE_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 5. Check logs
|
||||||
|
echo "5. System Logs:"
|
||||||
|
LOG_SIZE=$(sudo du -sh /Library/Logs /private/var/log 2>/dev/null 2>/dev/null | awk '{sum+=$1} END {print sum}' || echo "0")
|
||||||
|
echo " Logs: ~$LOG_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 6. Check MobileBackups
|
||||||
|
echo "6. MobileBackups (APFS Local Snapshots):"
|
||||||
|
MB_SIZE=$(sudo du -sh /System/Volumes/Data/.MobileBackups /.MobileBackups 2>/dev/null | awk '{sum+=$1} END {print sum}' || echo "0")
|
||||||
|
if [ "$MB_SIZE" != "0" ] && [ -n "$MB_SIZE" ]; then
|
||||||
|
echo " MobileBackups: $MB_SIZE"
|
||||||
|
else
|
||||||
|
echo " MobileBackups: Not found or empty"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 7. Check /private/var
|
||||||
|
echo "7. /private/var (System Data):"
|
||||||
|
PVAR_SIZE=$(sudo du -sh /System/Volumes/Data/private/var 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " /private/var: $PVAR_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 8. Check for sparse bundles
|
||||||
|
echo "8. Sparse Bundles (Disk Images):"
|
||||||
|
SPARSE_COUNT=$(sudo find /System/Volumes/Data -maxdepth 3 -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | wc -l | tr -d ' ')
|
||||||
|
echo " Found: $SPARSE_COUNT sparse bundle(s)"
|
||||||
|
if [ "$SPARSE_COUNT" -gt 0 ]; then
|
||||||
|
sudo find /System/Volumes/Data -maxdepth 3 -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | head -5 | while read bundle; do
|
||||||
|
SIZE=$(sudo du -sh "$bundle" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " - $bundle ($SIZE)"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 9. Check Library
|
||||||
|
echo "9. System Library:"
|
||||||
|
LIB_SIZE=$(sudo du -sh /System/Volumes/Data/Library 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " /Library: $LIB_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Summary ==="
|
||||||
|
echo ""
|
||||||
|
echo "System Data is 351GB. The components above may not add up to 351GB"
|
||||||
|
echo "because System Data also includes:"
|
||||||
|
echo " - Purgeable space (not shown in du)"
|
||||||
|
echo " - APFS snapshot overhead"
|
||||||
|
echo " - Reserved space"
|
||||||
|
echo " - Other system files"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 To Reduce System Data:"
|
||||||
|
echo ""
|
||||||
|
echo "1. Delete Time Machine local snapshots:"
|
||||||
|
if [ "$TM_SNAPS" -gt 0 ]; then
|
||||||
|
echo " sudo tmutil deletelocalsnapshots <date>"
|
||||||
|
else
|
||||||
|
echo " (No snapshots found)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "2. Thin local snapshots:"
|
||||||
|
echo " sudo tmutil thinlocalsnapshots / 1000000000 1"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "3. Remove Time Machine destination (prevents new snapshots):"
|
||||||
|
echo " System Settings → Time Machine → Remove backup disk"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "4. Clean system caches:"
|
||||||
|
echo " sudo rm -rf /private/var/folders/*"
|
||||||
|
echo " (⚠️ Be careful - this may affect running apps)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "5. Restart your Mac:"
|
||||||
|
echo " This often releases purgeable space and snapshots"
|
||||||
|
echo ""
|
||||||
Executable
+146
@@ -0,0 +1,146 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Find Time Machine System Files
|
||||||
|
# This script identifies Time Machine files in system locations that may be taking up 100GB+
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Time Machine System Files Finder ==="
|
||||||
|
echo ""
|
||||||
|
echo "Searching for Time Machine files in system locations..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
TOTAL_SIZE=0
|
||||||
|
|
||||||
|
# Function to check and report size
|
||||||
|
check_location() {
|
||||||
|
local path=$1
|
||||||
|
local description=$2
|
||||||
|
|
||||||
|
if [ -e "$path" ]; then
|
||||||
|
SIZE=$(sudo du -sh "$path" 2>/dev/null | awk '{print $1}')
|
||||||
|
SIZE_BYTES=$(sudo du -sb "$path" 2>/dev/null | awk '{print $1}')
|
||||||
|
if [ -n "$SIZE_BYTES" ] && [ "$SIZE_BYTES" -gt 0 ]; then
|
||||||
|
echo " ✓ $description: $SIZE"
|
||||||
|
echo " Path: $path"
|
||||||
|
TOTAL_SIZE=$((TOTAL_SIZE + SIZE_BYTES))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "🔍 Checking Time Machine locations:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. Local snapshots
|
||||||
|
echo "1. Local Snapshots:"
|
||||||
|
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
||||||
|
if [ "$SNAPSHOTS" -gt 0 ]; then
|
||||||
|
echo " Found $SNAPSHOTS snapshot(s):"
|
||||||
|
tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | while read snapshot; do
|
||||||
|
echo " - $snapshot"
|
||||||
|
# Get snapshot size (requires root)
|
||||||
|
SNAP_SIZE=$(sudo tmutil calculatedrift "$snapshot" 2>/dev/null | grep -i "size" | tail -1 || echo "")
|
||||||
|
if [ -n "$SNAP_SIZE" ]; then
|
||||||
|
echo " $SNAP_SIZE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " No local snapshots found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. MobileBackups (APFS snapshots location)
|
||||||
|
echo "2. MobileBackups (APFS Snapshots):"
|
||||||
|
check_location "/System/Volumes/Data/.MobileBackups" "MobileBackups (newer macOS)"
|
||||||
|
check_location "/.MobileBackups" "MobileBackups (older macOS)"
|
||||||
|
check_location "/private/var/.MobileBackups" "MobileBackups (alternate location)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. Time Machine sparse bundles in system locations
|
||||||
|
echo "3. Time Machine Sparse Bundles:"
|
||||||
|
find /private/var -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | while read bundle; do
|
||||||
|
if [ -e "$bundle" ]; then
|
||||||
|
SIZE=$(sudo du -sh "$bundle" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Found: $bundle ($SIZE)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
find /System/Volumes/Data -maxdepth 3 -name "*.sparsebundle" -o -name "*.sparseimage" 2>/dev/null | while read bundle; do
|
||||||
|
if [ -e "$bundle" ]; then
|
||||||
|
SIZE=$(sudo du -sh "$bundle" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Found: $bundle ($SIZE)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 4. Time Machine preferences and data
|
||||||
|
echo "4. Time Machine System Data:"
|
||||||
|
check_location "/Library/Preferences/com.apple.TimeMachine.plist" "Time Machine preferences"
|
||||||
|
check_location "/private/var/db/timezone" "Timezone data (may contain backups)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 5. Check for old backup files in /private/var
|
||||||
|
echo "5. System Backup Directories:"
|
||||||
|
check_location "/private/var/backups" "System backups"
|
||||||
|
check_location "/private/var/db" "Database files (may contain backup data)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 6. Check for Time Machine logs (usually small but let's check)
|
||||||
|
echo "6. Time Machine Logs:"
|
||||||
|
LOG_SIZE=$(sudo du -sh /private/var/log/com.apple.TimeMachine* 2>/dev/null | awk '{sum+=$1} END {print sum}' || echo "0")
|
||||||
|
if [ "$LOG_SIZE" != "0" ] && [ -n "$LOG_SIZE" ]; then
|
||||||
|
echo " Log files: $LOG_SIZE"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 7. Check System/Volumes/Data for large Time Machine related files
|
||||||
|
echo "7. System Volumes Data:"
|
||||||
|
echo " Checking for large directories in /System/Volumes/Data..."
|
||||||
|
sudo du -h -d 2 /System/Volumes/Data 2>/dev/null | grep -i "timemachine\|backup\|snapshot" | sort -hr | head -10 | while read line; do
|
||||||
|
echo " $line"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 8. Check for old Time Machine destinations
|
||||||
|
echo "8. Time Machine Backup Destinations:"
|
||||||
|
tmutil listbackups 2>/dev/null | head -5
|
||||||
|
BACKUP_COUNT=$(tmutil listbackups 2>/dev/null | wc -l | tr -d ' ')
|
||||||
|
if [ "$BACKUP_COUNT" -gt 0 ]; then
|
||||||
|
echo " Total backups listed: $BACKUP_COUNT"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 9. Check disk space breakdown
|
||||||
|
echo "9. Disk Space Analysis:"
|
||||||
|
echo " Running disk space analysis..."
|
||||||
|
df -h / | tail -1
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 10. Check what macOS Storage Management shows
|
||||||
|
echo "10. System Files Category:"
|
||||||
|
echo " 💡 To see what macOS considers 'System Files':"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Manage"
|
||||||
|
echo " Look under 'System Files' category"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
echo "=== Summary ==="
|
||||||
|
echo ""
|
||||||
|
echo "To find the 100GB+ of Time Machine system files:"
|
||||||
|
echo ""
|
||||||
|
echo "1. Check macOS Storage Management:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Manage → System Files"
|
||||||
|
echo ""
|
||||||
|
echo "2. Check for local snapshots (APFS snapshots):"
|
||||||
|
echo " tmutil listlocalsnapshots /"
|
||||||
|
echo " sudo tmutil listlocalsnapshots /"
|
||||||
|
echo ""
|
||||||
|
echo "3. Check MobileBackups:"
|
||||||
|
echo " sudo du -sh /.MobileBackups"
|
||||||
|
echo " sudo du -sh /System/Volumes/Data/.MobileBackups"
|
||||||
|
echo ""
|
||||||
|
echo "4. Find all sparse bundles:"
|
||||||
|
echo " sudo find / -name '*.sparsebundle' -o -name '*.sparseimage' 2>/dev/null"
|
||||||
|
echo ""
|
||||||
|
echo "5. Check system volumes:"
|
||||||
|
echo " sudo du -h -d 1 /System/Volumes/Data | sort -hr | head -20"
|
||||||
|
echo ""
|
||||||
Executable
+124
@@ -0,0 +1,124 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix: Free Space After Deleting Files
|
||||||
|
# When you delete files but don't see space back, this script fixes it
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Fix: Free Space After Deleting Files ==="
|
||||||
|
echo ""
|
||||||
|
echo "This script handles the common issue where deleted files don't free up space"
|
||||||
|
echo "because APFS snapshots are holding onto them."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check current free space
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for Time Machine local snapshots
|
||||||
|
echo "📸 Checking for Time Machine local snapshots..."
|
||||||
|
TM_SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
if [ -n "$TM_SNAPSHOTS" ]; then
|
||||||
|
echo " Found snapshot(s) that may be holding space:"
|
||||||
|
echo "$TM_SNAPSHOTS" | sed 's/^/ - /'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Delete these snapshots to free space? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "🗑️ Deleting snapshots..."
|
||||||
|
|
||||||
|
# Disable local snapshots first (helps with stuck snapshots)
|
||||||
|
echo " 1. Disabling local snapshots..."
|
||||||
|
sudo tmutil disablelocal 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Delete each snapshot
|
||||||
|
echo " 2. Deleting snapshots..."
|
||||||
|
echo "$TM_SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
# Extract date part from snapshot name
|
||||||
|
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
if [ -n "$SNAP_DATE" ]; then
|
||||||
|
echo " Deleting: $snapshot"
|
||||||
|
sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null && \
|
||||||
|
echo " ✓ Deleted" || \
|
||||||
|
echo " ⚠️ Could not delete (may need restart)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Try to thin all snapshots
|
||||||
|
echo " 3. Thinning all local snapshots..."
|
||||||
|
sudo tmutil thinlocalsnapshots / 1000000000 4 2>/dev/null || true
|
||||||
|
|
||||||
|
# Re-enable local snapshots
|
||||||
|
echo " 4. Re-enabling local snapshots..."
|
||||||
|
sleep 2
|
||||||
|
sudo tmutil enablelocal 2>/dev/null || true
|
||||||
|
|
||||||
|
echo " ✓ Snapshot cleanup completed"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✓ No Time Machine snapshots found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Force purge of memory and disk caches
|
||||||
|
echo "🧹 Purging system caches..."
|
||||||
|
if command -v purge &> /dev/null; then
|
||||||
|
sudo purge
|
||||||
|
echo " ✓ Purge completed"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Purge command not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Wait a moment for system to update
|
||||||
|
echo "⏳ Waiting for system to update disk space..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Check new free space
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No space freed yet"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if (( $(echo "$FREED_GB < 15" | bc -l) )) && (( $(echo "$FREE_SPACE_GB_AFTER < 5" | bc -l) )); then
|
||||||
|
echo "⚠️ If space still not freed, try these steps:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Restart your Mac** - This is often the most effective solution."
|
||||||
|
echo " Snapshots are sometimes only released after a restart."
|
||||||
|
echo ""
|
||||||
|
echo "2. Check if Time Machine is trying to connect:"
|
||||||
|
echo " - Open System Settings → Time Machine"
|
||||||
|
echo " - If it says 'Connecting...', wait for it to finish or disconnect"
|
||||||
|
echo " - Then try deleting snapshots again"
|
||||||
|
echo ""
|
||||||
|
echo "3. Manually delete the snapshot after disabling Time Machine:"
|
||||||
|
echo " sudo tmutil disablelocal"
|
||||||
|
echo " sudo tmutil deletelocalsnapshots <date>"
|
||||||
|
echo " sudo tmutil enablelocal"
|
||||||
|
echo ""
|
||||||
|
echo "4. Use macOS Storage Management:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Manage"
|
||||||
|
echo " This tool can identify and remove large system files"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix Oracle server firewall for WireGuard forwarding
|
||||||
|
echo "Fixing Oracle server firewall rules..."
|
||||||
|
|
||||||
|
ssh server2 "sudo iptables -I FORWARD -i wg0 -j ACCEPT"
|
||||||
|
ssh server2 "sudo iptables -I FORWARD -o wg0 -j ACCEPT"
|
||||||
|
ssh server2 "sudo iptables -I FORWARD -s 10.0.0.0/24 -d 192.168.1.0/24 -j ACCEPT"
|
||||||
|
|
||||||
|
echo "Firewall rules applied successfully!"
|
||||||
|
echo "Test connection: curl -I http://192.168.1.172:5000/"
|
||||||
|
|
||||||
Executable
+100
@@ -0,0 +1,100 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Fix iPhone Mirroring connection issues
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🔧 Fixing iPhone Mirroring issues..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check macOS version
|
||||||
|
echo "📱 Checking macOS version..."
|
||||||
|
MACOS_VERSION=$(sw_vers -productVersion | cut -d. -f1)
|
||||||
|
if [ "$MACOS_VERSION" -lt 15 ]; then
|
||||||
|
echo "❌ Error: iPhone Mirroring requires macOS Sequoia 15.0 or later"
|
||||||
|
echo " Current version: $(sw_vers -productVersion)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "✅ macOS version OK: $(sw_vers -productVersion)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Enable Handoff/Continuity
|
||||||
|
echo "🔄 Enabling Handoff and Continuity features..."
|
||||||
|
defaults write com.apple.coreservices.useractivityd.plist ActivityAdvertisingAllowed -bool true
|
||||||
|
defaults write com.apple.coreservices.useractivityd.plist ActivityReceivingAllowed -bool true
|
||||||
|
echo "✅ Handoff enabled"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Restart Continuity services
|
||||||
|
echo "🔄 Restarting Continuity services..."
|
||||||
|
killall sharingd 2>/dev/null || true
|
||||||
|
killall bluetoothd 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Restart Bluetooth daemon
|
||||||
|
echo "🔄 Restarting Bluetooth..."
|
||||||
|
sudo launchctl stop com.apple.bluetoothd 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
sudo launchctl start com.apple.bluetoothd 2>/dev/null || true
|
||||||
|
echo "✅ Services restarted"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check Bluetooth and Wi-Fi status
|
||||||
|
echo "📡 Checking connectivity..."
|
||||||
|
BLUETOOTH_STATUS=$(system_profiler SPBluetoothDataType 2>/dev/null | grep -i "state" | head -1 | grep -i "on" && echo "On" || echo "Off")
|
||||||
|
WIFI_STATUS=$(networksetup -getairportpower en0 2>/dev/null | grep -i "on" && echo "On" || echo "Off")
|
||||||
|
|
||||||
|
if [ "$BLUETOOTH_STATUS" = "On" ]; then
|
||||||
|
echo "✅ Bluetooth is enabled"
|
||||||
|
else
|
||||||
|
echo "⚠️ Bluetooth is disabled - please enable it in System Settings"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$WIFI_STATUS" = "On" ]; then
|
||||||
|
echo "✅ Wi-Fi is enabled"
|
||||||
|
else
|
||||||
|
echo "⚠️ Wi-Fi is disabled - please enable it in System Settings"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Verify Handoff settings
|
||||||
|
echo "✅ Verifying Handoff settings..."
|
||||||
|
ADVERTISING=$(defaults read com.apple.coreservices.useractivityd.plist ActivityAdvertisingAllowed 2>/dev/null || echo "false")
|
||||||
|
RECEIVING=$(defaults read com.apple.coreservices.useractivityd.plist ActivityReceivingAllowed 2>/dev/null || echo "false")
|
||||||
|
|
||||||
|
if [ "$ADVERTISING" = "1" ] && [ "$RECEIVING" = "1" ]; then
|
||||||
|
echo "✅ Handoff is properly configured"
|
||||||
|
else
|
||||||
|
echo "❌ Handoff configuration incomplete"
|
||||||
|
echo " ActivityAdvertisingAllowed: $ADVERTISING"
|
||||||
|
echo " ActivityReceivingAllowed: $RECEIVING"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo "✅ Fix script completed!"
|
||||||
|
echo ""
|
||||||
|
echo "📋 Next steps:"
|
||||||
|
echo " 1. Make sure your iPhone is:"
|
||||||
|
echo " - Running iOS 18.0 or later"
|
||||||
|
echo " - Unlocked and near this Mac"
|
||||||
|
echo " - Signed in to the SAME iCloud account"
|
||||||
|
echo " - Has Bluetooth and Wi-Fi enabled"
|
||||||
|
echo ""
|
||||||
|
echo " 2. Restart your Mac (recommended):"
|
||||||
|
echo " sudo reboot"
|
||||||
|
echo ""
|
||||||
|
echo " 3. After restart, try iPhone Mirroring again"
|
||||||
|
echo ""
|
||||||
|
echo " 4. If still not working, check:"
|
||||||
|
echo " - System Settings → General → AirDrop & Handoff"
|
||||||
|
echo " → Ensure 'Handoff' is enabled"
|
||||||
|
echo " - System Settings → Privacy & Security → Bluetooth"
|
||||||
|
echo " → Ensure Bluetooth access is granted"
|
||||||
|
echo " - System Settings → Network → Firewall"
|
||||||
|
echo " → Temporarily disable to test"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# Fix Network Security Group (NSG) Rules
|
||||||
|
|
||||||
|
## The Problem
|
||||||
|
Your instance has a **Network Security Group (NSG)** called `ig-quick-action-NSG` that might be blocking traffic even though Security List rules are added.
|
||||||
|
|
||||||
|
Oracle Cloud has **two firewall layers**:
|
||||||
|
1. **Security Lists** (VCN level) - ✅ You added rules here
|
||||||
|
2. **Network Security Groups (NSG)** (Instance level) - ❌ Might be blocking!
|
||||||
|
|
||||||
|
## Solution: Add Rules to NSG
|
||||||
|
|
||||||
|
### Step 1: Go to Network Security Group
|
||||||
|
From your instance details page (where you saw the VNIC info):
|
||||||
|
|
||||||
|
1. Find **"Network security groups"** section
|
||||||
|
2. Click on **"ig-quick-action-NSG"** (the blue link)
|
||||||
|
3. This opens the NSG details page
|
||||||
|
|
||||||
|
### Step 2: Add Ingress Rules
|
||||||
|
1. Click on **"Ingress Rules"** tab
|
||||||
|
2. Click **"Add Ingress Rules"**
|
||||||
|
3. Add the same 4 rules:
|
||||||
|
|
||||||
|
**Rule 1:**
|
||||||
|
- Source Type: CIDR
|
||||||
|
- Source CIDR: `0.0.0.0/0`
|
||||||
|
- IP Protocol: TCP
|
||||||
|
- Destination Port Range: `7890`
|
||||||
|
- Description: `Clash HTTP Proxy`
|
||||||
|
|
||||||
|
**Rule 2:**
|
||||||
|
- Source Type: CIDR
|
||||||
|
- Source CIDR: `0.0.0.0/0`
|
||||||
|
- IP Protocol: TCP
|
||||||
|
- Destination Port Range: `7891`
|
||||||
|
- Description: `Clash SOCKS5`
|
||||||
|
|
||||||
|
**Rule 3:**
|
||||||
|
- Source Type: CIDR
|
||||||
|
- Source CIDR: `0.0.0.0/0`
|
||||||
|
- IP Protocol: TCP
|
||||||
|
- Destination Port Range: `7892`
|
||||||
|
- Description: `Clash Mixed`
|
||||||
|
|
||||||
|
**Rule 4:**
|
||||||
|
- Source Type: CIDR
|
||||||
|
- Source CIDR: `0.0.0.0/0`
|
||||||
|
- IP Protocol: TCP
|
||||||
|
- Destination Port Range: `9090`
|
||||||
|
- Description: `Clash Web UI`
|
||||||
|
|
||||||
|
### Step 3: Save and Test
|
||||||
|
1. Click **"Add Ingress Rules"**
|
||||||
|
2. Wait 30-60 seconds
|
||||||
|
3. Test again: `curl --proxy http://proxy_user:Cs7yBx1Rh9oK@158.101.140.85:7890 http://httpbin.org/ip`
|
||||||
|
|
||||||
|
## Alternative: Remove NSG (If Not Needed)
|
||||||
|
|
||||||
|
If you don't need the NSG:
|
||||||
|
1. Go to instance → Primary VNIC
|
||||||
|
2. Click **"Edit"** next to Network security groups
|
||||||
|
3. Remove `ig-quick-action-NSG`
|
||||||
|
4. Save
|
||||||
|
|
||||||
|
Then Security List rules will be enough.
|
||||||
|
|
||||||
|
## Quick Path
|
||||||
|
```
|
||||||
|
Instance Details → Primary VNIC → Network security groups → ig-quick-action-NSG → Ingress Rules → Add Ingress Rules
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
# Fix Oracle Cloud Firewall for Proxy
|
||||||
|
|
||||||
|
## The Problem
|
||||||
|
Connection times out because **Oracle Cloud Security List** is blocking the ports, even though UFW allows them.
|
||||||
|
|
||||||
|
## Solution: Add Security List Rules in Oracle Cloud
|
||||||
|
|
||||||
|
### Method 1: Via Web Console (Easiest)
|
||||||
|
|
||||||
|
1. **Log into Oracle Cloud Console**
|
||||||
|
- Go to: https://cloud.oracle.com
|
||||||
|
- Navigate to your instance
|
||||||
|
|
||||||
|
2. **Find Your VCN/Subnet:**
|
||||||
|
- Go to **Networking** → **Virtual Cloud Networks**
|
||||||
|
- Click on your VCN
|
||||||
|
- Click on your **Subnet**
|
||||||
|
|
||||||
|
3. **Edit Security List:**
|
||||||
|
- Click on **Security Lists** tab
|
||||||
|
- Click on the default security list (or the one attached to your subnet)
|
||||||
|
- Click **Edit All Rules**
|
||||||
|
|
||||||
|
4. **Add Ingress Rules:**
|
||||||
|
Click **Add Ingress Rules** for each port:
|
||||||
|
|
||||||
|
**Rule 1: HTTP Proxy (7890)**
|
||||||
|
- **Source Type:** CIDR
|
||||||
|
- **Source CIDR:** `0.0.0.0/0` (or your IP for security)
|
||||||
|
- **IP Protocol:** TCP
|
||||||
|
- **Destination Port Range:** `7890`
|
||||||
|
- **Description:** Clash HTTP Proxy
|
||||||
|
|
||||||
|
**Rule 2: SOCKS5 Proxy (7891)**
|
||||||
|
- **Source Type:** CIDR
|
||||||
|
- **Source CIDR:** `0.0.0.0/0`
|
||||||
|
- **IP Protocol:** TCP
|
||||||
|
- **Destination Port Range:** `7891`
|
||||||
|
- **Description:** Clash SOCKS5 Proxy
|
||||||
|
|
||||||
|
**Rule 3: Mixed Proxy (7892)**
|
||||||
|
- **Source Type:** CIDR
|
||||||
|
- **Source CIDR:** `0.0.0.0/0`
|
||||||
|
- **IP Protocol:** TCP
|
||||||
|
- **Destination Port Range:** `7892`
|
||||||
|
- **Description:** Clash Mixed Proxy
|
||||||
|
|
||||||
|
**Rule 4: Web UI (9090)**
|
||||||
|
- **Source Type:** CIDR
|
||||||
|
- **Source CIDR:** `0.0.0.0/0`
|
||||||
|
- **IP Protocol:** TCP
|
||||||
|
- **Destination Port Range:** `9090`
|
||||||
|
- **Description:** Clash Web UI
|
||||||
|
|
||||||
|
5. **Save** the rules
|
||||||
|
|
||||||
|
6. **Wait 30 seconds** for rules to propagate
|
||||||
|
|
||||||
|
7. **Test again** from your iPhone
|
||||||
|
|
||||||
|
### Method 2: Via OCI CLI
|
||||||
|
|
||||||
|
If you have OCI CLI installed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get your security list OCID
|
||||||
|
oci network security-list list --compartment-id <your-compartment-id>
|
||||||
|
|
||||||
|
# Add ingress rule
|
||||||
|
oci network security-list update \
|
||||||
|
--security-list-id <your-security-list-id> \
|
||||||
|
--ingress-security-rules file://ingress-rules.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Security Note
|
||||||
|
|
||||||
|
Using `0.0.0.0/0` allows access from anywhere. For better security:
|
||||||
|
- Use your home IP: `YOUR_IP/32`
|
||||||
|
- Or use a VPN IP range
|
||||||
|
- The proxy has authentication, so it's somewhat protected
|
||||||
|
|
||||||
|
## Verify Rules Are Applied
|
||||||
|
|
||||||
|
After adding rules, test:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your Mac (not iPhone)
|
||||||
|
nc -zv 158.101.140.85 7890
|
||||||
|
# Should show: Connection succeeded
|
||||||
|
```
|
||||||
|
|
||||||
|
## Alternative: Use Tailscale Instead
|
||||||
|
|
||||||
|
If you don't want to open ports publicly:
|
||||||
|
- Keep proxy on Tailscale IP only (100.70.115.1)
|
||||||
|
- Use Tailscale VPN on iPhone
|
||||||
|
- Access proxy via Tailscale network
|
||||||
|
|
||||||
|
But this requires Tailscale VPN, which conflicts with Shadowrocket VPN.
|
||||||
|
|
||||||
|
## Quick Checklist
|
||||||
|
|
||||||
|
- [ ] Logged into Oracle Cloud Console
|
||||||
|
- [ ] Found VCN and Subnet
|
||||||
|
- [ ] Opened Security List
|
||||||
|
- [ ] Added ingress rules for ports 7890, 7891, 7892, 9090
|
||||||
|
- [ ] Saved rules
|
||||||
|
- [ ] Waited 30 seconds
|
||||||
|
- [ ] Tested from iPhone
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+116
@@ -0,0 +1,116 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix OS Update Snapshot Issue (351GB System Data)
|
||||||
|
# The OS update snapshot is preventing space from being freed
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Fix OS Update Snapshot Issue ==="
|
||||||
|
echo ""
|
||||||
|
echo "Your disk layout shows:"
|
||||||
|
echo " - Container: 494.4 GB"
|
||||||
|
echo " - Data volume: 472.5 GB"
|
||||||
|
echo " - System volume: 12.2 GB"
|
||||||
|
echo " - OS Update Snapshot: 12.2 GB (NOT purgeable)"
|
||||||
|
echo ""
|
||||||
|
echo "The 351GB in System Data is likely snapshot overhead"
|
||||||
|
echo "that can't be freed until the snapshot is cleared."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 Checking for macOS updates..."
|
||||||
|
UPDATES=$(softwareupdate --list 2>/dev/null | grep -i "update" | head -5)
|
||||||
|
if [ -n "$UPDATES" ]; then
|
||||||
|
echo " Found available updates:"
|
||||||
|
echo "$UPDATES" | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
echo " ✅ SOLUTION: Install macOS updates"
|
||||||
|
echo " This will create a new snapshot and clear the old one"
|
||||||
|
echo " System Settings → General → Software Update"
|
||||||
|
else
|
||||||
|
echo " No updates found (or check failed)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Immediate Space Savings:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check macOS Install Data
|
||||||
|
INSTALL_DATA="/System/Volumes/Data/macOS Install Data"
|
||||||
|
if [ -d "$INSTALL_DATA" ]; then
|
||||||
|
SIZE=$(sudo du -sh "$INSTALL_DATA" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " 1. Delete macOS Install Data: $SIZE"
|
||||||
|
echo " sudo rm -rf \"$INSTALL_DATA\""
|
||||||
|
echo " (Safe to delete after installation completes)"
|
||||||
|
echo ""
|
||||||
|
read -p " Delete macOS Install Data now? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo " Deleting..."
|
||||||
|
sudo rm -rf "$INSTALL_DATA" 2>/dev/null && \
|
||||||
|
echo " ✅ Deleted ($SIZE freed)" || \
|
||||||
|
echo " ⚠️ Could not delete (may be in use)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " 1. macOS Install Data: Not found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📊 Understanding the Problem:"
|
||||||
|
echo ""
|
||||||
|
echo "The OS update snapshot (12.2GB visible) is holding much more"
|
||||||
|
echo "space as 'overhead' or 'purgeable' that shows up in System Data."
|
||||||
|
echo ""
|
||||||
|
echo "APFS snapshots work by:"
|
||||||
|
echo " - Preserving deleted files"
|
||||||
|
echo " - Taking up space until cleared"
|
||||||
|
echo " - The OS update snapshot can't be deleted manually"
|
||||||
|
echo ""
|
||||||
|
echo "The 351GB in System Data includes:"
|
||||||
|
echo " - Snapshot overhead (space held by the snapshot)"
|
||||||
|
echo " - Purgeable space (that can't be purged due to snapshot)"
|
||||||
|
echo " - System reserved space"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Solutions ==="
|
||||||
|
echo ""
|
||||||
|
echo "Option 1: Install macOS Updates (Recommended)"
|
||||||
|
echo " - System Settings → General → Software Update"
|
||||||
|
echo " - Install any available updates"
|
||||||
|
echo " - This will clear the old snapshot"
|
||||||
|
echo " - Should free the 351GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Option 2: Wait for Automatic Cleanup"
|
||||||
|
echo " - macOS may clear old snapshots automatically"
|
||||||
|
echo " - But this can take weeks or months"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Option 3: Free Other Space First"
|
||||||
|
echo " - Clean Downloads: 8.7GB"
|
||||||
|
echo " - Clean Caches: ~6GB"
|
||||||
|
echo " - Review Documents: 40GB"
|
||||||
|
echo " - This gives you ~55GB to work with"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Option 4: Check Storage Management Details"
|
||||||
|
echo " - Apple Menu → About This Mac → Storage"
|
||||||
|
echo " - Hover over 'System Data' for breakdown"
|
||||||
|
echo " - May show 'Purgeable' or 'Snapshots'"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check final space
|
||||||
|
sleep 2
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo "✅ Freed: ${FREED_GB}GB"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+68
@@ -0,0 +1,68 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix Photo Volume Taking 175GB
|
||||||
|
# This is likely a mounted volume or disk image
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Fix Photo Volume (175GB) ==="
|
||||||
|
echo ""
|
||||||
|
echo "Found: /System/Volumes/Data/Volumes/photo is 175GB!"
|
||||||
|
echo "This is likely what's consuming your space."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check what it is
|
||||||
|
echo "🔍 Checking what 'photo' is:"
|
||||||
|
if [ -d "/System/Volumes/Data/Volumes/photo" ]; then
|
||||||
|
echo " It's a directory"
|
||||||
|
SIZE=$(sudo du -sh /System/Volumes/Data/Volumes/photo 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Size: $SIZE"
|
||||||
|
|
||||||
|
# Check if it's mounted
|
||||||
|
MOUNTED=$(mount | grep photo || echo "NOT_MOUNTED")
|
||||||
|
if [ "$MOUNTED" != "NOT_MOUNTED" ]; then
|
||||||
|
echo " ⚠️ It's a MOUNTED volume:"
|
||||||
|
echo "$MOUNTED" | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
echo " This is likely a disk image or network mount."
|
||||||
|
echo " You can unmount it to free the space."
|
||||||
|
else
|
||||||
|
echo " It's a regular directory (not mounted)"
|
||||||
|
echo " Contents:"
|
||||||
|
ls -lah /System/Volumes/Data/Volumes/photo 2>/dev/null | head -10 | sed 's/^/ /'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " Not found or not accessible"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if it's safe to remove
|
||||||
|
echo "❓ Questions:"
|
||||||
|
echo " 1. Do you have a 'photo' volume mounted?"
|
||||||
|
echo " 2. Is this from an external drive or disk image?"
|
||||||
|
echo " 3. Do you need this data?"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Solutions:"
|
||||||
|
echo ""
|
||||||
|
echo "If it's a mounted volume you don't need:"
|
||||||
|
echo " sudo umount /System/Volumes/Data/Volumes/photo"
|
||||||
|
echo ""
|
||||||
|
echo "If it's a directory with files you don't need:"
|
||||||
|
echo " sudo rm -rf /System/Volumes/Data/Volumes/photo/*"
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ WARNING: Make sure you don't need this data before deleting!"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Do you want to see what's inside? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "📁 Contents of /System/Volumes/Data/Volumes/photo:"
|
||||||
|
sudo ls -lah /System/Volumes/Data/Volumes/photo 2>/dev/null | head -20 | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
echo "📊 Top subdirectories:"
|
||||||
|
sudo du -h -d 1 /System/Volumes/Data/Volumes/photo 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+113
@@ -0,0 +1,113 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix QuickConnect 502 Error
|
||||||
|
# HTTP ERROR 502 - Bad Gateway
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Fix QuickConnect 502 Error ==="
|
||||||
|
echo ""
|
||||||
|
echo "502 Bad Gateway means QuickConnect relay server"
|
||||||
|
echo "can't reach your NAS or NAS is having issues."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔍 Diagnosing..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check local network connectivity
|
||||||
|
echo "1. Checking local network connection..."
|
||||||
|
if ping -c 2 DS224plus.local &>/dev/null || ping -c 2 192.168.1.172 &>/dev/null; then
|
||||||
|
echo " ✅ NAS is reachable on local network"
|
||||||
|
LOCAL_REACHABLE=true
|
||||||
|
else
|
||||||
|
echo " ❌ NAS not reachable on local network"
|
||||||
|
LOCAL_REACHABLE=false
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check SSH access
|
||||||
|
echo "2. Checking SSH access..."
|
||||||
|
if nas "uptime" &>/dev/null; then
|
||||||
|
echo " ✅ Can connect via SSH"
|
||||||
|
SSH_WORKING=true
|
||||||
|
else
|
||||||
|
echo " ❌ Cannot connect via SSH"
|
||||||
|
SSH_WORKING=false
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check DSM web interface locally
|
||||||
|
echo "3. Checking DSM web interface (local)..."
|
||||||
|
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 http://192.168.1.172:5000 2>/dev/null || echo "000")
|
||||||
|
if [ "$HTTP_STATUS" = "200" ] || [ "$HTTP_STATUS" = "302" ]; then
|
||||||
|
echo " ✅ DSM web interface working locally"
|
||||||
|
WEB_WORKING=true
|
||||||
|
else
|
||||||
|
echo " ❌ DSM web interface not responding (HTTP $HTTP_STATUS)"
|
||||||
|
WEB_WORKING=false
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Solutions ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$LOCAL_REACHABLE" = true ] && [ "$WEB_WORKING" = true ]; then
|
||||||
|
echo "✅ NAS is working locally!"
|
||||||
|
echo ""
|
||||||
|
echo "The 502 error is a QuickConnect issue, not your NAS."
|
||||||
|
echo ""
|
||||||
|
echo "Solution: Use local access instead:"
|
||||||
|
echo ""
|
||||||
|
echo " http://192.168.1.172:5000"
|
||||||
|
echo " or"
|
||||||
|
echo " http://DS224plus.local:5000"
|
||||||
|
echo ""
|
||||||
|
echo "QuickConnect issues are usually:"
|
||||||
|
echo " - QuickConnect relay server problems (temporary)"
|
||||||
|
echo " - QuickConnect service disabled on NAS"
|
||||||
|
echo " - Network/firewall blocking QuickConnect"
|
||||||
|
echo ""
|
||||||
|
elif [ "$LOCAL_REACHABLE" = true ] && [ "$SSH_WORKING" = true ]; then
|
||||||
|
echo "✅ NAS is reachable via SSH"
|
||||||
|
echo ""
|
||||||
|
echo "DSM web interface may be down. Check:"
|
||||||
|
echo ""
|
||||||
|
echo " 1. NAS may be restarting or updating"
|
||||||
|
echo " 2. Web service may be stopped"
|
||||||
|
echo ""
|
||||||
|
echo "Via SSH, check:"
|
||||||
|
echo " nas 'synoservice --status nginx'"
|
||||||
|
echo " nas 'synoservice --status httpd-user'"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo "⚠️ NAS may be down or unreachable"
|
||||||
|
echo ""
|
||||||
|
echo "Check:"
|
||||||
|
echo " 1. Is NAS powered on? (Check power LED)"
|
||||||
|
echo " 2. Is NAS connected to network? (Check network LED)"
|
||||||
|
echo " 3. Try accessing directly: http://192.168.1.172:5000"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== QuickConnect 502 Error Fixes ==="
|
||||||
|
echo ""
|
||||||
|
echo "1. **Use Local Access Instead** (Recommended)"
|
||||||
|
echo " http://192.168.1.172:5000"
|
||||||
|
echo " This bypasses QuickConnect entirely"
|
||||||
|
echo ""
|
||||||
|
echo "2. **Check QuickConnect Settings**"
|
||||||
|
echo " If you can access NAS locally:"
|
||||||
|
echo " - Control Panel → External Access → QuickConnect"
|
||||||
|
echo " - Make sure QuickConnect is enabled"
|
||||||
|
echo " - Try disabling and re-enabling"
|
||||||
|
echo ""
|
||||||
|
echo "3. **Wait and Retry**"
|
||||||
|
echo " QuickConnect 502 errors are often temporary"
|
||||||
|
echo " Wait 5-10 minutes and try again"
|
||||||
|
echo ""
|
||||||
|
echo "4. **Check NAS Status**"
|
||||||
|
echo " - Is NAS powered on?"
|
||||||
|
echo " - Are status LEDs normal?"
|
||||||
|
echo " - Try restarting NAS if needed"
|
||||||
|
echo ""
|
||||||
Executable
+126
@@ -0,0 +1,126 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix Stuck Time Machine Backup
|
||||||
|
# When Time Machine is stuck trying to connect to NAS and consuming space
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Fix Stuck Time Machine Backup ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check Time Machine status
|
||||||
|
TM_STATUS=$(tmutil status 2>/dev/null)
|
||||||
|
echo "📊 Current Time Machine Status:"
|
||||||
|
echo "$TM_STATUS" | grep -E "BackupPhase|Running" | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if it's stuck
|
||||||
|
if echo "$TM_STATUS" | grep -q "Running = 1"; then
|
||||||
|
PHASE=$(echo "$TM_STATUS" | grep "BackupPhase" | sed 's/.*BackupPhase = \([^;]*\).*/\1/')
|
||||||
|
echo "⚠️ Time Machine is RUNNING and stuck in phase: $PHASE"
|
||||||
|
echo ""
|
||||||
|
echo " This is why your space disappeared:"
|
||||||
|
echo " - Time Machine created a local snapshot before backing up"
|
||||||
|
echo " - It's trying to connect to NAS but can't"
|
||||||
|
echo " - The snapshot is holding your deleted file space"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check current free space
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo " Current free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Stop the stuck Time Machine backup? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "🛑 Stopping Time Machine backup..."
|
||||||
|
|
||||||
|
# Stop the backup
|
||||||
|
sudo tmutil stopbackup 2>/dev/null || {
|
||||||
|
echo " ⚠️ Could not stop via tmutil, trying alternative method..."
|
||||||
|
# Kill the backupd process (more aggressive)
|
||||||
|
sudo killall backupd 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
}
|
||||||
|
|
||||||
|
echo " ✓ Backup stopped"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Wait a moment
|
||||||
|
echo "⏳ Waiting for processes to clean up..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Check if it stopped
|
||||||
|
NEW_STATUS=$(tmutil status 2>/dev/null | grep "Running" || echo "Running = 0")
|
||||||
|
if echo "$NEW_STATUS" | grep -q "Running = 0"; then
|
||||||
|
echo " ✅ Time Machine backup stopped"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Backup may still be running, may need to restart"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Now try to delete the snapshot
|
||||||
|
echo "🗑️ Attempting to delete local snapshot..."
|
||||||
|
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
if [ -n "$SNAPSHOTS" ]; then
|
||||||
|
echo "$SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
if [ -n "$SNAP_DATE" ]; then
|
||||||
|
echo " Deleting: $snapshot"
|
||||||
|
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
||||||
|
echo " ✅ Snapshot deleted!"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Still stuck - may need to remove Time Machine destination first"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Checking disk space..."
|
||||||
|
sleep 3
|
||||||
|
NEW_FREE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
NEW_FREE_GB=$(echo "scale=2; $NEW_FREE / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $NEW_FREE_GB - $FREE_SPACE_GB" | bc)
|
||||||
|
|
||||||
|
echo " Before: ${FREE_SPACE_GB}GB free"
|
||||||
|
echo " After: ${NEW_FREE_GB}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Space not freed yet"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Next Steps ==="
|
||||||
|
echo ""
|
||||||
|
echo "1. If space is still not freed, remove Time Machine destination:"
|
||||||
|
echo " System Settings → Time Machine → Remove backup disk"
|
||||||
|
echo " Then delete snapshot: sudo tmutil deletelocalsnapshots <date>"
|
||||||
|
echo ""
|
||||||
|
echo "2. Fix Time Machine connection issue:"
|
||||||
|
echo " See: time_machine_troubleshooting.md"
|
||||||
|
echo " Common fixes:"
|
||||||
|
echo " - Clear credentials in Keychain Access"
|
||||||
|
echo " - Unmount any manual mounts"
|
||||||
|
echo " - Re-add Time Machine destination"
|
||||||
|
echo ""
|
||||||
|
echo "3. After fixing connection, re-add Time Machine:"
|
||||||
|
echo " System Settings → Time Machine → Add Backup Disk"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo "Cancelled."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "✅ Time Machine is not running"
|
||||||
|
echo ""
|
||||||
|
echo "If space is still missing, check for snapshots:"
|
||||||
|
echo " tmutil listlocalsnapshots /"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+107
@@ -0,0 +1,107 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix Stuck Time Machine Snapshot
|
||||||
|
# When snapshots can't be deleted due to "Stale NFS file handle" error
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Fix Stuck Time Machine Snapshot ==="
|
||||||
|
echo ""
|
||||||
|
echo "This script fixes the 'Stale NFS file handle' error that prevents"
|
||||||
|
echo "snapshot deletion. This happens when Time Machine has a stale"
|
||||||
|
echo "connection to the backup destination."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check current situation
|
||||||
|
echo "📊 Current Status:"
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo " Free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
if [ -n "$SNAPSHOTS" ]; then
|
||||||
|
echo " Stuck snapshots found:"
|
||||||
|
echo "$SNAPSHOTS" | sed 's/^/ - /'
|
||||||
|
else
|
||||||
|
echo " ✓ No snapshots found"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔧 Solution: Temporarily remove Time Machine destination, delete snapshot, then re-add"
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ IMPORTANT: This will temporarily disconnect Time Machine from your NAS."
|
||||||
|
echo " You'll need to re-add it after the snapshot is deleted."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Do you want to proceed? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 1: Removing Time Machine destination..."
|
||||||
|
echo ""
|
||||||
|
echo " Please do this manually:"
|
||||||
|
echo " 1. Open System Settings → General → Time Machine"
|
||||||
|
echo " 2. Click the 'Remove' or '-' button next to your backup disk"
|
||||||
|
echo " 3. Confirm removal"
|
||||||
|
echo ""
|
||||||
|
read -p " Have you removed the Time Machine destination? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo " Please remove it first, then run this script again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 2: Waiting for Time Machine to disconnect..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 3: Attempting to delete stuck snapshot..."
|
||||||
|
echo "$SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
# Extract date part
|
||||||
|
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
if [ -n "$SNAP_DATE" ]; then
|
||||||
|
echo " Deleting: $snapshot"
|
||||||
|
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
||||||
|
echo " ✅ Successfully deleted!"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Still stuck. Try restarting your Mac."
|
||||||
|
echo " After restart, run: sudo tmutil deletelocalsnapshots $SNAP_DATE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 4: Checking disk space..."
|
||||||
|
sleep 3
|
||||||
|
NEW_FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
NEW_FREE_SPACE_GB=$(echo "scale=2; $NEW_FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $NEW_FREE_SPACE_GB - $FREE_SPACE_GB" | bc)
|
||||||
|
|
||||||
|
echo " New free space: ${NEW_FREE_SPACE_GB}GB"
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Space not freed yet - may need restart"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 5: Re-adding Time Machine destination..."
|
||||||
|
echo ""
|
||||||
|
echo " Now re-add your Time Machine backup:"
|
||||||
|
echo " 1. System Settings → General → Time Machine"
|
||||||
|
echo " 2. Click 'Add Backup Disk...'"
|
||||||
|
echo " 3. Select 'Time Machine Folder' on 'DS224plus.local'"
|
||||||
|
echo " 4. Enter your credentials"
|
||||||
|
echo ""
|
||||||
|
echo " Or use the troubleshooting guide:"
|
||||||
|
echo " See: time_machine_troubleshooting.md"
|
||||||
|
echo ""
|
||||||
Executable
+161
@@ -0,0 +1,161 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix System Data Growth When Deleting Files
|
||||||
|
# This happens when APFS snapshots preserve deleted files
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Fix System Data Growth ==="
|
||||||
|
echo ""
|
||||||
|
echo "When you delete files but 'System Data' grows, it means:"
|
||||||
|
echo " - APFS snapshots are preserving deleted files"
|
||||||
|
echo " - Time Machine local snapshots are holding space"
|
||||||
|
echo " - The deleted data is being kept for backup purposes"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for snapshots
|
||||||
|
echo "📸 Checking for snapshots..."
|
||||||
|
TM_SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
SNAP_COUNT=$(echo "$TM_SNAPSHOTS" | grep -v "^$" | wc -l | tr -d ' ')
|
||||||
|
|
||||||
|
if [ "$SNAP_COUNT" -gt 0 ]; then
|
||||||
|
echo " Found $SNAP_COUNT Time Machine snapshot(s):"
|
||||||
|
echo "$TM_SNAPSHOTS" | sed 's/^/ - /'
|
||||||
|
else
|
||||||
|
echo " No Time Machine snapshots found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
APFS_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -c "Name:" || echo "0")
|
||||||
|
echo " Found $APFS_SNAPS APFS snapshot(s)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$SNAP_COUNT" -eq 0 ] && [ "$APFS_SNAPS" -le 1 ]; then
|
||||||
|
echo "⚠️ No obvious snapshots, but System Data is still growing."
|
||||||
|
echo " This may be due to:"
|
||||||
|
echo " - Time Machine preparing for backup"
|
||||||
|
echo " - System cache growth"
|
||||||
|
echo " - Other system processes"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🔧 Solution: Disable local snapshots and clean up"
|
||||||
|
echo ""
|
||||||
|
read -p "Proceed with cleanup? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Step 1: Stop Time Machine backup (if running)..."
|
||||||
|
sudo tmutil stopbackup 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
echo " ✓ Stopped"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Step 2: Delete all local snapshots..."
|
||||||
|
if [ "$SNAP_COUNT" -gt 0 ]; then
|
||||||
|
echo "$TM_SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
SNAP_DATE=$(echo "$snapshot" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
if [ -n "$SNAP_DATE" ]; then
|
||||||
|
echo " Deleting: $snapshot"
|
||||||
|
sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null && \
|
||||||
|
echo " ✅ Deleted" || \
|
||||||
|
echo " ⚠️ Could not delete (may be in use)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " No snapshots to delete"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Step 3: Aggressively thin all snapshots..."
|
||||||
|
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1 || true
|
||||||
|
echo " ✓ Thinned"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Step 4: Disable local snapshots (prevents new ones)..."
|
||||||
|
# Note: tmutil disablelocal doesn't exist in newer macOS, so we'll use a workaround
|
||||||
|
# We'll remove Time Machine destination temporarily
|
||||||
|
echo " ⚠️ To prevent snapshots, you need to:"
|
||||||
|
echo " 1. Remove Time Machine destination in System Settings"
|
||||||
|
echo " 2. Or wait for successful backup to clear snapshots"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Step 5: Purge system memory and caches..."
|
||||||
|
if command -v purge &> /dev/null; then
|
||||||
|
sudo purge
|
||||||
|
echo " ✓ Purged"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Purge command not available"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Step 6: Clean user caches..."
|
||||||
|
rm -rf ~/Library/Caches/* 2>/dev/null || true
|
||||||
|
echo " ✓ Cleaned"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "⏳ Waiting for system to update..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Check results
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No space freed yet"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Critical Next Steps ==="
|
||||||
|
echo ""
|
||||||
|
echo "To STOP System Data from growing when you delete files:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Remove Time Machine destination temporarily**:"
|
||||||
|
echo " System Settings → Time Machine → Remove backup disk"
|
||||||
|
echo " This prevents new snapshots from being created"
|
||||||
|
echo ""
|
||||||
|
echo "2. **Wait 10-15 minutes** after deleting files before checking space"
|
||||||
|
echo " macOS needs time to release snapshot space"
|
||||||
|
echo ""
|
||||||
|
echo "3. **After freeing space, fix Time Machine connection**:"
|
||||||
|
echo " - Clear credentials in Keychain Access"
|
||||||
|
echo " - Re-add Time Machine destination"
|
||||||
|
echo " - Ensure it can successfully connect"
|
||||||
|
echo ""
|
||||||
|
echo "4. **Alternative: Use 'Optimize Storage' in System Settings**:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Optimize"
|
||||||
|
echo " This can help release snapshot space"
|
||||||
|
echo ""
|
||||||
|
echo "5. **If System Data keeps growing**:"
|
||||||
|
echo " - Restart your Mac (releases snapshots)"
|
||||||
|
echo " - Or remove Time Machine until you have more free space"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if (( $(echo "$FREE_SPACE_GB_AFTER < 5" | bc -l) )); then
|
||||||
|
echo "⚠️ Still critically low on space!"
|
||||||
|
echo ""
|
||||||
|
echo " You need to free more space before Time Machine can work."
|
||||||
|
echo " Consider:"
|
||||||
|
echo " - Moving large files to NAS"
|
||||||
|
echo " - Removing unused applications"
|
||||||
|
echo " - Cleaning Downloads folder"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+106
@@ -0,0 +1,106 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Quick Fix: Free up space for Time Machine
|
||||||
|
# This script performs safe cleanup operations to free disk space
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Time Machine Disk Space Fix ==="
|
||||||
|
echo ""
|
||||||
|
echo "This script will help free up space so Time Machine can work."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check current free space
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Ask for confirmation
|
||||||
|
read -p "Do you want to proceed with safe cleanup? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🧹 Cleaning up..."
|
||||||
|
|
||||||
|
# 1. Empty Trash
|
||||||
|
if [ -d ~/.Trash ] && [ "$(ls -A ~/.Trash 2>/dev/null)" ]; then
|
||||||
|
TRASH_SIZE=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Emptying Trash ($TRASH_SIZE)..."
|
||||||
|
rm -rf ~/.Trash/* ~/.Trash/.* 2>/dev/null || true
|
||||||
|
echo " ✓ Trash emptied"
|
||||||
|
else
|
||||||
|
echo " ✓ Trash already empty"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Clean Library Caches (safe - will regenerate)
|
||||||
|
if [ -d ~/Library/Caches ]; then
|
||||||
|
CACHES_SIZE=$(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Cleaning Library/Caches ($CACHES_SIZE)..."
|
||||||
|
# Keep some important caches
|
||||||
|
mkdir -p ~/Library/Caches/backup_temp
|
||||||
|
find ~/Library/Caches -mindepth 1 -maxdepth 1 ! -name "backup_temp" -exec mv {} ~/Library/Caches/backup_temp/ \; 2>/dev/null || true
|
||||||
|
rm -rf ~/Library/Caches/backup_temp/* 2>/dev/null || true
|
||||||
|
rmdir ~/Library/Caches/backup_temp 2>/dev/null || true
|
||||||
|
echo " ✓ Caches cleaned"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Clean user cache
|
||||||
|
if [ -d ~/.cache ]; then
|
||||||
|
CACHE_SIZE=$(du -sh ~/.cache 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Cleaning ~/.cache ($CACHE_SIZE)..."
|
||||||
|
rm -rf ~/.cache/* 2>/dev/null || true
|
||||||
|
echo " ✓ User cache cleaned"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. Clean npm cache (if exists)
|
||||||
|
if command -v npm &> /dev/null; then
|
||||||
|
NPM_CACHE_SIZE=$(du -sh ~/.npm 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
if [ "$NPM_CACHE_SIZE" != "0" ] && [ -d ~/.npm ]; then
|
||||||
|
echo " Cleaning npm cache ($NPM_CACHE_SIZE)..."
|
||||||
|
npm cache clean --force 2>/dev/null || true
|
||||||
|
echo " ✓ npm cache cleaned"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Checking new disk space..."
|
||||||
|
NEW_FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
NEW_FREE_SPACE_GB=$(echo "scale=2; $NEW_FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $NEW_FREE_SPACE_GB - $FREE_SPACE_GB" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB}GB free"
|
||||||
|
echo " After: ${NEW_FREE_SPACE_GB}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " Freed: ${FREED_GB}GB"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if we have enough space now
|
||||||
|
if (( $(echo "$NEW_FREE_SPACE_GB < 5" | bc -l) )); then
|
||||||
|
echo "⚠️ Still low on space. Additional recommendations:"
|
||||||
|
echo ""
|
||||||
|
echo " 1. Review Downloads folder (19GB found):"
|
||||||
|
echo " cd ~/Downloads && ls -lhS | head -20"
|
||||||
|
echo ""
|
||||||
|
echo " 2. Check Documents folder (60GB found):"
|
||||||
|
echo " Move large files to NAS if possible"
|
||||||
|
echo ""
|
||||||
|
echo " 3. Review .ollama folder (17GB found):"
|
||||||
|
echo " Consider removing unused models"
|
||||||
|
echo ""
|
||||||
|
echo " 4. Use macOS Storage Management:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Manage"
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo "✅ Good! You should have enough space for Time Machine now."
|
||||||
|
echo " Try running Time Machine backup again."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+79
@@ -0,0 +1,79 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Fix Synology USB Copy Issue
|
||||||
|
# Based on diagnosis findings
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Fix Synology USB Copy ==="
|
||||||
|
echo ""
|
||||||
|
echo "Diagnosis found:"
|
||||||
|
echo " - USB connection errors (cable/device issue)"
|
||||||
|
echo " - USB device was unmounted"
|
||||||
|
echo " - No USB device currently mounted"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Solutions:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "1. **Physical USB Connection Issue**"
|
||||||
|
echo ""
|
||||||
|
echo " The logs show: 'Cannot enable. Maybe the USB cable is bad?'"
|
||||||
|
echo ""
|
||||||
|
echo " Try:"
|
||||||
|
echo " a) Unplug USB device from front port"
|
||||||
|
echo " b) Wait 10 seconds"
|
||||||
|
echo " c) Plug back in firmly"
|
||||||
|
echo " d) Wait for it to be recognized (check Control Panel → External Devices)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "2. **USB Device Format Issue**"
|
||||||
|
echo ""
|
||||||
|
echo " The device was exFAT and got unmounted due to errors."
|
||||||
|
echo ""
|
||||||
|
echo " Try:"
|
||||||
|
echo " a) Format USB device on your Mac to FAT32 or exFAT"
|
||||||
|
echo " b) Reconnect to Synology front port"
|
||||||
|
echo " c) Wait for recognition"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "3. **Unmount and Remount USB Device**"
|
||||||
|
echo ""
|
||||||
|
echo " Via DSM:"
|
||||||
|
echo " a) Control Panel → External Devices"
|
||||||
|
echo " b) If USB device shows, click 'Unmount'"
|
||||||
|
echo " c) Wait 5 seconds"
|
||||||
|
echo " d) Click 'Mount' or reconnect device"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "4. **Check USB Copy Service**"
|
||||||
|
echo ""
|
||||||
|
echo " Via DSM:"
|
||||||
|
echo " a) Package Center → USB Copy"
|
||||||
|
echo " b) Make sure it's 'Started' (not stopped)"
|
||||||
|
echo " c) If stopped, click 'Start'"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "5. **Check USB Copy Task Settings**"
|
||||||
|
echo ""
|
||||||
|
echo " Via DSM:"
|
||||||
|
echo " a) USB Copy → Select your task"
|
||||||
|
echo " b) Task Settings → Verify source is '[USB]'"
|
||||||
|
echo " c) Make sure no other tasks conflict"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Quick Fix Steps ==="
|
||||||
|
echo ""
|
||||||
|
echo "1. Unplug USB device from Synology"
|
||||||
|
echo "2. Wait 10 seconds"
|
||||||
|
echo "3. Plug USB device into FRONT USB port (not rear)"
|
||||||
|
echo "4. Wait 30 seconds for recognition"
|
||||||
|
echo "5. Check Control Panel → External Devices"
|
||||||
|
echo "6. If device appears, try USB Copy again"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "If still not working, check:"
|
||||||
|
echo " - USB device format (FAT32/exFAT recommended)"
|
||||||
|
echo " - USB device not mounted as shared folder"
|
||||||
|
echo " - USB Copy service is running"
|
||||||
|
echo ""
|
||||||
Executable
+131
@@ -0,0 +1,131 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Force Delete Stuck Snapshot - Last Resort Methods
|
||||||
|
# When normal deletion methods fail
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Force Delete Stuck Snapshot ==="
|
||||||
|
echo ""
|
||||||
|
echo "This script tries aggressive methods to free stuck snapshot space."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
if [ -z "$SNAPSHOTS" ]; then
|
||||||
|
echo "✅ No snapshots found!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Found stuck snapshot(s):"
|
||||||
|
echo "$SNAPSHOTS" | sed 's/^/ - /'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Try aggressive cleanup methods? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Method 1: Aggressive snapshot thinning..."
|
||||||
|
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1 || true
|
||||||
|
echo " ✓ Completed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Method 2: System purge..."
|
||||||
|
if command -v purge &> /dev/null; then
|
||||||
|
sudo purge
|
||||||
|
echo " ✓ Purged"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Purge command not available"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Method 3: Checking APFS snapshots..."
|
||||||
|
APFS_SNAPS=$(diskutil apfs listSnapshots / 2>/dev/null)
|
||||||
|
if echo "$APFS_SNAPS" | grep -qi "timemachine"; then
|
||||||
|
echo " Found Time Machine snapshot in APFS"
|
||||||
|
# Try to get UUID and delete
|
||||||
|
SNAP_UUID=$(echo "$APFS_SNAPS" | grep -A 2 -i "timemachine" | grep "UUID" | awk '{print $NF}' | head -1)
|
||||||
|
if [ -n "$SNAP_UUID" ]; then
|
||||||
|
echo " Attempting to delete APFS snapshot: $SNAP_UUID"
|
||||||
|
sudo diskutil apfs deleteSnapshot / -uuid "$SNAP_UUID" 2>&1 || echo " ⚠️ Could not delete (may be protected)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ℹ️ Snapshot not in APFS list (ghost entry)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Method 4: Force filesystem sync..."
|
||||||
|
sync
|
||||||
|
echo " ✓ Filesystem synced"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Method 5: Check for Time Machine temp files..."
|
||||||
|
TM_TEMP=$(sudo find /System/Volumes/Data/.timemachine -type f 2>/dev/null | wc -l | tr -d ' ')
|
||||||
|
if [ "$TM_TEMP" -gt 0 ]; then
|
||||||
|
TEMP_SIZE=$(sudo du -sh /System/Volumes/Data/.timemachine 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " Found Time Machine temp files: $TEMP_SIZE"
|
||||||
|
read -p " Delete Time Machine temp files? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
sudo rm -rf /System/Volumes/Data/.timemachine/* 2>/dev/null || true
|
||||||
|
echo " ✓ Cleaned"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✓ No temp files found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "⏳ Waiting for system to update..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Check results
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
REMAINING_SNAPS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Free space: ${FREE_SPACE_GB_BEFORE}GB → ${FREE_SPACE_GB_AFTER}GB"
|
||||||
|
if (( $(echo "$FREED_GB > 15" | bc -l) )); then
|
||||||
|
echo " ✅ Successfully freed: ${FREED_GB}GB"
|
||||||
|
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No space freed yet"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$REMAINING_SNAPS" -gt 0 ]; then
|
||||||
|
echo " ⚠️ Snapshot still listed (ghost entry)"
|
||||||
|
echo ""
|
||||||
|
echo " The snapshot entry may persist, but if space was freed,"
|
||||||
|
echo " it's likely just a database entry and not taking space."
|
||||||
|
else
|
||||||
|
echo " ✅ Snapshot removed!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if (( $(echo "$FREED_GB < 15" | bc -l) )); then
|
||||||
|
echo "⚠️ Space still not fully freed. Final options:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Restart your Mac** - This is the most reliable solution."
|
||||||
|
echo " The snapshot will be released after restart."
|
||||||
|
echo ""
|
||||||
|
echo "2. Wait 10-15 minutes - macOS may still be processing"
|
||||||
|
echo ""
|
||||||
|
echo "3. Check if space is actually available but not showing:"
|
||||||
|
echo " - Try creating a large file to test"
|
||||||
|
echo " - Check Activity Monitor → Disk tab"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+143
@@ -0,0 +1,143 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Force Free Space - Remove APFS and Time Machine Snapshots
|
||||||
|
# This script removes snapshots that are holding onto deleted file space
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Force Free Space - Remove Snapshots ==="
|
||||||
|
echo ""
|
||||||
|
echo "This script will remove APFS and Time Machine snapshots that may be"
|
||||||
|
echo "holding onto space from deleted files."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check current free space
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# List current snapshots
|
||||||
|
echo "📸 Current Snapshots:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "1. Time Machine Local Snapshots:"
|
||||||
|
TM_SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$")
|
||||||
|
if [ -n "$TM_SNAPSHOTS" ]; then
|
||||||
|
echo "$TM_SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
echo " - $snapshot"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo " None found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "2. APFS System Snapshots:"
|
||||||
|
APFS_SNAPSHOTS=$(diskutil apfs listSnapshots / 2>/dev/null | grep -E "Snapshot Name|Snapshot UUID" | head -10)
|
||||||
|
if [ -n "$APFS_SNAPSHOTS" ]; then
|
||||||
|
echo "$APFS_SNAPSHOTS"
|
||||||
|
else
|
||||||
|
echo " None found (or cannot list)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Ask for confirmation
|
||||||
|
read -p "Do you want to delete Time Machine local snapshots? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "🗑️ Deleting Time Machine local snapshots..."
|
||||||
|
|
||||||
|
# Delete each snapshot
|
||||||
|
echo "$TM_SNAPSHOTS" | while read snapshot; do
|
||||||
|
if [ -n "$snapshot" ]; then
|
||||||
|
echo " Deleting: $snapshot"
|
||||||
|
sudo tmutil deletelocalsnapshots "$snapshot" 2>/dev/null && \
|
||||||
|
echo " ✓ Deleted $snapshot" || \
|
||||||
|
echo " ⚠️ Could not delete $snapshot (may be in use)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Also try to delete all at once
|
||||||
|
sudo tmutil deletelocalsnapshots / 2>/dev/null || true
|
||||||
|
|
||||||
|
echo " ✓ Time Machine snapshots cleanup attempted"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Force purge of purgeable space
|
||||||
|
echo "3. Purging Purgeable Space..."
|
||||||
|
echo " This forces macOS to actually free up space from deleted files."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Do you want to purge purgeable space? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo " Running purge command..."
|
||||||
|
|
||||||
|
# Method 1: Use purge command (if available)
|
||||||
|
if command -v purge &> /dev/null; then
|
||||||
|
sudo purge
|
||||||
|
echo " ✓ Purge command executed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Method 2: Disable and re-enable local snapshots to force cleanup
|
||||||
|
echo " Disabling local snapshots..."
|
||||||
|
sudo tmutil disablelocal 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
echo " Re-enabling local snapshots..."
|
||||||
|
sudo tmutil enablelocal 2>/dev/null || true
|
||||||
|
|
||||||
|
# Method 3: Force Time Machine to clean up
|
||||||
|
echo " Triggering Time Machine cleanup..."
|
||||||
|
sudo tmutil thinlocalsnapshots / 1000000000 4 2>/dev/null || true
|
||||||
|
|
||||||
|
echo " ✓ Purge operations completed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check new free space
|
||||||
|
sleep 2
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No space freed yet (may need to wait or try other methods)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if (( $(echo "$FREED_GB < 15" | bc -l) )) && (( $(echo "$FREE_SPACE_GB_AFTER < 5" | bc -l) )); then
|
||||||
|
echo "⚠️ Still low on space. Additional steps:"
|
||||||
|
echo ""
|
||||||
|
echo "1. Wait a few minutes - macOS may still be processing"
|
||||||
|
echo ""
|
||||||
|
echo "2. Restart your Mac - this often frees up snapshot space"
|
||||||
|
echo ""
|
||||||
|
echo "3. Check for large files in other locations:"
|
||||||
|
echo " ./free_disk_space.sh"
|
||||||
|
echo ""
|
||||||
|
echo "4. Manually delete the Time Machine snapshot:"
|
||||||
|
SNAP=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | head -1)
|
||||||
|
if [ -n "$SNAP" ]; then
|
||||||
|
echo " sudo tmutil deletelocalsnapshots $SNAP"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
echo "5. Use macOS Storage Management:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Manage"
|
||||||
|
echo " This tool can identify and remove large system files"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+100
@@ -0,0 +1,100 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Force Purge System Data (351GB)
|
||||||
|
# The 351GB is likely "purgeable" space that macOS won't release until forced
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Force Purge System Data (351GB) ==="
|
||||||
|
echo ""
|
||||||
|
echo "The 351GB in System Data is likely PURGEABLE space."
|
||||||
|
echo "macOS shows it as 'used' but it's actually available."
|
||||||
|
echo "We'll force macOS to release it by creating a large file."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Method: Create a large file to force purge..."
|
||||||
|
echo ""
|
||||||
|
echo " This will:"
|
||||||
|
echo " 1. Create a 50GB file (forces macOS to purge space)"
|
||||||
|
echo " 2. Delete it immediately"
|
||||||
|
echo " 3. This should release the purgeable space"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Proceed? This is safe - file will be deleted immediately. (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Creating 50GB test file to force purge..."
|
||||||
|
echo " (This may take a few minutes)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create large file to force purge
|
||||||
|
TEST_FILE="$HOME/test_force_purge_$(date +%s).tmp"
|
||||||
|
if dd if=/dev/zero of="$TEST_FILE" bs=1g count=50 2>/dev/null; then
|
||||||
|
echo " ✅ Created 50GB file"
|
||||||
|
echo ""
|
||||||
|
echo " Checking space after creation..."
|
||||||
|
sleep 2
|
||||||
|
FREE_DURING=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_DURING_GB=$(echo "scale=2; $FREE_DURING / 1024 / 1024" | bc)
|
||||||
|
echo " Free space during: ${FREE_DURING_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo " Deleting test file..."
|
||||||
|
rm -f "$TEST_FILE"
|
||||||
|
echo " ✅ Deleted"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Could not create file (not enough space or permission issue)"
|
||||||
|
echo " This means the purgeable space may not be available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "⏳ Waiting for system to update..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# Check final results
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 100" | bc -l) )); then
|
||||||
|
echo " ✅ Successfully freed: ${FREED_GB}GB!"
|
||||||
|
echo " The purgeable space was released!"
|
||||||
|
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No space freed"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== Understanding System Data (351GB) ==="
|
||||||
|
echo ""
|
||||||
|
echo "If System Data still shows 351GB but you have free space,"
|
||||||
|
echo "this is NORMAL macOS behavior:"
|
||||||
|
echo ""
|
||||||
|
echo " - System Data includes PURGEABLE space"
|
||||||
|
echo " - Purgeable space is AVAILABLE but shown as 'used'"
|
||||||
|
echo " - macOS will release it automatically when needed"
|
||||||
|
echo " - The space is actually available for use"
|
||||||
|
echo ""
|
||||||
|
echo "To verify space is available:"
|
||||||
|
echo " 1. Try creating a large file (you just did)"
|
||||||
|
echo " 2. Check Activity Monitor → Disk → Purgeable"
|
||||||
|
echo " 3. The space will be released when you actually need it"
|
||||||
|
echo ""
|
||||||
|
echo "The 351GB in System Data is misleading - much of it"
|
||||||
|
echo "is purgeable and available when needed."
|
||||||
|
echo ""
|
||||||
Executable
+96
@@ -0,0 +1,96 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Free Disk Space for Time Machine
|
||||||
|
# This script helps identify and free up space on your Mac so Time Machine can work
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Mac Disk Space Analysis ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check current disk usage
|
||||||
|
echo "📊 Current Disk Status:"
|
||||||
|
df -h / | tail -1 | awk '{print " Total: " $2 " | Used: " $3 " (" $5 ") | Free: " $4}'
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if disk is critically low
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
|
||||||
|
if (( $(echo "$FREE_SPACE_GB < 5" | bc -l) )); then
|
||||||
|
echo "⚠️ WARNING: Disk has less than 5GB free. Time Machine requires free space to work!"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🔍 Analyzing Large Files and Folders:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check Downloads folder
|
||||||
|
if [ -d ~/Downloads ]; then
|
||||||
|
DOWNLOADS_SIZE=$(du -sh ~/Downloads 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " 📁 Downloads: $DOWNLOADS_SIZE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check Library Caches
|
||||||
|
if [ -d ~/Library/Caches ]; then
|
||||||
|
CACHES_SIZE=$(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " 🗑️ Library/Caches: $CACHES_SIZE (safe to clean)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check Trash
|
||||||
|
if [ -d ~/.Trash ]; then
|
||||||
|
TRASH_SIZE=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " 🗑️ Trash: $TRASH_SIZE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check local Time Machine snapshots
|
||||||
|
echo ""
|
||||||
|
echo "📸 Local Time Machine Snapshots:"
|
||||||
|
SNAPSHOTS=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | wc -l | tr -d ' ')
|
||||||
|
if [ "$SNAPSHOTS" -gt 0 ]; then
|
||||||
|
echo " Found $SNAPSHOTS local snapshot(s)"
|
||||||
|
tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | sed 's/^/ - /'
|
||||||
|
echo ""
|
||||||
|
echo " 💡 Tip: Local snapshots are automatically deleted when space is needed,"
|
||||||
|
echo " but you can delete them manually if needed."
|
||||||
|
else
|
||||||
|
echo " No local snapshots found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📋 Top 10 Largest Files/Directories in Home:"
|
||||||
|
du -h -d 1 ~ 2>/dev/null | sort -hr | head -10 | awk '{printf " %8s %s\n", $1, $2}'
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Recommendations ==="
|
||||||
|
echo ""
|
||||||
|
echo "1. 🗑️ Empty Trash:"
|
||||||
|
echo " rm -rf ~/.Trash/*"
|
||||||
|
echo ""
|
||||||
|
echo "2. 🧹 Clean System Caches (safe):"
|
||||||
|
echo " rm -rf ~/Library/Caches/*"
|
||||||
|
echo ""
|
||||||
|
echo "3. 📁 Review Downloads folder (~/Downloads) - 19GB found"
|
||||||
|
echo " Move large files to NAS or delete if not needed"
|
||||||
|
echo ""
|
||||||
|
echo "4. 🗑️ Delete old local snapshots (if needed):"
|
||||||
|
echo " sudo tmutil deletelocalsnapshots <snapshot-date>"
|
||||||
|
echo ""
|
||||||
|
echo "5. 💾 Use Storage Management:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Manage"
|
||||||
|
echo " This tool can help identify and remove large files, old backups, etc."
|
||||||
|
echo ""
|
||||||
|
echo "6. 📦 Check for large applications:"
|
||||||
|
echo " Review Applications folder for unused apps"
|
||||||
|
echo ""
|
||||||
|
echo "=== Quick Clean Commands ==="
|
||||||
|
echo ""
|
||||||
|
echo "To clean caches (safe, will regenerate):"
|
||||||
|
echo " rm -rf ~/Library/Caches/*"
|
||||||
|
echo ""
|
||||||
|
echo "To empty trash:"
|
||||||
|
echo " rm -rf ~/.Trash/*"
|
||||||
|
echo ""
|
||||||
|
echo "To see what's taking up space:"
|
||||||
|
echo " du -h -d 1 ~ | sort -hr | head -20"
|
||||||
|
echo ""
|
||||||
Executable
+87
@@ -0,0 +1,87 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Free Photo Cache Space
|
||||||
|
# The photo volume is taking 179GB - likely a local cache
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Free Photo Cache Space ==="
|
||||||
|
echo ""
|
||||||
|
echo "Found: /System/Volumes/Data/Volumes/photo is 179GB"
|
||||||
|
echo "This is a mounted NAS share that's being cached locally."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if it's the same as /Volumes/photo
|
||||||
|
echo "🔍 Checking mount points:"
|
||||||
|
MOUNT_POINT=$(mount | grep photo | awk '{print $3}')
|
||||||
|
echo " Network mount: $MOUNT_POINT"
|
||||||
|
echo " Cache location: /System/Volumes/Data/Volumes/photo"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check sizes
|
||||||
|
CACHE_SIZE=$(sudo du -sh /System/Volumes/Data/Volumes/photo 2>/dev/null | awk '{print $1}')
|
||||||
|
MOUNT_SIZE=$(sudo du -sh "$MOUNT_POINT" 2>/dev/null | awk '{print $1}' || echo "N/A")
|
||||||
|
echo " Cache size: $CACHE_SIZE"
|
||||||
|
echo " Mount size: $MOUNT_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "⚠️ The 179GB in /System/Volumes/Data/Volumes/photo is likely:"
|
||||||
|
echo " - A local cache of the network share"
|
||||||
|
echo " - Or files that were copied locally"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Solution:"
|
||||||
|
echo ""
|
||||||
|
echo "Option 1: Unmount the network share (if not needed right now)"
|
||||||
|
echo " diskutil unmount /Volumes/photo"
|
||||||
|
echo " This will free the space immediately"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Option 2: Clear the cache (if it's a cache)"
|
||||||
|
echo " ⚠️ WARNING: Make sure files are on NAS first!"
|
||||||
|
echo " sudo rm -rf /System/Volumes/Data/Volumes/photo/*"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "Option 3: Check if files are duplicated"
|
||||||
|
echo " Compare /Volumes/photo vs /System/Volumes/Data/Volumes/photo"
|
||||||
|
echo " If they're the same, you can safely remove the cache"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Do you want to unmount /Volumes/photo to free space? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "Unmounting /Volumes/photo..."
|
||||||
|
if diskutil unmount /Volumes/photo 2>/dev/null; then
|
||||||
|
echo "✅ Successfully unmounted"
|
||||||
|
echo ""
|
||||||
|
echo "⏳ Waiting for space to be released..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 150" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB (179GB cache released!)"
|
||||||
|
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Space not freed yet (may need to clear cache manually)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "⚠️ Could not unmount (may be in use)"
|
||||||
|
echo " Try: sudo umount /Volumes/photo"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+156
@@ -0,0 +1,156 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Free Space Without Triggering Snapshot Growth
|
||||||
|
# Delete files that are ALREADY in snapshots or don't trigger snapshots
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Free Space Without Snapshot Growth ==="
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ CRITICAL: Stop deleting regular files!"
|
||||||
|
echo " Every file you delete is preserved in the OS snapshot,"
|
||||||
|
echo " making System Data grow."
|
||||||
|
echo ""
|
||||||
|
echo "Instead, delete files that DON'T trigger snapshot growth:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Safe to Delete (Won't Grow System Data):"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. Caches (already cached, deleting doesn't create new snapshots)
|
||||||
|
echo "1. Library Caches (~6GB):"
|
||||||
|
CACHE_SIZE=$(du -sh ~/Library/Caches 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " Size: $CACHE_SIZE"
|
||||||
|
echo " Command: rm -rf ~/Library/Caches/*"
|
||||||
|
echo " ✅ Safe - caches are temporary"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. User cache
|
||||||
|
echo "2. User Cache (~3GB):"
|
||||||
|
USER_CACHE=$(du -sh ~/.cache 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " Size: $USER_CACHE"
|
||||||
|
echo " Command: rm -rf ~/.cache/*"
|
||||||
|
echo " ✅ Safe - temporary files"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. Downloads (if already backed up)
|
||||||
|
echo "3. Downloads (~9GB):"
|
||||||
|
DOWNLOADS_SIZE=$(du -sh ~/Downloads 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " Size: $DOWNLOADS_SIZE"
|
||||||
|
echo " ⚠️ Only if files are already on NAS"
|
||||||
|
echo " Command: rm -rf ~/Downloads/*"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 4. Trash
|
||||||
|
echo "4. Trash:"
|
||||||
|
TRASH_SIZE=$(du -sh ~/.Trash 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " Size: $TRASH_SIZE"
|
||||||
|
echo " Command: rm -rf ~/.Trash/*"
|
||||||
|
echo " ✅ Safe - already deleted"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 5. npm cache
|
||||||
|
echo "5. npm Cache (~1GB):"
|
||||||
|
NPM_SIZE=$(du -sh ~/.npm 2>/dev/null | awk '{print $1}' || echo "0")
|
||||||
|
echo " Size: $NPM_SIZE"
|
||||||
|
echo " Command: npm cache clean --force"
|
||||||
|
echo " ✅ Safe - can be regenerated"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
TOTAL_SAFE=$(echo "6 + 3 + 1" | bc)
|
||||||
|
echo "Estimated safe space to free: ~${TOTAL_SAFE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Clean these safe items now? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "🧹 Cleaning safe items..."
|
||||||
|
|
||||||
|
# Clean caches
|
||||||
|
if [ -d ~/Library/Caches ]; then
|
||||||
|
rm -rf ~/Library/Caches/* 2>/dev/null || true
|
||||||
|
echo " ✅ Cleaned Library/Caches"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d ~/.cache ]; then
|
||||||
|
rm -rf ~/.cache/* 2>/dev/null || true
|
||||||
|
echo " ✅ Cleaned user cache"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean trash
|
||||||
|
if [ -d ~/.Trash ]; then
|
||||||
|
rm -rf ~/.Trash/* 2>/dev/null || true
|
||||||
|
echo " ✅ Emptied Trash"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean npm
|
||||||
|
if command -v npm &> /dev/null && [ -d ~/.npm ]; then
|
||||||
|
npm cache clean --force 2>/dev/null || true
|
||||||
|
echo " ✅ Cleaned npm cache"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "⏳ Waiting for system to update..."
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check results
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No space freed (may need restart)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== CRITICAL INSTRUCTIONS ==="
|
||||||
|
echo ""
|
||||||
|
echo "1. ⛔ STOP DELETING REGULAR FILES"
|
||||||
|
echo " Every file you delete makes System Data grow!"
|
||||||
|
echo ""
|
||||||
|
echo "2. ✅ Only delete:"
|
||||||
|
echo " - Caches (already done above)"
|
||||||
|
echo " - Trash (already done above)"
|
||||||
|
echo " - Files that are already on NAS"
|
||||||
|
echo ""
|
||||||
|
echo "3. 🚀 Install macOS Update NOW:"
|
||||||
|
echo " System Settings → General → Software Update"
|
||||||
|
echo " Install macOS Tahoe 26.2"
|
||||||
|
echo ""
|
||||||
|
echo " The update will:"
|
||||||
|
echo " - Clear the old snapshot"
|
||||||
|
echo " - Free the 351GB in System Data"
|
||||||
|
echo " - Stop the snapshot growth problem"
|
||||||
|
echo ""
|
||||||
|
echo "4. ⏳ If you don't have enough space for update:"
|
||||||
|
echo " - The update needs ~3.6GB"
|
||||||
|
echo " - Try downloading it first (may work with less space)"
|
||||||
|
echo " - Or move files to NAS instead of deleting"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if (( $(echo "$FREE_SPACE_GB_AFTER < 4" | bc -l) )); then
|
||||||
|
echo "⚠️ Still low on space for update."
|
||||||
|
echo ""
|
||||||
|
echo " Try downloading the update first:"
|
||||||
|
echo " sudo softwareupdate --download --all"
|
||||||
|
echo ""
|
||||||
|
echo " Or move (don't delete) large files to NAS:"
|
||||||
|
echo " - Documents folder (40GB)"
|
||||||
|
echo " - .ollama models (17GB)"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+111
@@ -0,0 +1,111 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Free System Data (351GB)
|
||||||
|
# Most of this is purgeable space held by snapshots
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Free System Data (351GB) ==="
|
||||||
|
echo ""
|
||||||
|
echo "System Data is 351GB, but visible components only add up to ~20GB."
|
||||||
|
echo "This means ~330GB is PURGEABLE SPACE held by snapshots."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE_BEFORE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_BEFORE=$(echo "scale=2; $FREE_SPACE_BEFORE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB_BEFORE}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Step 1: Aggressively thin all snapshots..."
|
||||||
|
sudo tmutil thinlocalsnapshots / 1000000000 1 2>&1
|
||||||
|
echo " ✓ Completed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Step 2: Purge system memory and caches..."
|
||||||
|
if command -v purge &> /dev/null; then
|
||||||
|
sudo purge
|
||||||
|
echo " ✓ Purged"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Purge command not available"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Step 3: Remove Time Machine destination (CRITICAL)"
|
||||||
|
echo ""
|
||||||
|
echo " ⚠️ IMPORTANT: You MUST remove Time Machine destination to"
|
||||||
|
echo " prevent new snapshots from being created!"
|
||||||
|
echo ""
|
||||||
|
echo " Do this now:"
|
||||||
|
echo " 1. System Settings → General → Time Machine"
|
||||||
|
echo " 2. Click '-' to remove backup disk"
|
||||||
|
echo " 3. Confirm removal"
|
||||||
|
echo ""
|
||||||
|
read -p " Have you removed Time Machine destination? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo " ⚠️ Please remove it first, then run this script again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔧 Step 4: Wait for system to release purgeable space..."
|
||||||
|
echo " This may take a few minutes..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔧 Step 5: Try to delete stuck snapshot..."
|
||||||
|
SNAPSHOT=$(tmutil listlocalsnapshots / 2>/dev/null | grep -v "Snapshots for disk" | grep -v "^$" | head -1)
|
||||||
|
if [ -n "$SNAPSHOT" ]; then
|
||||||
|
SNAP_DATE=$(echo "$SNAPSHOT" | sed 's/.*\.\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}\)\.backup/\1/')
|
||||||
|
echo " Attempting to delete: $SNAPSHOT"
|
||||||
|
if sudo tmutil deletelocalsnapshots "$SNAP_DATE" 2>/dev/null; then
|
||||||
|
echo " ✅ Deleted!"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Still stuck (ghost entry - will clear on restart)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✅ No snapshots found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "⏳ Waiting for space to be released..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# Check results
|
||||||
|
FREE_SPACE_AFTER=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB_AFTER=$(echo "scale=2; $FREE_SPACE_AFTER / 1024 / 1024" | bc)
|
||||||
|
FREED_GB=$(echo "scale=2; $FREE_SPACE_GB_AFTER - $FREE_SPACE_GB_BEFORE" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Results ==="
|
||||||
|
echo " Before: ${FREE_SPACE_GB_BEFORE}GB free"
|
||||||
|
echo " After: ${FREE_SPACE_GB_AFTER}GB free"
|
||||||
|
if (( $(echo "$FREED_GB > 100" | bc -l) )); then
|
||||||
|
echo " ✅ Successfully freed: ${FREED_GB}GB!"
|
||||||
|
elif (( $(echo "$FREED_GB > 0" | bc -l) )); then
|
||||||
|
echo " ✅ Freed: ${FREED_GB}GB"
|
||||||
|
echo " (More space may be released over time)"
|
||||||
|
else
|
||||||
|
echo " ⚠️ No space freed yet"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if (( $(echo "$FREE_SPACE_GB_AFTER < 50" | bc -l) )); then
|
||||||
|
echo "⚠️ Still low on space. Additional steps:"
|
||||||
|
echo ""
|
||||||
|
echo "1. **Restart your Mac** - This is the most effective way"
|
||||||
|
echo " to release purgeable space from snapshots."
|
||||||
|
echo ""
|
||||||
|
echo "2. Use macOS Storage Management:"
|
||||||
|
echo " Apple Menu → About This Mac → Storage → Manage"
|
||||||
|
echo " Click 'Optimize' to release purgeable space"
|
||||||
|
echo ""
|
||||||
|
echo "3. Wait 15-30 minutes - macOS may need time to"
|
||||||
|
echo " release the purgeable space"
|
||||||
|
echo ""
|
||||||
|
echo "4. The 351GB in System Data is mostly purgeable space"
|
||||||
|
echo " that will be released when snapshots are cleared."
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+61
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to get detailed EnConvo crash information
|
||||||
|
|
||||||
|
echo "=== EnConvo Crash Details Collector ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. Check for crash reports
|
||||||
|
echo "1. Recent Crash Reports:"
|
||||||
|
CRASH_REPORTS=$(ls -t ~/Library/Logs/DiagnosticReports/*EnConvo* 2>/dev/null | head -3)
|
||||||
|
if [ -z "$CRASH_REPORTS" ]; then
|
||||||
|
echo " No crash reports found in DiagnosticReports"
|
||||||
|
else
|
||||||
|
echo " Found crash reports:"
|
||||||
|
echo "$CRASH_REPORTS" | while read report; do
|
||||||
|
echo " - $(basename "$report")"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. Get the most recent crash report summary
|
||||||
|
echo "2. Most Recent Crash Report Summary:"
|
||||||
|
LATEST_CRASH=$(ls -t ~/Library/Logs/DiagnosticReports/*EnConvo* 2>/dev/null | head -1)
|
||||||
|
if [ -n "$LATEST_CRASH" ]; then
|
||||||
|
echo " File: $(basename "$LATEST_CRASH")"
|
||||||
|
echo ""
|
||||||
|
echo " Exception Type:"
|
||||||
|
grep -A 5 "Exception Type:" "$LATEST_CRASH" 2>/dev/null | head -6 || echo " (Not found)"
|
||||||
|
echo ""
|
||||||
|
echo " Crashed Thread:"
|
||||||
|
grep -A 10 "Crashed Thread:" "$LATEST_CRASH" 2>/dev/null | head -11 || echo " (Not found)"
|
||||||
|
echo ""
|
||||||
|
echo " Application Specific Information:"
|
||||||
|
grep -A 5 "Application Specific Information:" "$LATEST_CRASH" 2>/dev/null | head -6 || echo " (Not found)"
|
||||||
|
else
|
||||||
|
echo " No crash report found. The app may have exited without creating one."
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. Check Console logs
|
||||||
|
echo "3. Recent Console Logs (last 30 seconds):"
|
||||||
|
log show --predicate 'process == "EnConvo" AND eventMessage CONTAINS "error" OR eventMessage CONTAINS "crash" OR eventMessage CONTAINS "exception"' --last 30s --style compact 2>/dev/null | tail -10 || echo " (No relevant logs found)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=== To view full crash report, run: ==="
|
||||||
|
if [ -n "$LATEST_CRASH" ]; then
|
||||||
|
echo "open '$LATEST_CRASH'"
|
||||||
|
else
|
||||||
|
echo "# No crash report found yet"
|
||||||
|
echo "# After the crash, run: ls -t ~/Library/Logs/DiagnosticReports/*EnConvo* | head -1 | xargs open"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+70
@@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Install Tailscale on server2
|
||||||
|
# This script will detect the OS and install Tailscale accordingly
|
||||||
|
|
||||||
|
echo "=== Installing Tailscale on server2 ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Detect OS and install Tailscale
|
||||||
|
echo "Detecting OS and installing Tailscale..."
|
||||||
|
ssh server2 << 'EOF'
|
||||||
|
# Detect OS
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
. /etc/os-release
|
||||||
|
OS=$ID
|
||||||
|
VER=$VERSION_ID
|
||||||
|
else
|
||||||
|
echo "Cannot detect OS. Assuming Ubuntu/Debian."
|
||||||
|
OS="ubuntu"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Detected OS: $OS $VER"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Install Tailscale based on OS
|
||||||
|
case $OS in
|
||||||
|
ubuntu|debian)
|
||||||
|
echo "Installing Tailscale on Ubuntu/Debian..."
|
||||||
|
curl -fsSL https://tailscale.com/install.sh | sh
|
||||||
|
;;
|
||||||
|
fedora|rhel|centos|rocky|almalinux)
|
||||||
|
echo "Installing Tailscale on RHEL/CentOS/Fedora..."
|
||||||
|
curl -fsSL https://tailscale.com/install.sh | sh
|
||||||
|
;;
|
||||||
|
arch|manjaro)
|
||||||
|
echo "Installing Tailscale on Arch Linux..."
|
||||||
|
curl -fsSL https://tailscale.com/install.sh | sh
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Using generic Linux installation..."
|
||||||
|
curl -fsSL https://tailscale.com/install.sh | sh
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Tailscale installation complete!"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo "1. Run: sudo tailscale up"
|
||||||
|
echo "2. Follow the authentication link to connect this machine to your Tailscale network"
|
||||||
|
echo ""
|
||||||
|
echo "To check status: sudo tailscale status"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Installation script completed ==="
|
||||||
|
echo ""
|
||||||
|
echo "To authenticate and start Tailscale, run:"
|
||||||
|
echo " ssh server2 'sudo tailscale up'"
|
||||||
|
echo ""
|
||||||
|
echo "This will provide a URL to authenticate the device."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
# iPhone Mirroring Troubleshooting
|
||||||
|
|
||||||
|
## Issue
|
||||||
|
iPhone Mirroring shows "Unable to Connect to iPhone" error, even though:
|
||||||
|
- ✅ Same iPhone works on another MacBook
|
||||||
|
- ✅ iPhone is near the Mac, powered on
|
||||||
|
- ✅ iPhone is running iOS 18 or later
|
||||||
|
|
||||||
|
## Requirements Checklist
|
||||||
|
|
||||||
|
### iPhone Requirements
|
||||||
|
- [ ] iOS 18.0 or later
|
||||||
|
- [ ] Bluetooth enabled
|
||||||
|
- [ ] Wi-Fi enabled
|
||||||
|
- [ ] Signed in to iCloud with same Apple ID as Mac
|
||||||
|
- [ ] iPhone is unlocked (or recently unlocked)
|
||||||
|
- [ ] iPhone is near the Mac (within Bluetooth range)
|
||||||
|
|
||||||
|
### Mac Requirements
|
||||||
|
- [ ] macOS Sequoia 15.0 or later
|
||||||
|
- [ ] Bluetooth enabled
|
||||||
|
- [ ] Wi-Fi enabled
|
||||||
|
- [ ] Signed in to iCloud with same Apple ID as iPhone
|
||||||
|
- [ ] Continuity features enabled
|
||||||
|
|
||||||
|
## Common Causes & Solutions
|
||||||
|
|
||||||
|
### 1. Different iCloud Account
|
||||||
|
**Most Common Issue**: Mac and iPhone signed in to different iCloud accounts
|
||||||
|
|
||||||
|
**Check:**
|
||||||
|
```bash
|
||||||
|
# On Mac - check iCloud account
|
||||||
|
defaults read MobileMeAccounts Accounts | grep AccountID
|
||||||
|
|
||||||
|
# Or check System Settings → Apple ID
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- System Settings → Apple ID → Sign in with same account as iPhone
|
||||||
|
- iPhone: Settings → [Your Name] → Verify Apple ID matches
|
||||||
|
|
||||||
|
### 2. Continuity Features Disabled
|
||||||
|
**Check:**
|
||||||
|
- System Settings → General → AirDrop & Handoff
|
||||||
|
- Ensure "Handoff" is enabled
|
||||||
|
- Ensure "Allow Handoff between this Mac and your iCloud devices" is checked
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
```bash
|
||||||
|
# Enable Handoff via command line
|
||||||
|
defaults write com.apple.coreservices.useractivityd.plist ActivityAdvertisingAllowed -bool true
|
||||||
|
defaults write com.apple.coreservices.useractivityd.plist ActivityReceivingAllowed -bool true
|
||||||
|
|
||||||
|
# Restart the service
|
||||||
|
killall sharingd
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Bluetooth/Wi-Fi Issues
|
||||||
|
**Check:**
|
||||||
|
```bash
|
||||||
|
# Check Bluetooth status
|
||||||
|
system_profiler SPBluetoothDataType | grep -A 5 "State"
|
||||||
|
|
||||||
|
# Check Wi-Fi status
|
||||||
|
networksetup -getairportpower en0
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- Turn Bluetooth off and on: System Settings → Bluetooth
|
||||||
|
- Turn Wi-Fi off and on: System Settings → Wi-Fi
|
||||||
|
- Restart both devices
|
||||||
|
|
||||||
|
### 4. macOS Version Too Old
|
||||||
|
**Check:**
|
||||||
|
```bash
|
||||||
|
sw_vers
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- iPhone Mirroring requires macOS Sequoia 15.0 or later
|
||||||
|
- Update macOS: System Settings → General → Software Update
|
||||||
|
|
||||||
|
### 5. Firewall Blocking Connection
|
||||||
|
**Check:**
|
||||||
|
- System Settings → Network → Firewall
|
||||||
|
- Check if Firewall is enabled
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- Temporarily disable Firewall to test
|
||||||
|
- If it works, add exception for "Continuity" or "Handoff"
|
||||||
|
- Or ensure "Block all incoming connections" is NOT checked
|
||||||
|
|
||||||
|
### 6. Network Isolation
|
||||||
|
**Check:**
|
||||||
|
- Are Mac and iPhone on the same Wi-Fi network?
|
||||||
|
- Is there a VPN active on either device?
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- Connect both to same Wi-Fi network
|
||||||
|
- Disable VPN temporarily to test
|
||||||
|
- Ensure network allows device-to-device communication (not in guest/isolated mode)
|
||||||
|
|
||||||
|
### 7. Bluetooth Permissions
|
||||||
|
**Check:**
|
||||||
|
- System Settings → Privacy & Security → Bluetooth
|
||||||
|
- Ensure apps have Bluetooth access
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
- Grant Bluetooth permissions if prompted
|
||||||
|
- Restart Mac after granting permissions
|
||||||
|
|
||||||
|
### 8. Stale Continuity Cache
|
||||||
|
**Fix:**
|
||||||
|
```bash
|
||||||
|
# Reset Continuity/Handoff cache
|
||||||
|
killall sharingd
|
||||||
|
killall bluetoothd
|
||||||
|
|
||||||
|
# Or restart Bluetooth daemon
|
||||||
|
sudo launchctl stop com.apple.bluetoothd
|
||||||
|
sudo launchctl start com.apple.bluetoothd
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9. Reset Network Settings (Last Resort)
|
||||||
|
**On iPhone:**
|
||||||
|
- Settings → General → Transfer or Reset iPhone → Reset → Reset Network Settings
|
||||||
|
- This will reset Wi-Fi passwords but may fix connection issues
|
||||||
|
|
||||||
|
**On Mac:**
|
||||||
|
```bash
|
||||||
|
# Reset network location (less drastic)
|
||||||
|
sudo networksetup -setairportpower en0 off
|
||||||
|
sleep 2
|
||||||
|
sudo networksetup -setairportpower en0 on
|
||||||
|
```
|
||||||
|
|
||||||
|
## Diagnostic Commands
|
||||||
|
|
||||||
|
### Check Continuity Status
|
||||||
|
```bash
|
||||||
|
# Check Handoff status
|
||||||
|
defaults read com.apple.coreservices.useractivityd.plist
|
||||||
|
|
||||||
|
# Check Bluetooth connectivity
|
||||||
|
system_profiler SPBluetoothDataType | grep -i "connected\|paired"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check System Logs
|
||||||
|
```bash
|
||||||
|
# Check for iPhone Mirroring errors
|
||||||
|
log show --predicate 'eventMessage contains "iPhone Mirroring" or eventMessage contains "Continuity"' --last 1h --info
|
||||||
|
|
||||||
|
# Check Bluetooth errors
|
||||||
|
log show --predicate 'subsystem == "com.apple.bluetooth"' --last 1h --info | tail -50
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check iCloud Account Match
|
||||||
|
```bash
|
||||||
|
# Mac iCloud account
|
||||||
|
defaults read MobileMeAccounts Accounts | grep -A 5 "AccountID"
|
||||||
|
|
||||||
|
# Compare with iPhone (check iPhone Settings → [Your Name])
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Bluetooth Connection
|
||||||
|
```bash
|
||||||
|
# List nearby Bluetooth devices
|
||||||
|
system_profiler SPBluetoothDataType | grep -A 10 "iPhone"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step-by-Step Troubleshooting
|
||||||
|
|
||||||
|
1. **Verify Requirements:**
|
||||||
|
- Check macOS version (must be 15.0+)
|
||||||
|
- Check iOS version (must be 18.0+)
|
||||||
|
- Verify same iCloud account on both devices
|
||||||
|
|
||||||
|
2. **Restart Services:**
|
||||||
|
```bash
|
||||||
|
killall sharingd
|
||||||
|
killall bluetoothd
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Restart Both Devices:**
|
||||||
|
- Restart Mac
|
||||||
|
- Restart iPhone
|
||||||
|
|
||||||
|
4. **Check System Settings:**
|
||||||
|
- System Settings → General → AirDrop & Handoff → Enable Handoff
|
||||||
|
- System Settings → Privacy & Security → Bluetooth → Ensure enabled
|
||||||
|
- System Settings → Network → Firewall → Check settings
|
||||||
|
|
||||||
|
5. **Try Again:**
|
||||||
|
- Make sure iPhone is unlocked
|
||||||
|
- Bring iPhone close to Mac
|
||||||
|
- Try connecting again
|
||||||
|
|
||||||
|
6. **If Still Not Working:**
|
||||||
|
- Sign out and sign back into iCloud on Mac
|
||||||
|
- Sign out and sign back into iCloud on iPhone
|
||||||
|
- Try again
|
||||||
|
|
||||||
|
## Comparison with Working MacBook
|
||||||
|
|
||||||
|
Since it works on another MacBook, compare:
|
||||||
|
|
||||||
|
1. **macOS Version:**
|
||||||
|
```bash
|
||||||
|
sw_vers # On both Macs
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **iCloud Account:**
|
||||||
|
- Verify both Macs use same iCloud account
|
||||||
|
- Check System Settings → Apple ID
|
||||||
|
|
||||||
|
3. **System Settings:**
|
||||||
|
- Compare AirDrop & Handoff settings
|
||||||
|
- Compare Firewall settings
|
||||||
|
- Compare Bluetooth/Wi-Fi settings
|
||||||
|
|
||||||
|
4. **Network:**
|
||||||
|
- Are both Macs on same network?
|
||||||
|
- Any VPN differences?
|
||||||
|
|
||||||
|
## Quick Fix Script
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# Quick fix for iPhone Mirroring issues
|
||||||
|
|
||||||
|
echo "Resetting Continuity services..."
|
||||||
|
killall sharingd 2>/dev/null
|
||||||
|
killall bluetoothd 2>/dev/null
|
||||||
|
|
||||||
|
echo "Restarting Bluetooth..."
|
||||||
|
sudo launchctl stop com.apple.bluetoothd 2>/dev/null
|
||||||
|
sudo launchctl start com.apple.bluetoothd 2>/dev/null
|
||||||
|
|
||||||
|
echo "Checking Handoff settings..."
|
||||||
|
defaults read com.apple.coreservices.useractivityd.plist ActivityAdvertisingAllowed
|
||||||
|
defaults read com.apple.coreservices.useractivityd.plist ActivityReceivingAllowed
|
||||||
|
|
||||||
|
echo "Done. Please restart your Mac and try again."
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- iPhone Mirroring requires **macOS Sequoia 15.0+** and **iOS 18.0+**
|
||||||
|
- Both devices must be on same Wi-Fi network (or have Wi-Fi enabled even if using cellular)
|
||||||
|
- Bluetooth must be enabled on both devices (used for proximity detection)
|
||||||
|
- Same iCloud account is **required** (not just signed in, but same account)
|
||||||
|
- Some corporate networks block device-to-device communication
|
||||||
|
- VPNs can interfere with Continuity features
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
# iPhone Proxy Setup Guide
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
- ✅ Tailscale installed and connected on iPhone
|
||||||
|
- ✅ server2 proxy running at `100.70.115.1`
|
||||||
|
|
||||||
|
## Option 1: System-Wide Proxy (Limited Support)
|
||||||
|
|
||||||
|
iOS has limited system-wide proxy support. This works for some apps but not all browsers.
|
||||||
|
|
||||||
|
### Steps:
|
||||||
|
1. Open **Settings** → **Wi-Fi**
|
||||||
|
2. Tap the **ⓘ** icon next to your connected Wi-Fi network
|
||||||
|
3. Scroll down to **HTTP Proxy**
|
||||||
|
4. Select **Manual**
|
||||||
|
5. Configure:
|
||||||
|
- **Server:** `100.70.115.1`
|
||||||
|
- **Port:** `7890` (HTTP) or `7892` (Mixed)
|
||||||
|
- **Authentication:** Off
|
||||||
|
6. Save
|
||||||
|
|
||||||
|
**Note:** This only works when connected to that specific Wi-Fi network. It won't work on cellular or other Wi-Fi networks.
|
||||||
|
|
||||||
|
## Option 2: Proxy App (Recommended)
|
||||||
|
|
||||||
|
**⚠️ Important: VPN Conflict Solution**
|
||||||
|
|
||||||
|
iOS only allows **one VPN connection** at a time. Since Tailscale uses VPN mode, you have two options:
|
||||||
|
|
||||||
|
### Solution A: Use Shadowrocket in Proxy Mode (Recommended)
|
||||||
|
|
||||||
|
Shadowrocket can work **WITH Tailscale** if configured correctly:
|
||||||
|
|
||||||
|
1. **Keep Tailscale ON** (for network access)
|
||||||
|
2. Install **Shadowrocket** from App Store
|
||||||
|
3. Open Shadowrocket
|
||||||
|
4. Tap **+** (Add Server)
|
||||||
|
5. Select **HTTP** (not VPN mode)
|
||||||
|
6. Configure:
|
||||||
|
- **Type:** HTTP
|
||||||
|
- **Address:** `100.70.115.1` (Tailscale IP)
|
||||||
|
- **Port:** `7890`
|
||||||
|
- **Name:** server2-proxy
|
||||||
|
7. Tap **Done**
|
||||||
|
8. **Important:** In Shadowrocket settings:
|
||||||
|
- Go to **Settings** → **Proxy**
|
||||||
|
- Enable **"Use Proxy"** but **DO NOT enable VPN mode**
|
||||||
|
- Or use **"Proxy" mode** instead of **"VPN" mode**
|
||||||
|
9. Enable the proxy
|
||||||
|
|
||||||
|
**How it works:** Shadowrocket routes traffic through the proxy, but uses Tailscale's VPN connection to reach the proxy server. Both work together!
|
||||||
|
|
||||||
|
### Solution B: Use Shadowrocket VPN Mode (Disable Tailscale)
|
||||||
|
|
||||||
|
If you need Shadowrocket's VPN mode:
|
||||||
|
1. **Disable Tailscale** temporarily
|
||||||
|
2. Use Shadowrocket in VPN mode
|
||||||
|
3. Shadowrocket will handle both VPN and proxy routing
|
||||||
|
|
||||||
|
**Note:** You'll lose direct Tailscale network access, but can still reach server2 via proxy.
|
||||||
|
|
||||||
|
### Surge (Paid, ~$10)
|
||||||
|
Similar setup process - supports more advanced features.
|
||||||
|
|
||||||
|
### Potatso Lite (Free)
|
||||||
|
1. Install **Potatso Lite**
|
||||||
|
2. Add proxy with same settings
|
||||||
|
|
||||||
|
## Option 3: Safari Browser Extension
|
||||||
|
|
||||||
|
Some browsers support proxy extensions, but iOS Safari doesn't support system proxies well.
|
||||||
|
|
||||||
|
## Option 4: Clash Client for iOS
|
||||||
|
|
||||||
|
If you want to use Clash directly on iPhone:
|
||||||
|
|
||||||
|
### Clash Meta for iOS (Stash)
|
||||||
|
1. Install **Stash** from App Store (or use TestFlight)
|
||||||
|
2. Add your server2 as an HTTP proxy
|
||||||
|
3. Configure routing rules
|
||||||
|
|
||||||
|
## Quick Test
|
||||||
|
|
||||||
|
After setup, test if proxy is working:
|
||||||
|
|
||||||
|
1. Open Safari or your browser
|
||||||
|
2. Visit: https://api.ipify.org
|
||||||
|
3. It should show server2's IP: `158.101.140.85` (not your iPhone's IP)
|
||||||
|
|
||||||
|
Or visit: http://100.70.115.1:9090/ui to see Clash dashboard
|
||||||
|
|
||||||
|
## Recommended Setup
|
||||||
|
|
||||||
|
**Best Solution: Use Both Together**
|
||||||
|
- **Keep Tailscale ON** (for network connectivity)
|
||||||
|
- Use **Shadowrocket in Proxy mode** (not VPN mode)
|
||||||
|
- Configure HTTP proxy: `100.70.115.1:7890`
|
||||||
|
- Shadowrocket will route through Tailscale's connection
|
||||||
|
- Works on both Wi-Fi and cellular
|
||||||
|
|
||||||
|
**Alternative: Use Shadowrocket VPN Mode**
|
||||||
|
- Disable Tailscale when using Shadowrocket VPN mode
|
||||||
|
- Shadowrocket handles both VPN and proxy
|
||||||
|
- You'll need to manually switch between them
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### VPN Conflict?
|
||||||
|
- **If both Tailscale and Shadowrocket show VPN icons:** You can only have one active
|
||||||
|
- **Solution:** Use Shadowrocket in **Proxy mode** (not VPN mode) while Tailscale is active
|
||||||
|
- **Or:** Disable Tailscale and use Shadowrocket VPN mode
|
||||||
|
|
||||||
|
### Can't connect?
|
||||||
|
1. Verify Tailscale is connected on iPhone (needed to reach `100.70.115.1`)
|
||||||
|
2. Check Tailscale status: Open Tailscale app, verify you see "oracle-tokyo" device
|
||||||
|
3. Test connection: Open Safari, visit `http://100.70.115.1:9090/ui`
|
||||||
|
4. If dashboard loads, proxy is reachable via Tailscale
|
||||||
|
|
||||||
|
### Proxy not working?
|
||||||
|
1. Check if proxy app is enabled/running
|
||||||
|
2. Verify server2 is online: `ssh server2 'sudo systemctl status clash-meta'`
|
||||||
|
3. Try different port: 7890 (HTTP), 7891 (SOCKS5), or 7892 (Mixed)
|
||||||
|
4. Make sure Tailscale is connected (required to reach the proxy server)
|
||||||
|
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# SSH Tunnel Workaround for iPhone Proxy
|
||||||
|
|
||||||
|
## The Problem
|
||||||
|
Oracle Cloud Security List blocks proxy ports, and you don't have console access right now.
|
||||||
|
|
||||||
|
## Solution: SSH Tunnel via Your Mac
|
||||||
|
|
||||||
|
Since SSH (port 22) is already open, we can use it to tunnel proxy traffic!
|
||||||
|
|
||||||
|
### Step 1: Create SSH Tunnel on Your Mac
|
||||||
|
|
||||||
|
Open Terminal on your Mac and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -L 7890:127.0.0.1:7890 -N server2
|
||||||
|
```
|
||||||
|
|
||||||
|
Or run in background:
|
||||||
|
```bash
|
||||||
|
ssh -f -N -L 7890:127.0.0.1:7890 server2
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a tunnel: `Your Mac:7890` → `SSH` → `server2:7890`
|
||||||
|
|
||||||
|
### Step 2: Configure iPhone to Use Your Mac as Proxy
|
||||||
|
|
||||||
|
**Option A: If Mac and iPhone on Same Wi-Fi**
|
||||||
|
|
||||||
|
1. **On your Mac:**
|
||||||
|
- System Settings → Network → Wi-Fi → Details → TCP/IP
|
||||||
|
- Note your Mac's local IP (e.g., `192.168.1.100`)
|
||||||
|
|
||||||
|
2. **On iPhone:**
|
||||||
|
- Settings → Wi-Fi → ⓘ (next to your Wi-Fi network)
|
||||||
|
- Scroll to **HTTP Proxy** → **Manual**
|
||||||
|
- **Server:** `192.168.1.100` (your Mac's IP)
|
||||||
|
- **Port:** `7890`
|
||||||
|
- **Authentication:** Off (SSH tunnel doesn't need it, but Clash does)
|
||||||
|
|
||||||
|
**Wait - this won't work because Clash needs authentication...**
|
||||||
|
|
||||||
|
### Better Solution: Use SOCKS Proxy Over SSH
|
||||||
|
|
||||||
|
Actually, SSH can create a SOCKS proxy directly!
|
||||||
|
|
||||||
|
### Step 3: Use SSH SOCKS Proxy (Better Method)
|
||||||
|
|
||||||
|
**On your Mac, run:**
|
||||||
|
```bash
|
||||||
|
ssh -D 1080 -N server2
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates a SOCKS5 proxy on your Mac at `127.0.0.1:1080`
|
||||||
|
|
||||||
|
**Then on iPhone (same Wi-Fi):**
|
||||||
|
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
||||||
|
- **Server:** `192.168.1.100` (your Mac's IP)
|
||||||
|
- **Port:** `1080`
|
||||||
|
- **Type:** SOCKS5 (if option available)
|
||||||
|
|
||||||
|
**But iOS HTTP Proxy doesn't support SOCKS5...**
|
||||||
|
|
||||||
|
### Best Workaround: Use a Proxy App on Mac
|
||||||
|
|
||||||
|
Install a local proxy server on your Mac that:
|
||||||
|
1. Connects to server2 via SSH tunnel
|
||||||
|
2. Provides HTTP proxy for iPhone
|
||||||
|
|
||||||
|
### Alternative: Use Tailscale (If Available)
|
||||||
|
|
||||||
|
If you can use Tailscale:
|
||||||
|
1. Enable Tailscale VPN on iPhone
|
||||||
|
2. Configure Shadowrocket to use: `100.70.115.1:7890`
|
||||||
|
3. This bypasses Oracle Cloud firewall
|
||||||
|
|
||||||
|
### Simplest Workaround: Keep SSH Tunnel + Use Mac as Bridge
|
||||||
|
|
||||||
|
1. **On Mac:** Create SSH tunnel to server2's Clash
|
||||||
|
2. **On Mac:** Run a local proxy server that iPhone can connect to
|
||||||
|
3. **On iPhone:** Connect to Mac's proxy
|
||||||
|
|
||||||
|
Let me create a script for this...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Executable
+125
@@ -0,0 +1,125 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Move Small Files Test - Start with smallest files first
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Move Small Files Test ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
NAS_PATH="/Volumes/Download/temp documents from MAc"
|
||||||
|
DOCS_PATH="$HOME/Documents"
|
||||||
|
|
||||||
|
# Check NAS is mounted
|
||||||
|
if [ ! -d "$NAS_PATH" ]; then
|
||||||
|
echo "⚠️ NAS not mounted at: $NAS_PATH"
|
||||||
|
echo " Please check your mount point"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check current space
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo "Current free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create destination
|
||||||
|
mkdir -p "$NAS_PATH/Documents"
|
||||||
|
|
||||||
|
echo "🔍 Finding smallest folders/files to move first..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get list sorted by size (smallest first)
|
||||||
|
du -h -d 1 "$DOCS_PATH" 2>/dev/null | sort -h | while read size item; do
|
||||||
|
# Skip the total line
|
||||||
|
if [ "$item" = "$DOCS_PATH" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
FOLDER_NAME=$(basename "$item")
|
||||||
|
|
||||||
|
# Skip if it's not a directory
|
||||||
|
if [ ! -d "$item" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show what we found
|
||||||
|
echo "Found: $FOLDER_NAME ($size)"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📦 Moving smallest items first (under 1GB)..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
MOVED_COUNT=0
|
||||||
|
|
||||||
|
# Move items under 1GB first
|
||||||
|
du -h -d 1 "$DOCS_PATH" 2>/dev/null | sort -h | while read size item; do
|
||||||
|
# Skip the total line
|
||||||
|
if [ "$item" = "$DOCS_PATH" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Skip if not a directory
|
||||||
|
if [ ! -d "$item" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
FOLDER_NAME=$(basename "$item")
|
||||||
|
|
||||||
|
# Check if size is under 1GB (look for M or K, not G)
|
||||||
|
if echo "$size" | grep -qE "[0-9]+[MK]"; then
|
||||||
|
echo "Moving: $FOLDER_NAME ($size)..."
|
||||||
|
|
||||||
|
if mv -v "$item" "$NAS_PATH/Documents/" 2>&1 | tail -3; then
|
||||||
|
echo " ✅ Successfully moved"
|
||||||
|
MOVED_COUNT=$((MOVED_COUNT + 1))
|
||||||
|
|
||||||
|
# Show progress
|
||||||
|
REMAINING=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
||||||
|
MOVED=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
||||||
|
FREE_NOW=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_NOW_GB=$(echo "scale=2; $FREE_NOW / 1024 / 1024" | bc)
|
||||||
|
|
||||||
|
echo " Progress: $MOVED on NAS, $REMAINING remaining"
|
||||||
|
echo " Free space: ${FREE_NOW_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Ask to continue after a few moves
|
||||||
|
if [ $MOVED_COUNT -ge 3 ]; then
|
||||||
|
read -p " Continue with more small files? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo " Stopped. Run again to continue."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
MOVED_COUNT=0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ⚠️ Error moving $FOLDER_NAME"
|
||||||
|
echo " Continuing with next..."
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Summary:"
|
||||||
|
REMAINING=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
||||||
|
MOVED=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
||||||
|
FREE_NOW=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_NOW_GB=$(echo "scale=2; $FREE_NOW / 1024 / 1024" | bc)
|
||||||
|
|
||||||
|
echo " Moved to NAS: $MOVED"
|
||||||
|
echo " Remaining: $REMAINING"
|
||||||
|
echo " Free space now: ${FREE_NOW_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$REMAINING" != "0B" ] && [ -n "$REMAINING" ]; then
|
||||||
|
echo "✅ Test successful! You can now:"
|
||||||
|
echo " 1. Run this script again to move more small files"
|
||||||
|
echo " 2. Or move larger files manually"
|
||||||
|
echo " 3. Or use: ./safe_move_documents.sh for automated chunked moves"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
# Oracle Cloud Console - Open Proxy Ports
|
||||||
|
|
||||||
|
## Step-by-Step Instructions
|
||||||
|
|
||||||
|
### Step 1: Find Your VCN
|
||||||
|
From the screenshot, you have multiple VCNs. We need to find which one your server2 instance uses.
|
||||||
|
|
||||||
|
**Option A: Check from server2**
|
||||||
|
```bash
|
||||||
|
ssh server2 'ip addr show ens3 | grep "inet "'
|
||||||
|
```
|
||||||
|
This will show the IP (e.g., 10.0.0.100), which matches VCN CIDR 10.0.0.0/16.
|
||||||
|
|
||||||
|
**Option B: Check instance details**
|
||||||
|
- Go to **Compute** → **Instances**
|
||||||
|
- Find your server2 instance
|
||||||
|
- Click on it
|
||||||
|
- Check the **VCN** or **Subnet** it's attached to
|
||||||
|
|
||||||
|
### Step 2: Open the VCN
|
||||||
|
1. Click on the **VCN name** (e.g., "vcn-20250609-0221") that matches your instance
|
||||||
|
2. This opens the VCN details page
|
||||||
|
|
||||||
|
### Step 3: Navigate to Security Lists
|
||||||
|
1. In the VCN details page, look for **"Security Lists"** in the left sidebar or Resources section
|
||||||
|
2. Click on **"Security Lists"**
|
||||||
|
3. You'll see a list of security lists (usually "Default Security List for vcn-...")
|
||||||
|
|
||||||
|
### Step 4: Edit the Security List
|
||||||
|
1. Click on the **Default Security List** (or the one attached to your subnet)
|
||||||
|
2. Click **"Edit All Rules"** or **"Add Ingress Rules"**
|
||||||
|
|
||||||
|
### Step 5: Add Ingress Rules
|
||||||
|
Add these 4 rules (one for each port):
|
||||||
|
|
||||||
|
**Rule 1: HTTP Proxy (7890)**
|
||||||
|
- **Source Type:** CIDR
|
||||||
|
- **Source CIDR:** `0.0.0.0/0` (or your IP for better security)
|
||||||
|
- **IP Protocol:** TCP
|
||||||
|
- **Destination Port Range:** `7890`
|
||||||
|
- **Description:** `Clash HTTP Proxy`
|
||||||
|
|
||||||
|
**Rule 2: SOCKS5 Proxy (7891)**
|
||||||
|
- **Source Type:** CIDR
|
||||||
|
- **Source CIDR:** `0.0.0.0/0`
|
||||||
|
- **IP Protocol:** TCP
|
||||||
|
- **Destination Port Range:** `7891`
|
||||||
|
- **Description:** `Clash SOCKS5 Proxy`
|
||||||
|
|
||||||
|
**Rule 3: Mixed Proxy (7892)**
|
||||||
|
- **Source Type:** CIDR
|
||||||
|
- **Source CIDR:** `0.0.0.0/0`
|
||||||
|
- **IP Protocol:** TCP
|
||||||
|
- **Destination Port Range:** `7892`
|
||||||
|
- **Description:** `Clash Mixed Proxy`
|
||||||
|
|
||||||
|
**Rule 4: Web UI (9090)**
|
||||||
|
- **Source Type:** CIDR
|
||||||
|
- **Source CIDR:** `0.0.0.0/0`
|
||||||
|
- **IP Protocol:** TCP
|
||||||
|
- **Destination Port Range:** `9090`
|
||||||
|
- **Description:** `Clash Web UI`
|
||||||
|
|
||||||
|
### Step 6: Save
|
||||||
|
1. Click **"Save Changes"** or **"Add Ingress Rules"**
|
||||||
|
2. Wait 30-60 seconds for rules to propagate
|
||||||
|
|
||||||
|
### Step 7: Test
|
||||||
|
After adding rules, test from your iPhone:
|
||||||
|
- Open Shadowrocket
|
||||||
|
- Add server: `158.101.140.85:7890`
|
||||||
|
- Username: `proxy_user`
|
||||||
|
- Password: `Cs7yBx1Rh9oK`
|
||||||
|
- Test connection
|
||||||
|
|
||||||
|
## Security Note
|
||||||
|
|
||||||
|
Using `0.0.0.0/0` allows access from anywhere. For better security:
|
||||||
|
- Use your home IP: `YOUR_IP/32`
|
||||||
|
- Or use a VPN IP range
|
||||||
|
- The proxy has authentication, so it's somewhat protected
|
||||||
|
|
||||||
|
## Quick Navigation Path
|
||||||
|
|
||||||
|
1. **Networking** → **Virtual Cloud Networks**
|
||||||
|
2. Click your VCN (the one with 10.0.0.0/16)
|
||||||
|
3. **Security Lists** (left sidebar or Resources)
|
||||||
|
4. Click **Default Security List**
|
||||||
|
5. **Add Ingress Rules**
|
||||||
|
6. Add 4 rules (ports 7890, 7891, 7892, 9090)
|
||||||
|
7. **Save**
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Can't find Security Lists?**
|
||||||
|
- Make sure you're in the VCN details page
|
||||||
|
- Look in the left sidebar under "Resources"
|
||||||
|
- Or check the "Resources" tab in the main content area
|
||||||
|
|
||||||
|
**Rules not working?**
|
||||||
|
- Wait 1-2 minutes for propagation
|
||||||
|
- Check that you added rules to the correct Security List
|
||||||
|
- Verify the Security List is attached to your subnet
|
||||||
|
- Check instance's subnet assignment
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+128
@@ -0,0 +1,128 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Safe Move Documents - Move in smaller chunks to avoid getting stuck
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Safe Move Documents ==="
|
||||||
|
echo ""
|
||||||
|
echo "Moving large folders can get stuck. This script moves in smaller chunks."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
NAS_PATH="/Volumes/Download/temp documents from MAc"
|
||||||
|
DOCS_PATH="$HOME/Documents"
|
||||||
|
|
||||||
|
# Check if NAS is mounted
|
||||||
|
if [ ! -d "$NAS_PATH" ]; then
|
||||||
|
echo "⚠️ NAS path not found: $NAS_PATH"
|
||||||
|
echo ""
|
||||||
|
echo "Please check your NAS mount point:"
|
||||||
|
ls -la /Volumes/ | grep -i "download\|ds224"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "📊 Current Status:"
|
||||||
|
DOCS_SIZE=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Documents size: $DOCS_SIZE"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check what's already moved
|
||||||
|
if [ -d "$NAS_PATH/Documents" ]; then
|
||||||
|
MOVED_SIZE=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Already on NAS: $MOVED_SIZE"
|
||||||
|
echo ""
|
||||||
|
echo " ⚠️ Documents folder already exists on NAS!"
|
||||||
|
echo " The previous move may have partially completed."
|
||||||
|
echo ""
|
||||||
|
read -p " Continue moving remaining files? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🔍 Analyzing Documents folder..."
|
||||||
|
echo " Finding largest subfolders to move first..."
|
||||||
|
du -h -d 1 "$DOCS_PATH" 2>/dev/null | sort -hr | head -10
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📦 Strategy: Move in smaller chunks"
|
||||||
|
echo ""
|
||||||
|
echo "This will:"
|
||||||
|
echo " 1. Move largest subfolders one at a time"
|
||||||
|
echo " 2. Show progress after each move"
|
||||||
|
echo " 3. Allow you to stop if needed"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Proceed with chunked move? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create destination
|
||||||
|
mkdir -p "$NAS_PATH/Documents"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🚚 Moving in chunks..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get list of subfolders, sorted by size
|
||||||
|
du -h -d 1 "$DOCS_PATH" 2>/dev/null | sort -hr | while read size folder; do
|
||||||
|
# Skip the total line
|
||||||
|
if [ "$folder" = "$DOCS_PATH" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
FOLDER_NAME=$(basename "$folder")
|
||||||
|
|
||||||
|
# Skip if it's a file (not a directory)
|
||||||
|
if [ ! -d "$folder" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Moving: $FOLDER_NAME ($size)..."
|
||||||
|
|
||||||
|
# Move with verbose output
|
||||||
|
if mv -v "$folder" "$NAS_PATH/Documents/" 2>&1 | head -5; then
|
||||||
|
echo " ✅ Moved successfully"
|
||||||
|
else
|
||||||
|
echo " ⚠️ Error moving $FOLDER_NAME"
|
||||||
|
echo " Continuing with next folder..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Show progress
|
||||||
|
REMAINING=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
||||||
|
MOVED=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Progress: $MOVED moved, $REMAINING remaining"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Ask to continue after each large folder
|
||||||
|
if echo "$size" | grep -qE "[0-9]+G"; then
|
||||||
|
read -p " Continue? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo " Stopped. You can resume later."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 Final Status:"
|
||||||
|
REMAINING=$(du -sh "$DOCS_PATH" 2>/dev/null | awk '{print $1}')
|
||||||
|
MOVED=$(du -sh "$NAS_PATH/Documents" 2>/dev/null | awk '{print $1}')
|
||||||
|
echo " Moved to NAS: $MOVED"
|
||||||
|
echo " Remaining: $REMAINING"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$REMAINING" != "0B" ] && [ -n "$REMAINING" ]; then
|
||||||
|
echo "⚠️ Some files remain. You can:"
|
||||||
|
echo " 1. Run this script again to continue"
|
||||||
|
echo " 2. Manually move remaining files"
|
||||||
|
echo " 3. Leave them if they're small"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
Executable
+222
@@ -0,0 +1,222 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Setup Clash Meta proxy server on server2
|
||||||
|
# Clash Meta is more actively maintained than original Clash
|
||||||
|
|
||||||
|
echo "=== Setting up Clash Meta proxy server on server2 ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
ssh server2 << 'EOF'
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Get Tailscale IP
|
||||||
|
TAILSCALE_IP=$(tailscale ip -4)
|
||||||
|
echo "Tailscale IP: $TAILSCALE_IP"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Detect architecture
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
case $ARCH in
|
||||||
|
x86_64) CLASH_ARCH="amd64" ;;
|
||||||
|
aarch64|arm64) CLASH_ARCH="arm64" ;;
|
||||||
|
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Create directories
|
||||||
|
CLASH_DIR="$HOME/clash-meta"
|
||||||
|
mkdir -p "$CLASH_DIR"
|
||||||
|
mkdir -p ~/.config/clash-meta
|
||||||
|
cd "$CLASH_DIR"
|
||||||
|
|
||||||
|
# Download Clash Meta
|
||||||
|
echo "Downloading Clash Meta..."
|
||||||
|
CLASH_VERSION="v1.18.0"
|
||||||
|
CLASH_FILE="clash.meta-linux-${CLASH_ARCH}-${CLASH_VERSION}"
|
||||||
|
|
||||||
|
if wget -q "https://github.com/MetaCubeX/mihomo/releases/download/${CLASH_VERSION}/${CLASH_FILE}.gz" -O clash.gz; then
|
||||||
|
gunzip -f clash.gz
|
||||||
|
mv "$CLASH_FILE" clash
|
||||||
|
chmod +x clash
|
||||||
|
echo "✓ Clash Meta downloaded"
|
||||||
|
else
|
||||||
|
echo "Failed to download Clash Meta. Trying alternative method..."
|
||||||
|
# Try downloading from release page
|
||||||
|
wget -q "https://github.com/MetaCubeX/mihomo/releases/latest/download/mihomo-linux-${CLASH_ARCH}.gz" -O clash.gz 2>/dev/null || \
|
||||||
|
wget -q "https://github.com/MetaCubeX/mihomo/releases/download/v1.18.0/mihomo-linux-${CLASH_ARCH}.gz" -O clash.gz
|
||||||
|
gunzip -f clash.gz
|
||||||
|
mv mihomo-linux-${CLASH_ARCH} clash 2>/dev/null || mv mihomo clash
|
||||||
|
chmod +x clash
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify installation
|
||||||
|
if [ -f ./clash ]; then
|
||||||
|
./clash -v || echo "Clash binary ready"
|
||||||
|
else
|
||||||
|
echo "✗ Clash binary not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create Clash configuration
|
||||||
|
echo "Creating configuration..."
|
||||||
|
cat > ~/.config/clash-meta/config.yaml << CONFIG
|
||||||
|
# Clash Meta configuration for server2 proxy
|
||||||
|
port: 7890
|
||||||
|
socks-port: 7891
|
||||||
|
mixed-port: 7892
|
||||||
|
allow-lan: true
|
||||||
|
bind-address: '*'
|
||||||
|
mode: rule
|
||||||
|
log-level: info
|
||||||
|
ipv6: false
|
||||||
|
external-controller: 0.0.0.0:9090
|
||||||
|
external-ui: ui
|
||||||
|
|
||||||
|
# DNS
|
||||||
|
dns:
|
||||||
|
enable: true
|
||||||
|
listen: 0.0.0.0:53
|
||||||
|
enhanced-mode: fake-ip
|
||||||
|
fake-ip-range: 198.18.0.1/16
|
||||||
|
nameserver:
|
||||||
|
- 8.8.8.8
|
||||||
|
- 1.1.1.1
|
||||||
|
fallback:
|
||||||
|
- 8.8.4.4
|
||||||
|
- 1.0.0.1
|
||||||
|
fallback-filter:
|
||||||
|
geoip: true
|
||||||
|
geoip-code: CN
|
||||||
|
ipcidr:
|
||||||
|
- 240.0.0.0/4
|
||||||
|
|
||||||
|
# Proxy (direct connection)
|
||||||
|
proxies:
|
||||||
|
- name: "direct"
|
||||||
|
type: direct
|
||||||
|
|
||||||
|
# Proxy groups
|
||||||
|
proxy-groups:
|
||||||
|
- name: "Proxy"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- direct
|
||||||
|
- name: "Auto"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- direct
|
||||||
|
|
||||||
|
# Rules - route all traffic through direct connection
|
||||||
|
rules:
|
||||||
|
- MATCH,Proxy
|
||||||
|
|
||||||
|
# Experimental
|
||||||
|
experimental:
|
||||||
|
ignore-resolve-fail: true
|
||||||
|
sniff-tls-sni: true
|
||||||
|
CONFIG
|
||||||
|
|
||||||
|
# Download Clash dashboard UI
|
||||||
|
echo "Downloading Clash UI..."
|
||||||
|
cd ~/.config/clash-meta
|
||||||
|
if [ ! -d ui ]; then
|
||||||
|
wget -q https://github.com/haishanh/yacd/archive/gh-pages.zip -O ui.zip 2>/dev/null || \
|
||||||
|
wget -q https://github.com/haishanh/yacd/releases/latest/download/yacd.tar.xz -O yacd.tar.xz 2>/dev/null
|
||||||
|
if [ -f yacd.tar.xz ]; then
|
||||||
|
tar -xf yacd.tar.xz
|
||||||
|
mv public ui
|
||||||
|
rm yacd.tar.xz
|
||||||
|
elif [ -f ui.zip ]; then
|
||||||
|
unzip -q ui.zip
|
||||||
|
mv yacd-gh-pages ui
|
||||||
|
rm ui.zip
|
||||||
|
else
|
||||||
|
echo "UI download failed, but Clash will work without it"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create systemd service
|
||||||
|
echo "Creating systemd service..."
|
||||||
|
sudo tee /etc/systemd/system/clash-meta.service > /dev/null << SERVICE
|
||||||
|
[Unit]
|
||||||
|
Description=Clash Meta daemon
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Restart=always
|
||||||
|
User=$USER
|
||||||
|
WorkingDirectory=$CLASH_DIR
|
||||||
|
ExecStart=$CLASH_DIR/clash -d $HOME/.config/clash-meta
|
||||||
|
Environment="HOME=$HOME"
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
SERVICE
|
||||||
|
|
||||||
|
# Reload systemd and start Clash
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable clash-meta
|
||||||
|
sudo systemctl restart clash-meta
|
||||||
|
|
||||||
|
# Wait for service to start
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
if sudo systemctl is-active --quiet clash-meta; then
|
||||||
|
echo ""
|
||||||
|
echo "✓ Clash Meta is running!"
|
||||||
|
echo ""
|
||||||
|
echo "=== Configuration Summary ==="
|
||||||
|
echo "HTTP Proxy: $TAILSCALE_IP:7890"
|
||||||
|
echo "SOCKS5 Proxy: $TAILSCALE_IP:7891"
|
||||||
|
echo "Mixed Proxy (HTTP+SOCKS5): $TAILSCALE_IP:7892"
|
||||||
|
echo "Web UI: http://$TAILSCALE_IP:9090/ui"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Configure firewall
|
||||||
|
echo "=== Firewall Configuration ==="
|
||||||
|
if command -v ufw >/dev/null 2>&1 && sudo ufw status | grep -q "Status: active"; then
|
||||||
|
echo "Configuring UFW..."
|
||||||
|
sudo ufw allow 7890/tcp comment "Clash HTTP"
|
||||||
|
sudo ufw allow 7891/tcp comment "Clash SOCKS5"
|
||||||
|
sudo ufw allow 7892/tcp comment "Clash Mixed"
|
||||||
|
sudo ufw allow 9090/tcp comment "Clash Web UI"
|
||||||
|
sudo ufw allow 53/udp comment "Clash DNS"
|
||||||
|
else
|
||||||
|
echo "UFW not active. If using iptables, ensure ports 7890, 7891, 7892, 9090, 53 are open."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Client Configuration ==="
|
||||||
|
echo "For Clash clients, configure:"
|
||||||
|
echo " Type: HTTP"
|
||||||
|
echo " Server: $TAILSCALE_IP"
|
||||||
|
echo " Port: 7890"
|
||||||
|
echo ""
|
||||||
|
echo "Or use Mixed port (supports both HTTP and SOCKS5):"
|
||||||
|
echo " Server: $TAILSCALE_IP"
|
||||||
|
echo " Port: 7892"
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "✗ Clash Meta failed to start"
|
||||||
|
echo "Check logs: sudo journalctl -u clash-meta -n 50"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Setup Complete ==="
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " Status: ssh server2 'sudo systemctl status clash-meta'"
|
||||||
|
echo " Logs: ssh server2 'sudo journalctl -u clash-meta -f'"
|
||||||
|
echo " Restart: ssh server2 'sudo systemctl restart clash-meta'"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+176
@@ -0,0 +1,176 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Setup Clash proxy server on server2
|
||||||
|
# This will install Clash and configure it to work with Tailscale
|
||||||
|
|
||||||
|
echo "=== Setting up Clash proxy server on server2 ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
ssh server2 << 'EOF'
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Get Tailscale IP
|
||||||
|
TAILSCALE_IP=$(tailscale ip -4)
|
||||||
|
echo "Tailscale IP: $TAILSCALE_IP"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Create clash directory
|
||||||
|
CLASH_DIR="$HOME/clash"
|
||||||
|
mkdir -p "$CLASH_DIR"
|
||||||
|
cd "$CLASH_DIR"
|
||||||
|
|
||||||
|
# Download Clash (latest version)
|
||||||
|
echo "Downloading Clash..."
|
||||||
|
CLASH_VERSION="v1.20.0"
|
||||||
|
ARCH="amd64"
|
||||||
|
if [ "$(uname -m)" = "aarch64" ] || [ "$(uname -m)" = "arm64" ]; then
|
||||||
|
ARCH="arm64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
wget -q "https://github.com/Dreamacro/clash/releases/download/${CLASH_VERSION}/clash-linux-${ARCH}-${CLASH_VERSION}.gz" -O clash.gz
|
||||||
|
gunzip -f clash.gz
|
||||||
|
chmod +x clash
|
||||||
|
|
||||||
|
# Create config directory
|
||||||
|
mkdir -p ~/.config/clash
|
||||||
|
|
||||||
|
# Create Clash configuration file
|
||||||
|
cat > ~/.config/clash/config.yaml << CONFIG
|
||||||
|
# Clash configuration for server2 proxy
|
||||||
|
port: 7890
|
||||||
|
socks-port: 7891
|
||||||
|
allow-lan: true
|
||||||
|
bind-address: '*'
|
||||||
|
mode: rule
|
||||||
|
log-level: info
|
||||||
|
external-controller: 0.0.0.0:9090
|
||||||
|
external-ui: /root/.config/clash/ui
|
||||||
|
|
||||||
|
# DNS
|
||||||
|
dns:
|
||||||
|
enable: true
|
||||||
|
listen: 0.0.0.0:53
|
||||||
|
enhanced-mode: fake-ip
|
||||||
|
nameserver:
|
||||||
|
- 8.8.8.8
|
||||||
|
- 1.1.1.1
|
||||||
|
fallback:
|
||||||
|
- 8.8.4.4
|
||||||
|
- 1.0.0.1
|
||||||
|
|
||||||
|
# Proxy (direct connection - no upstream proxy needed)
|
||||||
|
proxies:
|
||||||
|
- name: "direct"
|
||||||
|
type: direct
|
||||||
|
|
||||||
|
# Proxy groups
|
||||||
|
proxy-groups:
|
||||||
|
- name: "Proxy"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- direct
|
||||||
|
- name: "Auto"
|
||||||
|
type: select
|
||||||
|
proxies:
|
||||||
|
- direct
|
||||||
|
|
||||||
|
# Rules - route all traffic through direct connection
|
||||||
|
rules:
|
||||||
|
- MATCH,Proxy
|
||||||
|
|
||||||
|
# Experimental features
|
||||||
|
experimental:
|
||||||
|
ignore-resolve-fail: true
|
||||||
|
CONFIG
|
||||||
|
|
||||||
|
# Download Clash dashboard UI (optional but useful)
|
||||||
|
echo "Downloading Clash UI..."
|
||||||
|
if [ ! -d ~/.config/clash/ui ]; then
|
||||||
|
cd ~/.config/clash
|
||||||
|
wget -q https://github.com/haishanh/yacd/releases/latest/download/yacd.tar.xz -O yacd.tar.xz
|
||||||
|
tar -xf yacd.tar.xz
|
||||||
|
mv public ui
|
||||||
|
rm yacd.tar.xz
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create systemd service
|
||||||
|
echo "Creating systemd service..."
|
||||||
|
sudo tee /etc/systemd/system/clash.service > /dev/null << SERVICE
|
||||||
|
[Unit]
|
||||||
|
Description=Clash daemon
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Restart=always
|
||||||
|
User=$USER
|
||||||
|
ExecStart=$CLASH_DIR/clash -d $HOME/.config/clash
|
||||||
|
Environment="HOME=$HOME"
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
SERVICE
|
||||||
|
|
||||||
|
# Reload systemd and start Clash
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable clash
|
||||||
|
sudo systemctl restart clash
|
||||||
|
|
||||||
|
# Wait a moment for service to start
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
if sudo systemctl is-active --quiet clash; then
|
||||||
|
echo ""
|
||||||
|
echo "✓ Clash is running!"
|
||||||
|
echo ""
|
||||||
|
echo "=== Configuration Summary ==="
|
||||||
|
echo "HTTP Proxy: $TAILSCALE_IP:7890"
|
||||||
|
echo "SOCKS5 Proxy: $TAILSCALE_IP:7891"
|
||||||
|
echo "Web UI: http://$TAILSCALE_IP:9090/ui"
|
||||||
|
echo ""
|
||||||
|
echo "=== Firewall Configuration ==="
|
||||||
|
echo "Checking firewall rules..."
|
||||||
|
|
||||||
|
# Check if ufw is active
|
||||||
|
if sudo ufw status | grep -q "Status: active"; then
|
||||||
|
echo "UFW is active. Adding rules..."
|
||||||
|
sudo ufw allow 7890/tcp comment "Clash HTTP"
|
||||||
|
sudo ufw allow 7891/tcp comment "Clash SOCKS5"
|
||||||
|
sudo ufw allow 9090/tcp comment "Clash Web UI"
|
||||||
|
sudo ufw allow 53/udp comment "Clash DNS"
|
||||||
|
else
|
||||||
|
echo "UFW is not active. If using iptables, you may need to add rules manually."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Client Configuration ==="
|
||||||
|
echo "For Clash clients, use this proxy:"
|
||||||
|
echo " Type: HTTP"
|
||||||
|
echo " Server: $TAILSCALE_IP"
|
||||||
|
echo " Port: 7890"
|
||||||
|
echo ""
|
||||||
|
echo "Or SOCKS5:"
|
||||||
|
echo " Type: SOCKS5"
|
||||||
|
echo " Server: $TAILSCALE_IP"
|
||||||
|
echo " Port: 7891"
|
||||||
|
else
|
||||||
|
echo "✗ Clash failed to start. Check logs with: sudo journalctl -u clash -n 50"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Setup Complete ==="
|
||||||
|
echo ""
|
||||||
|
echo "To check Clash status: ssh server2 'sudo systemctl status clash'"
|
||||||
|
echo "To view logs: ssh server2 'sudo journalctl -u clash -f'"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+40
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Setup Mac as Proxy Bridge for iPhone
|
||||||
|
# This script sets up a local proxy on Mac that tunnels to server2
|
||||||
|
|
||||||
|
echo "=== Mac Proxy Bridge Setup ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if Python is available (for simple HTTP proxy)
|
||||||
|
if command -v python3 &> /dev/null; then
|
||||||
|
echo "Python3 found - creating simple proxy bridge..."
|
||||||
|
echo ""
|
||||||
|
echo "Run this command to start the bridge:"
|
||||||
|
echo ""
|
||||||
|
echo "python3 -m http.server 8080 &"
|
||||||
|
echo "ssh -L 7890:127.0.0.1:7890 -N server2 &"
|
||||||
|
echo ""
|
||||||
|
echo "But we need a proper HTTP proxy, not just a web server..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Better: Use socat or create a proper proxy
|
||||||
|
if command -v socat &> /dev/null; then
|
||||||
|
echo "socat found - can create proxy bridge"
|
||||||
|
echo ""
|
||||||
|
echo "Run:"
|
||||||
|
echo "ssh -L 7890:127.0.0.1:7890 -N server2 &"
|
||||||
|
echo "socat TCP-LISTEN:8080,fork,reuseaddr TCP:127.0.0.1:7890 &"
|
||||||
|
else
|
||||||
|
echo "Installing socat for proxy bridging..."
|
||||||
|
echo "brew install socat"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Alternative: Use SSH Dynamic Port Forwarding ==="
|
||||||
|
echo ""
|
||||||
|
echo "Run this on your Mac:"
|
||||||
|
echo "ssh -D 1080 -N server2"
|
||||||
|
echo ""
|
||||||
|
echo "This creates a SOCKS5 proxy on localhost:1080"
|
||||||
|
echo "But iPhone HTTP Proxy doesn't support SOCKS5 directly..."
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
# Shadowrocket Setup for Cellular Data
|
||||||
|
|
||||||
|
## The Solution
|
||||||
|
|
||||||
|
Since iOS doesn't support HTTP proxy for cellular data, you need to use **Shadowrocket VPN mode**. Here's how:
|
||||||
|
|
||||||
|
## Setup Steps
|
||||||
|
|
||||||
|
### Step 1: Configure Server (Already Done ✅)
|
||||||
|
- Clash now listens on all interfaces
|
||||||
|
- Firewall allows Tailscale network (100.x.x.x) only
|
||||||
|
- Proxy accessible at: `100.70.115.1:7890`
|
||||||
|
|
||||||
|
### Step 2: On Your iPhone
|
||||||
|
|
||||||
|
**Option A: Use Shadowrocket VPN Mode (Recommended for Cellular)**
|
||||||
|
|
||||||
|
1. **Disable Tailscale VPN:**
|
||||||
|
- Open Tailscale app
|
||||||
|
- Toggle VPN OFF (but keep app installed/running)
|
||||||
|
- This frees up the VPN slot for Shadowrocket
|
||||||
|
|
||||||
|
2. **Configure Shadowrocket:**
|
||||||
|
- Open Shadowrocket
|
||||||
|
- Go to **Home** tab
|
||||||
|
- Tap **"+"** to add server
|
||||||
|
- Select **HTTP**
|
||||||
|
- Enter:
|
||||||
|
- **Address:** `100.70.115.1`
|
||||||
|
- **Port:** `7890`
|
||||||
|
- **Remark:** `server2-proxy`
|
||||||
|
- Tap **Done**
|
||||||
|
|
||||||
|
3. **Enable Shadowrocket:**
|
||||||
|
- Select `server2-proxy` in Home tab
|
||||||
|
- Toggle switch **ON**
|
||||||
|
- VPN icon should appear in status bar
|
||||||
|
|
||||||
|
4. **Test:**
|
||||||
|
- Open Safari
|
||||||
|
- Visit: https://api.ipify.org
|
||||||
|
- Should show: `158.101.140.85` (server2's IP)
|
||||||
|
- Works on both Wi-Fi and cellular! ✅
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
- Shadowrocket creates a VPN connection
|
||||||
|
- It routes all traffic (Wi-Fi + cellular) through the proxy
|
||||||
|
- Traffic goes: iPhone → Shadowrocket VPN → Tailscale network → server2 proxy → Internet
|
||||||
|
|
||||||
|
**Note:** You'll lose direct Tailscale network access (can't SSH to other Tailscale devices), but proxy will work on both Wi-Fi and cellular.
|
||||||
|
|
||||||
|
### Option B: Keep Tailscale VPN, Use System Proxy (Wi-Fi Only)
|
||||||
|
|
||||||
|
If you need Tailscale network access:
|
||||||
|
|
||||||
|
1. **Keep Tailscale VPN ON**
|
||||||
|
2. **Don't use Shadowrocket VPN mode**
|
||||||
|
3. Configure system proxy for Wi-Fi:
|
||||||
|
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
||||||
|
- Server: `100.70.115.1`
|
||||||
|
- Port: `7890`
|
||||||
|
4. **Cellular won't work** with this method (iOS limitation)
|
||||||
|
|
||||||
|
## Recommendation
|
||||||
|
|
||||||
|
**Use Option A (Shadowrocket VPN mode)** if you:
|
||||||
|
- Need proxy on cellular data
|
||||||
|
- Don't need direct Tailscale network access while using proxy
|
||||||
|
- Want it to work everywhere
|
||||||
|
|
||||||
|
**Use Option B (System proxy)** if you:
|
||||||
|
- Only need proxy on Wi-Fi
|
||||||
|
- Need direct Tailscale network access
|
||||||
|
- Can live without cellular proxy
|
||||||
|
|
||||||
|
## Switching Between Modes
|
||||||
|
|
||||||
|
You can easily switch:
|
||||||
|
- **Need proxy on cellular?** → Disable Tailscale VPN, enable Shadowrocket VPN
|
||||||
|
- **Need Tailscale network?** → Disable Shadowrocket VPN, enable Tailscale VPN
|
||||||
|
- **Need both?** → Use system proxy on Wi-Fi (but no cellular proxy)
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
After setup:
|
||||||
|
1. Turn OFF Wi-Fi (use cellular only)
|
||||||
|
2. Open Safari
|
||||||
|
3. Visit: https://api.ipify.org
|
||||||
|
4. Should show server2's IP: `158.101.140.85`
|
||||||
|
5. If it shows your cellular IP, proxy isn't working
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Proxy not working on cellular?**
|
||||||
|
- Make sure Shadowrocket VPN is enabled (VPN icon in status bar)
|
||||||
|
- Check that server2 is online: `ssh server2 'sudo systemctl status clash-meta'`
|
||||||
|
- Verify Tailscale network is reachable (even with VPN off, the network should exist)
|
||||||
|
|
||||||
|
**Can't reach other Tailscale devices?**
|
||||||
|
- That's expected when Shadowrocket VPN is on
|
||||||
|
- Disable Shadowrocket VPN and enable Tailscale VPN when you need direct access
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
# Shadowrocket Correct Setup - Working with Tailscale
|
||||||
|
|
||||||
|
## Understanding Shadowrocket Architecture
|
||||||
|
|
||||||
|
Shadowrocket works as a **local proxy server** on your iPhone:
|
||||||
|
- Apps connect to Shadowrocket's local proxy (127.0.0.1:80)
|
||||||
|
- Shadowrocket forwards traffic to your configured server (server2)
|
||||||
|
- This way it doesn't need VPN mode!
|
||||||
|
|
||||||
|
## Step-by-Step Setup
|
||||||
|
|
||||||
|
### Step 1: Add Server2 as a Server (NOT in Proxy Settings)
|
||||||
|
|
||||||
|
1. Open Shadowrocket app
|
||||||
|
2. Go to the **"Home"** tab (house icon at bottom)
|
||||||
|
3. Tap the **"+"** button in the top right corner
|
||||||
|
4. Select **"HTTP"** or **"HTTPS"**
|
||||||
|
5. Fill in:
|
||||||
|
- **Remark:** `server2-proxy`
|
||||||
|
- **Address:** `100.70.115.1` (your Tailscale IP)
|
||||||
|
- **Port:** `7890` (HTTP) or `7892` (Mixed)
|
||||||
|
- **Username:** (leave empty)
|
||||||
|
- **Password:** (leave empty)
|
||||||
|
6. Tap **"Done"**
|
||||||
|
|
||||||
|
### Step 2: Enable the Server
|
||||||
|
|
||||||
|
1. Go back to **"Home"** tab
|
||||||
|
2. You should see `server2-proxy` in the server list
|
||||||
|
3. Tap on it to select it
|
||||||
|
4. Toggle the switch at the top to **ON**
|
||||||
|
|
||||||
|
### Step 3: Configure Proxy Settings (What You Saw)
|
||||||
|
|
||||||
|
The "Proxy Settings" you saw (127.0.0.1:80) is Shadowrocket's **local proxy** that apps connect to. You can configure it:
|
||||||
|
|
||||||
|
1. Go to **"Settings"** tab (gear icon)
|
||||||
|
2. Tap **"Proxy"**
|
||||||
|
3. In **"Proxy Settings"** section:
|
||||||
|
- **Proxy Type:** HTTP (or leave as is)
|
||||||
|
- **Proxy Port:** `80` (or any port, this is local)
|
||||||
|
- **Proxy Address:** `127.0.0.1` (localhost - this is correct)
|
||||||
|
|
||||||
|
**Important:** These settings are for Shadowrocket's LOCAL proxy. Your apps will connect to this, and Shadowrocket will forward to server2.
|
||||||
|
|
||||||
|
### Step 4: Configure Apps to Use Shadowrocket's Local Proxy
|
||||||
|
|
||||||
|
Now you need to tell your apps to use Shadowrocket's local proxy:
|
||||||
|
|
||||||
|
**Option A: System-Wide (Limited)**
|
||||||
|
1. Settings → Wi-Fi
|
||||||
|
2. Tap ⓘ next to your Wi-Fi
|
||||||
|
3. Scroll to **HTTP Proxy**
|
||||||
|
4. Select **Manual**
|
||||||
|
5. Enter:
|
||||||
|
- **Server:** `127.0.0.1` (or `localhost`)
|
||||||
|
- **Port:** `80` (or whatever you set in Proxy Settings)
|
||||||
|
6. Save
|
||||||
|
|
||||||
|
**Option B: Use Shadowrocket's VPN Mode (But Configured Correctly)**
|
||||||
|
|
||||||
|
Actually, Shadowrocket's "VPN mode" is how it intercepts traffic. Here's the trick:
|
||||||
|
|
||||||
|
1. In Shadowrocket **"Home"** tab
|
||||||
|
2. Make sure your `server2-proxy` is selected
|
||||||
|
3. Toggle the switch ON
|
||||||
|
4. **This will create a VPN connection** BUT it's Shadowrocket's VPN, not a conflict
|
||||||
|
5. Shadowrocket's VPN intercepts traffic and routes it through server2
|
||||||
|
|
||||||
|
**The key:** Shadowrocket's VPN mode is fine - it's a different VPN than Tailscale. However, iOS only allows ONE VPN at a time, so:
|
||||||
|
|
||||||
|
### Solution: Use Shadowrocket's VPN Mode (Disable Tailscale VPN)
|
||||||
|
|
||||||
|
Since iOS only allows one VPN:
|
||||||
|
1. **Disable Tailscale's VPN mode** (but keep Tailscale app running for network access)
|
||||||
|
2. **Enable Shadowrocket's VPN mode**
|
||||||
|
3. Shadowrocket will route through Tailscale's network to reach server2
|
||||||
|
|
||||||
|
Wait - that won't work because Tailscale needs VPN mode to provide network access...
|
||||||
|
|
||||||
|
### Better Solution: Use Proxy Chain Feature
|
||||||
|
|
||||||
|
Looking at your screenshot, I see **"Proxy Chain"** option! This might be the solution:
|
||||||
|
|
||||||
|
1. Go to **Settings** → **Proxy Chain**
|
||||||
|
2. Enable **"Enable Chain"** toggle
|
||||||
|
3. Configure:
|
||||||
|
- **Type:** HTTP
|
||||||
|
- **Address:** `100.70.115.1`
|
||||||
|
- **Port:** `7890`
|
||||||
|
4. This might allow Shadowrocket to use Tailscale's network without VPN conflict
|
||||||
|
|
||||||
|
## Recommended Approach
|
||||||
|
|
||||||
|
Based on your screenshots, here's what to do:
|
||||||
|
|
||||||
|
### Method 1: Use Proxy Chain (Try This First)
|
||||||
|
|
||||||
|
1. **Keep Tailscale VPN ON**
|
||||||
|
2. In Shadowrocket:
|
||||||
|
- Go to **Settings** → **Proxy Chain**
|
||||||
|
- Enable **"Enable Chain"**
|
||||||
|
- Set Type: HTTP, Address: `100.70.115.1`, Port: `7890`
|
||||||
|
3. In Shadowrocket **Home** tab:
|
||||||
|
- Add a "Direct" or "Reject" server (or use existing)
|
||||||
|
- Enable Shadowrocket
|
||||||
|
4. Configure apps to use Shadowrocket's local proxy (127.0.0.1:80)
|
||||||
|
|
||||||
|
### Method 2: Use Shadowrocket VPN Mode (Disable Tailscale)
|
||||||
|
|
||||||
|
1. **Disable Tailscale VPN** (but app can stay installed)
|
||||||
|
2. In Shadowrocket **Home** tab:
|
||||||
|
- Add server2: `100.70.115.1:7890`
|
||||||
|
- Enable Shadowrocket VPN mode
|
||||||
|
3. Shadowrocket will handle routing
|
||||||
|
|
||||||
|
**Problem:** You'll lose direct Tailscale network access, but proxy will work.
|
||||||
|
|
||||||
|
### Method 3: Use System Proxy Settings
|
||||||
|
|
||||||
|
1. Keep Tailscale ON
|
||||||
|
2. Don't use Shadowrocket VPN mode
|
||||||
|
3. Configure system proxy:
|
||||||
|
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
||||||
|
- Server: `100.70.115.1`
|
||||||
|
- Port: `7890`
|
||||||
|
4. This works for some apps but not all
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
After setup:
|
||||||
|
1. Open Safari
|
||||||
|
2. Visit: https://api.ipify.org
|
||||||
|
3. Should show: `158.101.140.85` (server2's IP)
|
||||||
|
|
||||||
|
## Which Method Should You Use?
|
||||||
|
|
||||||
|
**Try Proxy Chain first** - it might allow both Tailscale and Shadowrocket to work together!
|
||||||
|
|
||||||
|
If that doesn't work, you'll need to choose:
|
||||||
|
- **Tailscale VPN** = Direct network access, but no proxy
|
||||||
|
- **Shadowrocket VPN** = Proxy works, but no direct Tailscale network
|
||||||
|
|
||||||
|
Let me know which method works for you!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
# Shadowrocket Proxy Mode Setup Guide
|
||||||
|
|
||||||
|
## Understanding Shadowrocket Modes
|
||||||
|
|
||||||
|
Shadowrocket has two main modes:
|
||||||
|
1. **VPN Mode (TUN Mode)** - Creates a VPN connection (conflicts with Tailscale)
|
||||||
|
2. **Proxy Mode** - Routes traffic through proxy without VPN (works with Tailscale) ✅ **Use This!**
|
||||||
|
|
||||||
|
## Reference Article
|
||||||
|
For additional details, see: https://privateproxy.me/blog/how-to-use-proxies-with-shadowrocket/
|
||||||
|
|
||||||
|
## Step-by-Step: Enable Proxy Mode
|
||||||
|
|
||||||
|
### Step 1: Install Shadowrocket
|
||||||
|
- Download from App Store (~$3)
|
||||||
|
- Open the app
|
||||||
|
|
||||||
|
### Step 2: Add Your Proxy Server
|
||||||
|
|
||||||
|
1. Open Shadowrocket app
|
||||||
|
2. Tap the **"+"** button in the top right corner
|
||||||
|
3. You'll see different server types - select **"HTTP"** or **"HTTPS"**
|
||||||
|
|
||||||
|
### Step 3: Configure Proxy Settings
|
||||||
|
|
||||||
|
Fill in the details:
|
||||||
|
- **Type:** HTTP (or HTTPS)
|
||||||
|
- **Remark:** `server2-proxy` (or any name you prefer)
|
||||||
|
- **Address:** `100.70.115.1` (your Tailscale IP)
|
||||||
|
- **Port:** `7890` (HTTP) or `7892` (Mixed port)
|
||||||
|
- **Username:** (leave empty)
|
||||||
|
- **Password:** (leave empty)
|
||||||
|
- **Method:** (leave as default)
|
||||||
|
|
||||||
|
4. Tap **"Done"** or **"Save"**
|
||||||
|
|
||||||
|
### Step 4: Enable Proxy Mode (NOT VPN Mode)
|
||||||
|
|
||||||
|
**This is the critical step!**
|
||||||
|
|
||||||
|
1. In Shadowrocket main screen, you'll see your proxy server listed
|
||||||
|
2. Tap on your proxy server to select it
|
||||||
|
3. **Important:** Look for these settings:
|
||||||
|
|
||||||
|
**Option A: Global Routing Mode**
|
||||||
|
- Tap the three dots (⋯) or "Edit" next to your proxy
|
||||||
|
- Look for **"Routing"** or **"Mode"** setting
|
||||||
|
- Select **"Proxy"** or **"Global Proxy"** (NOT "VPN" or "TUN")
|
||||||
|
|
||||||
|
**Option B: Settings Menu**
|
||||||
|
- Go to **Settings** (gear icon at bottom)
|
||||||
|
- Find **"Proxy"** or **"Routing"** section
|
||||||
|
- Enable **"Use Proxy"**
|
||||||
|
- Make sure **"VPN" mode is OFF** or **"TUN" mode is OFF**
|
||||||
|
- Select **"Proxy Mode"** instead
|
||||||
|
|
||||||
|
### Step 5: Enable the Connection
|
||||||
|
|
||||||
|
1. Go back to main screen
|
||||||
|
2. Find the toggle switch at the top
|
||||||
|
3. **Toggle it ON**
|
||||||
|
4. You should see a checkmark next to your proxy server
|
||||||
|
5. **Important:** You should NOT see a VPN icon in status bar (that means VPN mode is active)
|
||||||
|
|
||||||
|
### Step 6: Verify It's Working in Proxy Mode
|
||||||
|
|
||||||
|
**Check for VPN icon:**
|
||||||
|
- ✅ **Correct:** No VPN icon in status bar = Proxy mode active
|
||||||
|
- ❌ **Wrong:** VPN icon appears = VPN mode active (will conflict with Tailscale)
|
||||||
|
|
||||||
|
**Test the connection:**
|
||||||
|
1. Open Safari
|
||||||
|
2. Visit: https://api.ipify.org
|
||||||
|
3. Should show: `158.101.140.85` (server2's IP)
|
||||||
|
|
||||||
|
## Alternative: Using Configuration File
|
||||||
|
|
||||||
|
If the UI is confusing, you can use a config file:
|
||||||
|
|
||||||
|
1. In Shadowrocket, tap **"Config"** tab at bottom
|
||||||
|
2. Tap **"+"** to add new config
|
||||||
|
3. Create a config with:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Shadowrocket Config
|
||||||
|
[Proxy]
|
||||||
|
server2 = http, 100.70.115.1, 7890
|
||||||
|
|
||||||
|
[Rule]
|
||||||
|
FINAL,server2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Problem: VPN icon appears (conflicts with Tailscale)
|
||||||
|
**Solution:**
|
||||||
|
- Go to Settings → Routing
|
||||||
|
- Disable "TUN Mode" or "VPN Mode"
|
||||||
|
- Enable "Proxy Mode" only
|
||||||
|
- Restart Shadowrocket
|
||||||
|
|
||||||
|
### Problem: Can't connect to proxy
|
||||||
|
**Check:**
|
||||||
|
1. Is Tailscale connected? (Required to reach 100.70.115.1)
|
||||||
|
2. Is server2 online? `ssh server2 'sudo systemctl status clash-meta'`
|
||||||
|
3. Try different port: 7890, 7891, or 7892
|
||||||
|
|
||||||
|
### Problem: Some apps don't work
|
||||||
|
**Solution:**
|
||||||
|
- Some iOS apps ignore system proxy
|
||||||
|
- You may need to use Shadowrocket's VPN mode for those apps
|
||||||
|
- But then you'll need to disable Tailscale temporarily
|
||||||
|
|
||||||
|
## Visual Guide Reference
|
||||||
|
|
||||||
|
Look for these in Shadowrocket:
|
||||||
|
- **"Proxy"** or **"HTTP Proxy"** option (use this)
|
||||||
|
- **"TUN"** or **"VPN"** option (avoid this when Tailscale is on)
|
||||||
|
- **"Global Proxy"** or **"Proxy Mode"** (this is what you want)
|
||||||
|
|
||||||
|
## Key Differences
|
||||||
|
|
||||||
|
| Mode | VPN Icon? | Works with Tailscale? | Use Case |
|
||||||
|
|------|-----------|----------------------|----------|
|
||||||
|
| **Proxy Mode** | ❌ No | ✅ Yes | Use this! |
|
||||||
|
| **VPN Mode** | ✅ Yes | ❌ No | Only when Tailscale is off |
|
||||||
|
|
||||||
|
## Quick Checklist
|
||||||
|
|
||||||
|
- [ ] Tailscale is ON and connected
|
||||||
|
- [ ] Added HTTP proxy: `100.70.115.1:7890`
|
||||||
|
- [ ] Enabled "Proxy Mode" (NOT VPN mode)
|
||||||
|
- [ ] Toggle switch is ON
|
||||||
|
- [ ] No VPN icon in status bar
|
||||||
|
- [ ] Test: Visit https://api.ipify.org shows server2 IP
|
||||||
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
# Shadowrocket Setup with Public IP (No Tailscale VPN Needed)
|
||||||
|
|
||||||
|
## ✅ Solution: Proxy Now Accessible via Public IP
|
||||||
|
|
||||||
|
The proxy is now configured to listen on the public IP, so you can use Shadowrocket **without** Tailscale VPN!
|
||||||
|
|
||||||
|
## Setup Steps
|
||||||
|
|
||||||
|
### Step 1: Get Proxy Credentials
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh server2 'cat ~/.clash_credentials.txt'
|
||||||
|
```
|
||||||
|
|
||||||
|
You'll see: `username:password`
|
||||||
|
|
||||||
|
### Step 2: Configure Shadowrocket on iPhone
|
||||||
|
|
||||||
|
1. **Disable Tailscale VPN** (Settings → Tailscale → toggle OFF)
|
||||||
|
- This frees up the VPN slot for Shadowrocket
|
||||||
|
|
||||||
|
2. **Open Shadowrocket**
|
||||||
|
- Go to **Home** tab
|
||||||
|
- Tap **"+"** to add server
|
||||||
|
|
||||||
|
3. **Add HTTP Proxy with Authentication:**
|
||||||
|
- **Type:** HTTP
|
||||||
|
- **Address:** `158.101.140.85` (server2's public IP)
|
||||||
|
- **Port:** `7890` (HTTP) or `7892` (Mixed)
|
||||||
|
- **Username:** (from credentials file)
|
||||||
|
- **Password:** (from credentials file)
|
||||||
|
- **Remark:** `server2-proxy`
|
||||||
|
|
||||||
|
4. **Enable Shadowrocket:**
|
||||||
|
- Select your proxy server
|
||||||
|
- Toggle switch **ON**
|
||||||
|
- VPN icon should appear in status bar
|
||||||
|
|
||||||
|
### Step 3: Test
|
||||||
|
|
||||||
|
1. Turn OFF Wi-Fi (use cellular only)
|
||||||
|
2. Open Safari
|
||||||
|
3. Visit: https://api.ipify.org
|
||||||
|
4. Should show: `158.101.140.85` (server2's IP) ✅
|
||||||
|
|
||||||
|
## Proxy Details
|
||||||
|
|
||||||
|
- **Public IP:** `158.101.140.85`
|
||||||
|
- **Ports:**
|
||||||
|
- `7890` - HTTP
|
||||||
|
- `7891` - SOCKS5
|
||||||
|
- `7892` - Mixed (HTTP + SOCKS5) - **Recommended**
|
||||||
|
- **Authentication:** Required (username/password)
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
✅ **Protected by:**
|
||||||
|
- Username/password authentication
|
||||||
|
- Firewall rules (UFW active)
|
||||||
|
- Only proxy ports exposed (not SSH or other services)
|
||||||
|
|
||||||
|
⚠️ **Considerations:**
|
||||||
|
- Proxy is accessible from public internet
|
||||||
|
- Anyone with credentials can use it
|
||||||
|
- Monitor usage: `ssh server2 'sudo journalctl -u clash-meta -f'`
|
||||||
|
|
||||||
|
## Advantages
|
||||||
|
|
||||||
|
✅ Works on **both Wi-Fi and cellular**
|
||||||
|
✅ **No Tailscale VPN needed** (can keep it off)
|
||||||
|
✅ Shadowrocket VPN mode works independently
|
||||||
|
✅ Simple setup
|
||||||
|
|
||||||
|
## Get Credentials
|
||||||
|
|
||||||
|
Run this command to get your proxy credentials:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh server2 'cat ~/.clash_credentials.txt'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use them in Shadowrocket when adding the proxy server.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Can't connect?**
|
||||||
|
1. Check server2 is online: `ssh server2 'sudo systemctl status clash-meta'`
|
||||||
|
2. Verify credentials are correct
|
||||||
|
3. Try different port: 7890, 7891, or 7892
|
||||||
|
4. Check firewall: `ssh server2 'sudo ufw status'`
|
||||||
|
|
||||||
|
**Proxy slow?**
|
||||||
|
- Normal - traffic goes: iPhone → Internet → server2 → Internet
|
||||||
|
- Depends on server2's connection speed
|
||||||
|
|
||||||
|
## Change Credentials
|
||||||
|
|
||||||
|
If you want to change the password:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh server2 'openssl rand -base64 12'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then update `~/.config/clash-meta/config.yaml` and restart Clash.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
# Simple Workaround: Use Tailscale (Easiest)
|
||||||
|
|
||||||
|
## Quick Solution
|
||||||
|
|
||||||
|
Since you already have Tailscale set up, the **simplest workaround** is:
|
||||||
|
|
||||||
|
### Option 1: Use Tailscale + Shadowrocket (Temporarily)
|
||||||
|
|
||||||
|
1. **On iPhone:**
|
||||||
|
- Enable **Tailscale VPN** (Settings → Tailscale → toggle ON)
|
||||||
|
- Open **Shadowrocket**
|
||||||
|
- Add server: `100.70.115.1:7890`
|
||||||
|
- **Username:** `proxy_user`
|
||||||
|
- **Password:** `Cs7yBx1Rh9oK`
|
||||||
|
- Enable Shadowrocket
|
||||||
|
|
||||||
|
**Problem:** iOS only allows one VPN, so you can't use both...
|
||||||
|
|
||||||
|
### Option 2: Use Tailscale Only (No Shadowrocket)
|
||||||
|
|
||||||
|
1. **On iPhone:**
|
||||||
|
- Enable **Tailscale VPN**
|
||||||
|
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
||||||
|
- **Server:** `100.70.115.1`
|
||||||
|
- **Port:** `7890`
|
||||||
|
- **Authentication:** Username/Password
|
||||||
|
- **Username:** `proxy_user`
|
||||||
|
- **Password:** `Cs7yBx1Rh9oK`
|
||||||
|
|
||||||
|
**Limitation:** Only works on Wi-Fi, not cellular (iOS limitation)
|
||||||
|
|
||||||
|
### Option 3: SSH Tunnel on Mac + Share with iPhone
|
||||||
|
|
||||||
|
**On your Mac:**
|
||||||
|
|
||||||
|
1. **Create SSH tunnel:**
|
||||||
|
```bash
|
||||||
|
ssh -L 7890:127.0.0.1:7890 -N server2
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Install a local proxy bridge** (like `cow` or `polipo`):
|
||||||
|
```bash
|
||||||
|
# Using polipo (if installed)
|
||||||
|
polipo proxyAddress=0.0.0.0 proxyPort=8080 parentProxy=127.0.0.1:7890
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **On iPhone (same Wi-Fi):**
|
||||||
|
- Settings → Wi-Fi → ⓘ → HTTP Proxy → Manual
|
||||||
|
- **Server:** `192.168.1.XXX` (your Mac's IP)
|
||||||
|
- **Port:** `8080`
|
||||||
|
|
||||||
|
### Option 4: Use WireGuard (You Already Have It!)
|
||||||
|
|
||||||
|
You have `wg0` interface on server2! Use WireGuard instead:
|
||||||
|
|
||||||
|
1. **On iPhone:** Install WireGuard app
|
||||||
|
2. **On server2:** Generate WireGuard config
|
||||||
|
3. **Connect via WireGuard** to access `100.70.115.1:7890`
|
||||||
|
|
||||||
|
This works because WireGuard creates a VPN, and you can use Shadowrocket's proxy chain feature.
|
||||||
|
|
||||||
|
## Recommended: Option 2 (Tailscale + System Proxy)
|
||||||
|
|
||||||
|
**Easiest and works now:**
|
||||||
|
|
||||||
|
1. Enable Tailscale VPN on iPhone
|
||||||
|
2. Configure system HTTP proxy:
|
||||||
|
- Server: `100.70.115.1`
|
||||||
|
- Port: `7890`
|
||||||
|
- Username: `proxy_user`
|
||||||
|
- Password: `Cs7yBx1Rh9oK`
|
||||||
|
3. Works on Wi-Fi (cellular won't work, but it's a temporary workaround)
|
||||||
|
|
||||||
|
## When You Get Console Access
|
||||||
|
|
||||||
|
Add Security List rules for ports 7890, 7891, 7892, 9090, then you can use Shadowrocket directly with public IP.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# SSH Tunnel Workaround for Proxy Access
|
||||||
|
# This creates an SSH tunnel to forward proxy traffic through SSH (port 22)
|
||||||
|
|
||||||
|
echo "=== SSH Tunnel Workaround for Clash Proxy ==="
|
||||||
|
echo ""
|
||||||
|
echo "Since Oracle Cloud Security List blocks proxy ports, we'll use SSH port forwarding"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get server details
|
||||||
|
SERVER="server2"
|
||||||
|
PROXY_PORT="7890"
|
||||||
|
LOCAL_PORT="7890"
|
||||||
|
|
||||||
|
echo "Creating SSH tunnel..."
|
||||||
|
echo "Local port: $LOCAL_PORT -> Remote: $SERVER:$PROXY_PORT"
|
||||||
|
echo ""
|
||||||
|
echo "Run this command on your Mac:"
|
||||||
|
echo ""
|
||||||
|
echo "ssh -L $LOCAL_PORT:127.0.0.1:$PROXY_PORT -N $SERVER"
|
||||||
|
echo ""
|
||||||
|
echo "Or for background:"
|
||||||
|
echo "ssh -f -N -L $LOCAL_PORT:127.0.0.1:$PROXY_PORT $SERVER"
|
||||||
|
echo ""
|
||||||
|
echo "Then configure Shadowrocket to use:"
|
||||||
|
echo " Server: 127.0.0.1 (localhost)"
|
||||||
|
echo " Port: $LOCAL_PORT"
|
||||||
|
echo " Username: proxy_user"
|
||||||
|
echo " Password: Cs7yBx1Rh9oK"
|
||||||
|
echo ""
|
||||||
|
echo "Note: This only works when SSH tunnel is active on your Mac"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+45
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Sync projects to server2
|
||||||
|
# Usage: ./sync-to-server.sh [project_name]
|
||||||
|
|
||||||
|
SERVER="server2"
|
||||||
|
REMOTE_PATH="/home/$USER/repos"
|
||||||
|
LOCAL_PATH="/Users/jimmyg/repos"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Starting sync to $SERVER...${NC}"
|
||||||
|
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
# Sync specific project
|
||||||
|
PROJECT="$1"
|
||||||
|
echo -e "${GREEN}Syncing project: $PROJECT${NC}"
|
||||||
|
rsync -avz --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
--exclude='__pycache__/' \
|
||||||
|
--exclude='*.pyc' \
|
||||||
|
--exclude='.DS_Store' \
|
||||||
|
--exclude='*.log' \
|
||||||
|
"$LOCAL_PATH/$PROJECT/" \
|
||||||
|
"$SERVER:$REMOTE_PATH/$PROJECT/"
|
||||||
|
else
|
||||||
|
# Sync all projects
|
||||||
|
echo -e "${GREEN}Syncing all projects${NC}"
|
||||||
|
rsync -avz --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
--exclude='__pycache__/' \
|
||||||
|
--exclude='*.pyc' \
|
||||||
|
--exclude='.DS_Store' \
|
||||||
|
--exclude='*.log' \
|
||||||
|
"$LOCAL_PATH/" \
|
||||||
|
"$SERVER:$REMOTE_PATH/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Sync completed!${NC}"
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
# Synology USB Copy Troubleshooting
|
||||||
|
|
||||||
|
## Issue
|
||||||
|
USB Copy shows "Unavailable" status with message:
|
||||||
|
**"No USB/SD storage mounted to the front port or storage used for another task"**
|
||||||
|
|
||||||
|
## Possible Causes
|
||||||
|
|
||||||
|
### 1. No USB Device Connected
|
||||||
|
- USB/SD card not plugged into the front USB port
|
||||||
|
- USB device not properly connected
|
||||||
|
- USB device not recognized by Synology
|
||||||
|
|
||||||
|
### 2. USB Device Already in Use
|
||||||
|
- USB device mounted for another purpose (file sharing, etc.)
|
||||||
|
- Another USB Copy task using the same device
|
||||||
|
- USB device mounted as a shared folder
|
||||||
|
|
||||||
|
### 3. USB Copy Task Configuration Issue
|
||||||
|
- Task configured but USB device not detected
|
||||||
|
- Wrong USB port selected in task settings
|
||||||
|
- USB device format not supported
|
||||||
|
|
||||||
|
## Solutions
|
||||||
|
|
||||||
|
### Solution 1: Check USB Device Connection
|
||||||
|
|
||||||
|
1. **Physically check:**
|
||||||
|
- Ensure USB device is plugged into the **front USB port** (not rear ports)
|
||||||
|
- Try unplugging and reconnecting
|
||||||
|
- Try a different USB device to test
|
||||||
|
|
||||||
|
2. **Check in DSM:**
|
||||||
|
- Control Panel → External Devices
|
||||||
|
- See if USB device appears in the list
|
||||||
|
- Check if it shows as "Mounted" or "Unmounted"
|
||||||
|
|
||||||
|
### Solution 2: Unmount USB Device from Other Uses
|
||||||
|
|
||||||
|
1. **Check if USB is mounted as shared folder:**
|
||||||
|
- Control Panel → Shared Folder
|
||||||
|
- Look for USB device name
|
||||||
|
- If found, unmount it first
|
||||||
|
|
||||||
|
2. **Check other USB Copy tasks:**
|
||||||
|
- USB Copy → Check all tasks
|
||||||
|
- See if another task is using the USB device
|
||||||
|
- Disable or delete conflicting tasks
|
||||||
|
|
||||||
|
3. **Unmount manually:**
|
||||||
|
- Control Panel → External Devices
|
||||||
|
- Select USB device → Unmount
|
||||||
|
- Then try USB Copy again
|
||||||
|
|
||||||
|
### Solution 3: Check USB Copy Task Settings
|
||||||
|
|
||||||
|
1. **Open USB Copy task:**
|
||||||
|
- USB Copy → Select "Copy Button" task
|
||||||
|
- Go to "Task Settings" tab
|
||||||
|
|
||||||
|
2. **Verify settings:**
|
||||||
|
- Source: Should be [USB] or specific USB device
|
||||||
|
- Destination: Should be valid path
|
||||||
|
- Make sure correct USB port is selected
|
||||||
|
|
||||||
|
3. **Check "Trigger Time" tab:**
|
||||||
|
- Ensure trigger is properly configured
|
||||||
|
- If using "Copy Button" trigger, ensure button is enabled
|
||||||
|
|
||||||
|
### Solution 4: Restart USB Copy Service
|
||||||
|
|
||||||
|
1. **Stop USB Copy:**
|
||||||
|
- Package Center → USB Copy → Stop
|
||||||
|
|
||||||
|
2. **Unmount all USB devices:**
|
||||||
|
- Control Panel → External Devices → Unmount all
|
||||||
|
|
||||||
|
3. **Restart USB Copy:**
|
||||||
|
- Package Center → USB Copy → Start
|
||||||
|
|
||||||
|
4. **Reconnect USB device:**
|
||||||
|
- Plug USB device into front port
|
||||||
|
- Wait for it to be recognized
|
||||||
|
- Try USB Copy again
|
||||||
|
|
||||||
|
### Solution 5: Check USB Device Format
|
||||||
|
|
||||||
|
- **Supported formats:** FAT32, NTFS, exFAT, HFS+, ext4
|
||||||
|
- **Not supported:** Some encrypted formats, certain proprietary formats
|
||||||
|
- Try formatting USB device to FAT32 or exFAT if needed
|
||||||
|
|
||||||
|
## Diagnostic Steps
|
||||||
|
|
||||||
|
1. **Check USB device recognition:**
|
||||||
|
```
|
||||||
|
SSH to NAS → Run: lsusb
|
||||||
|
Or check: Control Panel → External Devices
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check mount status:**
|
||||||
|
```
|
||||||
|
SSH to NAS → Run: mount | grep usb
|
||||||
|
Or check: Control Panel → External Devices → Status
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Check USB Copy logs:**
|
||||||
|
- USB Copy → Settings → View logs
|
||||||
|
- Look for error messages
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### Issue: "Copy Button" Task Shows Unavailable
|
||||||
|
- **Cause:** USB device not detected or already mounted elsewhere
|
||||||
|
- **Fix:** Unmount USB device from other uses, then reconnect
|
||||||
|
|
||||||
|
### Issue: USB Device Not Detected
|
||||||
|
- **Cause:** Wrong port, unsupported format, or hardware issue
|
||||||
|
- **Fix:** Try front port, check format, try different USB device
|
||||||
|
|
||||||
|
### Issue: Task Configured But Won't Run
|
||||||
|
- **Cause:** USB device mounted as shared folder or used by another task
|
||||||
|
- **Fix:** Unmount from shared folders, disable other USB Copy tasks
|
||||||
|
|
||||||
|
## Quick Fix Checklist
|
||||||
|
|
||||||
|
- [ ] USB device plugged into **front USB port**
|
||||||
|
- [ ] USB device appears in Control Panel → External Devices
|
||||||
|
- [ ] USB device is **not** mounted as shared folder
|
||||||
|
- [ ] No other USB Copy tasks using the same device
|
||||||
|
- [ ] USB Copy service is running (Package Center)
|
||||||
|
- [ ] USB device format is supported (FAT32/exFAT/NTFS)
|
||||||
|
- [ ] Try unmounting and reconnecting USB device
|
||||||
|
|
||||||
|
## If Still Not Working
|
||||||
|
|
||||||
|
1. **Check Synology logs:**
|
||||||
|
- Control Panel → Log Center
|
||||||
|
- Look for USB-related errors
|
||||||
|
|
||||||
|
2. **Try different USB device:**
|
||||||
|
- Test if issue is device-specific
|
||||||
|
|
||||||
|
3. **Check Synology model compatibility:**
|
||||||
|
- Some older models have USB Copy limitations
|
||||||
|
- Check Synology documentation for your model
|
||||||
|
|
||||||
|
4. **Contact Synology Support:**
|
||||||
|
- If hardware issue suspected
|
||||||
|
- Provide model number and error details
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# Test Proxy Connection
|
||||||
|
|
||||||
|
## ✅ Security List Rules Added!
|
||||||
|
|
||||||
|
Now let's test if it works.
|
||||||
|
|
||||||
|
## Step 1: Wait for Rules to Propagate
|
||||||
|
Wait 30-60 seconds for Oracle Cloud to apply the rules.
|
||||||
|
|
||||||
|
## Step 2: Test from Your Mac (Quick Test)
|
||||||
|
|
||||||
|
Run this command to test:
|
||||||
|
```bash
|
||||||
|
curl --proxy http://proxy_user:Cs7yBx1Rh9oK@158.101.140.85:7890 http://httpbin.org/ip
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected result:** Should show `{"origin":"158.101.140.85"}`
|
||||||
|
|
||||||
|
If it works, the firewall is open! ✅
|
||||||
|
|
||||||
|
## Step 3: Configure Shadowrocket on iPhone
|
||||||
|
|
||||||
|
1. **Open Shadowrocket**
|
||||||
|
2. **Add Server:**
|
||||||
|
- Tap **"+"** button
|
||||||
|
- Select **HTTP**
|
||||||
|
- **Address:** `158.101.140.85`
|
||||||
|
- **Port:** `7890` (or `7892` for Mixed)
|
||||||
|
- **Username:** `proxy_user`
|
||||||
|
- **Password:** `Cs7yBx1Rh9oK`
|
||||||
|
- **Remark:** `server2-proxy`
|
||||||
|
- Tap **Done**
|
||||||
|
|
||||||
|
3. **Enable Shadowrocket:**
|
||||||
|
- Select your proxy server
|
||||||
|
- Toggle switch **ON**
|
||||||
|
- VPN icon should appear
|
||||||
|
|
||||||
|
4. **Test:**
|
||||||
|
- Open Safari
|
||||||
|
- Visit: https://api.ipify.org
|
||||||
|
- Should show: `158.101.140.85` ✅
|
||||||
|
|
||||||
|
## Step 4: Test on Cellular
|
||||||
|
|
||||||
|
1. Turn OFF Wi-Fi (use cellular only)
|
||||||
|
2. Open Safari
|
||||||
|
3. Visit: https://api.ipify.org
|
||||||
|
4. Should show server2's IP ✅
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Still timing out?**
|
||||||
|
- Wait another 1-2 minutes (rules can take time to propagate)
|
||||||
|
- Check Security List rules are saved
|
||||||
|
- Verify ports: 7890, 7891, 7892, 9090
|
||||||
|
- Try different port: 7892 (Mixed port)
|
||||||
|
|
||||||
|
**Connection works but slow?**
|
||||||
|
- Normal - traffic goes: iPhone → Internet → server2 → Internet
|
||||||
|
- Depends on server2's connection speed
|
||||||
|
|
||||||
|
**Can't connect?**
|
||||||
|
- Check server2 is running: `ssh server2 'sudo systemctl status clash-meta'`
|
||||||
|
- Verify credentials are correct
|
||||||
|
- Check firewall: `ssh server2 'sudo ufw status | grep 7890'`
|
||||||
|
|
||||||
|
## Success Indicators
|
||||||
|
|
||||||
|
✅ Mac test shows server2's IP
|
||||||
|
✅ Shadowrocket connects without timeout
|
||||||
|
✅ Safari shows server2's IP when proxy is on
|
||||||
|
✅ Works on both Wi-Fi and cellular
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
# Time Machine NAS Connection Troubleshooting
|
||||||
|
|
||||||
|
## Issue
|
||||||
|
Time Machine shows "Connecting to backup disk..." but never completes, even though:
|
||||||
|
- ✅ NAS is accessible from Finder
|
||||||
|
- ✅ User `zjgump` is in administrators group (has full permissions)
|
||||||
|
- ✅ Network connectivity is fine (ping works, SMB works in Finder)
|
||||||
|
|
||||||
|
## Root Cause Analysis
|
||||||
|
|
||||||
|
### Key Finding
|
||||||
|
**`zjgump` is in the administrators group** - This means:
|
||||||
|
- Explicit file permissions won't apply to SMB/file protocols
|
||||||
|
- Admin users have full access by default
|
||||||
|
- The "Permission denied" errors are NOT about file permissions
|
||||||
|
|
||||||
|
### Actual Issues
|
||||||
|
1. **Credential Cache Mismatch**: macOS has saved credentials for `DS224plus` (without .local) but Time Machine tries to use `DS224plus.local`
|
||||||
|
2. **Stale Mounts**: Manual mounts interfere with Time Machine's automatic mounting
|
||||||
|
3. **Time Machine Process Permissions**: Time Machine runs as a different user than your login user
|
||||||
|
|
||||||
|
## Solutions
|
||||||
|
|
||||||
|
### Solution 1: Clear Credentials and Let Time Machine Mount Itself (Recommended)
|
||||||
|
|
||||||
|
1. **Unmount all existing mounts:**
|
||||||
|
```bash
|
||||||
|
diskutil unmount "/Volumes/Time Machine Folder" 2>/dev/null
|
||||||
|
sudo umount -f /Volumes/.timemachine/* 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Clear saved credentials:**
|
||||||
|
- Open **Keychain Access**
|
||||||
|
- Search for `DS224plus`
|
||||||
|
- Delete ALL entries related to DS224plus
|
||||||
|
- Also search for `Time Machine` and delete related entries
|
||||||
|
|
||||||
|
3. **Remove Time Machine destination:**
|
||||||
|
- System Settings → General → Time Machine
|
||||||
|
- Remove the existing backup disk (click `-` button)
|
||||||
|
|
||||||
|
4. **Re-add Time Machine:**
|
||||||
|
- Click "Add Backup Disk..."
|
||||||
|
- Select "Time Machine Folder" on "DS224plus.local" (the one with `.local`)
|
||||||
|
- When prompted, enter `zjgump` credentials
|
||||||
|
- **Let Time Machine mount it itself** - don't mount it manually first
|
||||||
|
|
||||||
|
### Solution 2: Use a Dedicated Time Machine User (Best Practice)
|
||||||
|
|
||||||
|
Synology recommends using a **dedicated non-admin user** for Time Machine:
|
||||||
|
|
||||||
|
1. **On Synology DSM:**
|
||||||
|
- Control Panel → User & Group → Create
|
||||||
|
- Create user: `tm-backup` (or similar)
|
||||||
|
- **Do NOT add to administrators group**
|
||||||
|
- Set password
|
||||||
|
|
||||||
|
2. **Grant permissions:**
|
||||||
|
- Control Panel → Shared Folder → Time Machine Folder → Edit → Permissions
|
||||||
|
- Add `tm-backup` user with **Read/Write** permission
|
||||||
|
- Check "Apply to this folder, sub-folders and files"
|
||||||
|
|
||||||
|
3. **Configure Time Machine on NAS:**
|
||||||
|
- Control Panel → File Services → Time Machine
|
||||||
|
- Select "Time Machine Folder" as the shared folder
|
||||||
|
- Select `tm-backup` as the user (or leave blank for all users)
|
||||||
|
|
||||||
|
4. **On macOS:**
|
||||||
|
- Remove existing Time Machine destination
|
||||||
|
- Add Backup Disk → Select "Time Machine Folder – DS224plus.local"
|
||||||
|
- When prompted, use `tm-backup` credentials (not `zjgump`)
|
||||||
|
|
||||||
|
### Solution 3: Fix Credential Cache for Admin User
|
||||||
|
|
||||||
|
If you want to keep using `zjgump` (admin user):
|
||||||
|
|
||||||
|
1. **Clear all DS224plus credentials:**
|
||||||
|
```bash
|
||||||
|
security delete-internet-password -s "DS224plus" 2>/dev/null
|
||||||
|
security delete-internet-password -s "DS224plus.local" 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Remove Time Machine destination**
|
||||||
|
|
||||||
|
3. **Manually connect via Finder first:**
|
||||||
|
- Finder → ⌘K → `smb://DS224plus.local`
|
||||||
|
- Connect as `zjgump`
|
||||||
|
- This will save the credential properly
|
||||||
|
|
||||||
|
4. **Then add Time Machine:**
|
||||||
|
- System Settings → Time Machine → Add Backup Disk
|
||||||
|
- Select "Time Machine Folder – DS224plus.local"
|
||||||
|
- It should use the saved credential
|
||||||
|
|
||||||
|
### Solution 4: Use IP Address Instead of Hostname
|
||||||
|
|
||||||
|
If Bonjour (.local) is causing issues:
|
||||||
|
|
||||||
|
1. **Find NAS IP:**
|
||||||
|
```bash
|
||||||
|
ping -c 1 DS224plus.local | grep PING
|
||||||
|
# Or check your router's DHCP table
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Connect via IP:**
|
||||||
|
- System Settings → Time Machine → Add Backup Disk
|
||||||
|
- If it doesn't show up, manually mount first:
|
||||||
|
- Finder → ⌘K → `smb://192.168.1.172/Time Machine Folder`
|
||||||
|
- Connect as `zjgump`
|
||||||
|
- Then add the mounted share in Time Machine
|
||||||
|
|
||||||
|
## Diagnostic Commands
|
||||||
|
|
||||||
|
### Check Current Mounts
|
||||||
|
```bash
|
||||||
|
mount | grep -i "timemachine\|ds224plus"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Time Machine Logs
|
||||||
|
```bash
|
||||||
|
log show --predicate 'subsystem == "com.apple.TimeMachine"' --last 10m --info | tail -50
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Saved Credentials
|
||||||
|
```bash
|
||||||
|
security find-internet-password -s "DS224plus"
|
||||||
|
security find-internet-password -s "DS224plus.local"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test SMB Connection
|
||||||
|
```bash
|
||||||
|
smbutil status DS224plus.local
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Time Machine Configuration
|
||||||
|
```bash
|
||||||
|
tmutil listbackups
|
||||||
|
defaults read /Library/Preferences/com.apple.TimeMachine
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Errors and Fixes
|
||||||
|
|
||||||
|
### "Time Machine could not back up the disk because it is nearly full"
|
||||||
|
- **Cause**: The **source disk** (Macintosh HD) is nearly full, NOT the destination (NAS)
|
||||||
|
- **Symptoms**: Error says disk is "nearly full" but NAS shows plenty of space (e.g., 1.67TB available)
|
||||||
|
- **Fix**: Free up space on your Mac's internal disk:
|
||||||
|
1. Run the diagnostic script: `./free_disk_space.sh`
|
||||||
|
2. Run the cleanup script: `./fix_time_machine_disk_full.sh`
|
||||||
|
3. Or manually:
|
||||||
|
- Empty Trash: `rm -rf ~/.Trash/*`
|
||||||
|
- Clean caches: `rm -rf ~/Library/Caches/*`
|
||||||
|
- Review Downloads folder (often has large files)
|
||||||
|
- Use macOS Storage Management: Apple Menu → About This Mac → Storage → Manage
|
||||||
|
- **Why**: Time Machine needs free space on the source disk to:
|
||||||
|
- Create local snapshots
|
||||||
|
- Stage files for backup
|
||||||
|
- Maintain the backup process
|
||||||
|
- **Minimum**: Aim for at least 5-10GB free space for Time Machine to work properly
|
||||||
|
|
||||||
|
### "Deleted files but space not freed" / "Stuck Time Machine snapshot"
|
||||||
|
- **Cause**: APFS snapshots (especially Time Machine local snapshots) hold onto deleted file space
|
||||||
|
- **Symptoms**:
|
||||||
|
- Deleted 20GB+ of files but disk space didn't increase
|
||||||
|
- Error: "Stale NFS file handle" when trying to delete snapshots
|
||||||
|
- `tmutil listlocalsnapshots /` shows snapshots that can't be deleted
|
||||||
|
- **Fix**:
|
||||||
|
1. **Quick fix - Restart Mac**: Often the simplest solution - snapshots are released after restart
|
||||||
|
2. **Remove Time Machine destination temporarily**:
|
||||||
|
- System Settings → Time Machine → Remove backup disk
|
||||||
|
- Delete snapshot: `sudo tmutil deletelocalsnapshots <date>`
|
||||||
|
- Re-add Time Machine destination
|
||||||
|
3. **Use the fix script**: `./fix_stuck_snapshot.sh` (guides you through the process)
|
||||||
|
4. **Force purge**: `sudo purge` (if available)
|
||||||
|
- **Why**: Time Machine creates local snapshots before backing up. If the backup destination (NAS) is unreachable or has a stale connection, the snapshot gets stuck and holds onto space from deleted files.
|
||||||
|
- **Prevention**: Ensure Time Machine can reliably connect to backup destination
|
||||||
|
|
||||||
|
### "Permission denied" on mount point
|
||||||
|
- **Cause**: Manual mount with wrong permissions
|
||||||
|
- **Fix**: Unmount and let Time Machine mount it itself
|
||||||
|
|
||||||
|
### "Connecting to backup disk..." hangs
|
||||||
|
- **Cause**: Credential cache mismatch or stale mount
|
||||||
|
- **Fix**: Clear credentials, unmount all, re-add
|
||||||
|
|
||||||
|
### "Server may not exist or unavailable"
|
||||||
|
- **Cause**: Using wrong hostname (DS224plus vs DS224plus.local)
|
||||||
|
- **Fix**: Always use `.local` version or IP address
|
||||||
|
|
||||||
|
## Prevention
|
||||||
|
|
||||||
|
1. **Don't manually mount Time Machine shares** - let Time Machine do it
|
||||||
|
2. **Use dedicated non-admin user** for Time Machine (best practice)
|
||||||
|
3. **Keep credentials in sync** - if you change NAS password, update on Mac
|
||||||
|
4. **Use `.local` hostname** - more reliable than IP or NetBIOS name
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Admin users (`zjgump`) bypass file-level permissions on Synology
|
||||||
|
- Time Machine runs as `_backup` user on macOS, not your login user
|
||||||
|
- Bonjour (`.local`) is preferred over NetBIOS for Time Machine
|
||||||
|
- Manual mounts can interfere with Time Machine's automatic mounting
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# Troubleshooting Proxy Connection Timeout
|
||||||
|
|
||||||
|
## Issue
|
||||||
|
Connection test timeout when connecting to proxy from iPhone/Shadowrocket.
|
||||||
|
|
||||||
|
## Status Check
|
||||||
|
✅ Clash is running
|
||||||
|
✅ Listening on ports 7890, 7891, 7892
|
||||||
|
✅ Local connection works (tested from server2)
|
||||||
|
✅ Authentication configured
|
||||||
|
✅ UFW firewall allows ports
|
||||||
|
|
||||||
|
## Possible Causes
|
||||||
|
|
||||||
|
### 1. Oracle Cloud Security List / Firewall
|
||||||
|
Oracle Cloud has a **Security List** that acts as a firewall. Even if UFW allows the ports, Oracle's firewall might be blocking them.
|
||||||
|
|
||||||
|
**Solution:** Check Oracle Cloud Console:
|
||||||
|
1. Go to Oracle Cloud Console
|
||||||
|
2. Networking → Virtual Cloud Networks
|
||||||
|
3. Find your VCN
|
||||||
|
4. Security Lists → Ingress Rules
|
||||||
|
5. Add rules for ports 7890, 7891, 7892, 9090
|
||||||
|
- Source: 0.0.0.0/0 (or your IP for security)
|
||||||
|
- Protocol: TCP
|
||||||
|
- Port: 7890, 7891, 7892, 9090
|
||||||
|
|
||||||
|
### 2. Network ACL
|
||||||
|
Oracle Cloud also has Network ACLs that might block traffic.
|
||||||
|
|
||||||
|
### 3. IPv6 vs IPv4
|
||||||
|
Clash shows as `tcp6` but `*:7890` means it listens on both IPv4 and IPv6. This should be fine.
|
||||||
|
|
||||||
|
### 4. Connection from iPhone
|
||||||
|
Test from a different network to see if it's network-specific.
|
||||||
|
|
||||||
|
## Quick Tests
|
||||||
|
|
||||||
|
### Test 1: Check if port is reachable
|
||||||
|
```bash
|
||||||
|
# From your Mac (not iPhone)
|
||||||
|
nc -zv 158.101.140.85 7890
|
||||||
|
# or
|
||||||
|
telnet 158.101.140.85 7890
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test 2: Test from server2 itself
|
||||||
|
```bash
|
||||||
|
ssh server2 'curl -v --proxy http://proxy_user:Cs7yBx1Rh9oK@127.0.0.1:7890 http://httpbin.org/ip'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test 3: Check Oracle Cloud Security List
|
||||||
|
- Log into Oracle Cloud Console
|
||||||
|
- Check Security List rules for your instance
|
||||||
|
|
||||||
|
## Most Likely Issue: Oracle Cloud Security List
|
||||||
|
|
||||||
|
Oracle Cloud blocks all incoming traffic by default unless explicitly allowed in the Security List. UFW on the server won't help if Oracle's firewall blocks it first.
|
||||||
|
|
||||||
|
## Solution Steps
|
||||||
|
|
||||||
|
1. **Check Oracle Cloud Console:**
|
||||||
|
- Go to your instance
|
||||||
|
- Click on the VCN/subnet
|
||||||
|
- Security Lists → Ingress Rules
|
||||||
|
- Add rules for ports 7890, 7891, 7892
|
||||||
|
|
||||||
|
2. **Or use Oracle Cloud CLI:**
|
||||||
|
```bash
|
||||||
|
# Add security list rule (example - adjust for your setup)
|
||||||
|
oci network security-list update --security-list-id <your-security-list-id> ...
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Test again from iPhone after adding rules**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+120
@@ -0,0 +1,120 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Use External Drive to Free Space for Update
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== Use External Drive for Update ==="
|
||||||
|
echo ""
|
||||||
|
echo "External drive detected! This is your solution."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Find external drive
|
||||||
|
EXTERNAL_VOLUMES=$(ls -d /Volumes/* 2>/dev/null | grep -v -E "Macintosh|Preboot|Recovery|VM|Download" || echo "")
|
||||||
|
|
||||||
|
if [ -z "$EXTERNAL_VOLUMES" ]; then
|
||||||
|
echo "⚠️ No external volumes found mounted"
|
||||||
|
echo ""
|
||||||
|
echo "Please:"
|
||||||
|
echo " 1. Connect your external USB drive"
|
||||||
|
echo " 2. Wait for it to mount"
|
||||||
|
echo " 3. Run this script again"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Found external volume(s):"
|
||||||
|
echo "$EXTERNAL_VOLUMES" | while read vol; do
|
||||||
|
SIZE=$(df -h "$vol" 2>/dev/null | tail -1 | awk '{print $2}')
|
||||||
|
FREE=$(df -h "$vol" 2>/dev/null | tail -1 | awk '{print $4}')
|
||||||
|
echo " - $vol ($SIZE total, $FREE free)"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Use first external volume
|
||||||
|
EXTERNAL_VOL=$(echo "$EXTERNAL_VOLUMES" | head -1)
|
||||||
|
echo "Using: $EXTERNAL_VOL"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
FREE_SPACE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
FREE_SPACE_GB=$(echo "scale=2; $FREE_SPACE / 1024 / 1024" | bc)
|
||||||
|
echo "Current Mac free space: ${FREE_SPACE_GB}GB"
|
||||||
|
echo "Need: 17.64GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📦 Large files you can move to external drive:"
|
||||||
|
echo ""
|
||||||
|
echo " Downloads: 8.7GB"
|
||||||
|
echo " .ollama: 17GB"
|
||||||
|
echo " .local: 18GB"
|
||||||
|
echo " Total: ~44GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔧 Steps:"
|
||||||
|
echo ""
|
||||||
|
echo "1. Move large files to external drive:"
|
||||||
|
echo " mv ~/Downloads \"$EXTERNAL_VOL/Downloads_backup\""
|
||||||
|
echo " mv ~/.ollama \"$EXTERNAL_VOL/ollama_backup\""
|
||||||
|
echo " mv ~/.local \"$EXTERNAL_VOL/local_backup\""
|
||||||
|
echo ""
|
||||||
|
echo "2. This should free ~44GB on Mac"
|
||||||
|
echo ""
|
||||||
|
echo "3. Install macOS update"
|
||||||
|
echo ""
|
||||||
|
echo "4. After update clears snapshot, move files back"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Move Downloads, .ollama, and .local to external drive? (y/n) " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "Moving files..."
|
||||||
|
|
||||||
|
# Move Downloads
|
||||||
|
if [ -d ~/Downloads ]; then
|
||||||
|
echo "Moving Downloads (8.7GB)..."
|
||||||
|
mv ~/Downloads "$EXTERNAL_VOL/Downloads_backup" && \
|
||||||
|
echo " ✅ Moved Downloads" || \
|
||||||
|
echo " ⚠️ Error moving Downloads"
|
||||||
|
mkdir ~/Downloads
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Move .ollama
|
||||||
|
if [ -d ~/.ollama ]; then
|
||||||
|
echo "Moving .ollama (17GB)..."
|
||||||
|
mv ~/.ollama "$EXTERNAL_VOL/ollama_backup" && \
|
||||||
|
echo " ✅ Moved .ollama" || \
|
||||||
|
echo " ⚠️ Error moving .ollama"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Move .local
|
||||||
|
if [ -d ~/.local ]; then
|
||||||
|
echo "Moving .local (18GB)..."
|
||||||
|
mv ~/.local "$EXTERNAL_VOL/local_backup" && \
|
||||||
|
echo " ✅ Moved .local" || \
|
||||||
|
echo " ⚠️ Error moving .local"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "⏳ Waiting for space to update..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
NEW_FREE=$(df / | tail -1 | awk '{print $4}')
|
||||||
|
NEW_FREE_GB=$(echo "scale=2; $NEW_FREE / 1024 / 1024" | bc)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "New free space: ${NEW_FREE_GB}GB"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if (( $(echo "$NEW_FREE_GB > 17" | bc -l) )); then
|
||||||
|
echo "✅ Enough space! Now install update:"
|
||||||
|
echo " System Settings → General → Software Update"
|
||||||
|
echo " OR"
|
||||||
|
echo " sudo softwareupdate --download --all"
|
||||||
|
else
|
||||||
|
echo "⚠️ Still not enough. May need to move more files."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Cancelled."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# NAS WebDAV External Access Troubleshooting
|
||||||
|
|
||||||
|
This repository contains diagnostic tools and guides to help troubleshoot WebDAV external access issues on NAS systems.
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
WebDAV works on intranet but fails from external networks with "Connection refused" error.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. **Run the diagnostic script on your NAS:**
|
||||||
|
```bash
|
||||||
|
sudo ./diagnose_webdav.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Check port forwarding:**
|
||||||
|
```bash
|
||||||
|
./check_port_forwarding.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Review the troubleshooting guide:**
|
||||||
|
- See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for detailed solutions
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `diagnose_webdav.sh` - Comprehensive diagnostic script to check service binding, firewall, and configuration
|
||||||
|
- `check_port_forwarding.sh` - Tests port accessibility and provides port forwarding checklist
|
||||||
|
- `TROUBLESHOOTING.md` - Detailed troubleshooting guide with common issues and solutions
|
||||||
|
|
||||||
|
## Most Common Issues
|
||||||
|
|
||||||
|
1. **Service bound to localhost only** - Service listens on `127.0.0.1:5006` instead of `0.0.0.0:5006`
|
||||||
|
2. **Firewall blocking port** - Port 5006 not allowed in firewall rules
|
||||||
|
3. **Router port forwarding not configured** - External port 5006 not forwarded to NAS internal IP
|
||||||
|
4. **Router firewall blocking** - Router firewall blocking incoming connections
|
||||||
|
|
||||||
|
## Quick Fix
|
||||||
|
|
||||||
|
The most common fix is ensuring your WebDAV service is bound to all interfaces:
|
||||||
|
|
||||||
|
**Apache:**
|
||||||
|
```apache
|
||||||
|
Listen 0.0.0.0:5006
|
||||||
|
```
|
||||||
|
|
||||||
|
**Nginx:**
|
||||||
|
```nginx
|
||||||
|
listen 0.0.0.0:5006;
|
||||||
|
```
|
||||||
|
|
||||||
|
Then configure router port forwarding: External 5006 → Internal NAS IP:5006
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
All scripts should be run on your NAS system:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Make scripts executable (already done)
|
||||||
|
chmod +x *.sh
|
||||||
|
|
||||||
|
# Run diagnostics
|
||||||
|
sudo ./diagnose_webdav.sh
|
||||||
|
|
||||||
|
# Check port forwarding
|
||||||
|
./check_port_forwarding.sh
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
# WebDAV External Access Troubleshooting Guide
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
WebDAV works on intranet but fails from external networks with "Connection refused" error.
|
||||||
|
|
||||||
|
## Common Causes and Solutions
|
||||||
|
|
||||||
|
### 1. Service Bound to Localhost Only
|
||||||
|
|
||||||
|
**Symptom:** Service only listens on `127.0.0.1` or `::1` instead of all interfaces.
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
- **Apache:** Change `Listen 127.0.0.1:5006` to `Listen 0.0.0.0:5006` or `Listen *:5006`
|
||||||
|
- **Nginx:** Change `listen 127.0.0.1:5006;` to `listen 0.0.0.0:5006;` or `listen *:5006;`
|
||||||
|
- **Other services:** Ensure binding to `0.0.0.0` or `*` instead of `localhost`/`127.0.0.1`
|
||||||
|
|
||||||
|
**Check:**
|
||||||
|
```bash
|
||||||
|
netstat -tuln | grep 5006
|
||||||
|
# or
|
||||||
|
ss -tuln | grep 5006
|
||||||
|
```
|
||||||
|
|
||||||
|
If you see `127.0.0.1:5006` or `::1:5006`, the service is only accessible locally.
|
||||||
|
|
||||||
|
### 2. Firewall Blocking Port 5006
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
|
||||||
|
**UFW (Ubuntu/Debian):**
|
||||||
|
```bash
|
||||||
|
sudo ufw allow 5006/tcp
|
||||||
|
sudo ufw reload
|
||||||
|
```
|
||||||
|
|
||||||
|
**firewalld (CentOS/RHEL):**
|
||||||
|
```bash
|
||||||
|
sudo firewall-cmd --permanent --add-port=5006/tcp
|
||||||
|
sudo firewall-cmd --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
**iptables:**
|
||||||
|
```bash
|
||||||
|
sudo iptables -A INPUT -p tcp --dport 5006 -j ACCEPT
|
||||||
|
sudo iptables-save
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Router Port Forwarding Not Configured
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
1. Access your router's admin panel
|
||||||
|
2. Navigate to Port Forwarding / Virtual Server settings
|
||||||
|
3. Add rule:
|
||||||
|
- **External Port:** 5006
|
||||||
|
- **Internal IP:** Your NAS IP address (e.g., 192.168.1.100)
|
||||||
|
- **Internal Port:** 5006
|
||||||
|
- **Protocol:** TCP
|
||||||
|
4. Save and apply changes
|
||||||
|
|
||||||
|
### 4. Router Firewall Blocking Incoming Connections
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
- Check router firewall settings
|
||||||
|
- Ensure port 5006 is allowed for incoming connections
|
||||||
|
- Some routers have separate WAN firewall rules
|
||||||
|
|
||||||
|
### 5. ISP Blocking Port 5006
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
- Some ISPs block certain ports
|
||||||
|
- Try a different external port (e.g., 5007, 8080)
|
||||||
|
- Update port forwarding to use the new port
|
||||||
|
|
||||||
|
### 6. Service Not Running or Crashed
|
||||||
|
|
||||||
|
**Check service status:**
|
||||||
|
```bash
|
||||||
|
# For systemd services
|
||||||
|
systemctl status webdav
|
||||||
|
# or
|
||||||
|
systemctl status apache2
|
||||||
|
# or
|
||||||
|
systemctl status nginx
|
||||||
|
|
||||||
|
# Check if process is running
|
||||||
|
ps aux | grep -i webdav
|
||||||
|
```
|
||||||
|
|
||||||
|
**Restart service:**
|
||||||
|
```bash
|
||||||
|
sudo systemctl restart webdav
|
||||||
|
# or
|
||||||
|
sudo systemctl restart apache2
|
||||||
|
# or
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. NAS-Specific Configuration
|
||||||
|
|
||||||
|
**Synology NAS:**
|
||||||
|
1. Control Panel → External Access → Router Configuration
|
||||||
|
2. Enable port forwarding for port 5006
|
||||||
|
3. Control Panel → Security → Firewall
|
||||||
|
4. Ensure port 5006 is allowed
|
||||||
|
|
||||||
|
**QNAP NAS:**
|
||||||
|
1. Network & Virtual Switch → Port Forwarding
|
||||||
|
2. Add rule for port 5006
|
||||||
|
3. Security → Firewall → Allow port 5006
|
||||||
|
|
||||||
|
**Other NAS:**
|
||||||
|
- Check NAS admin panel for port forwarding/firewall settings
|
||||||
|
- Ensure WebDAV service is enabled and configured for external access
|
||||||
|
|
||||||
|
## Diagnostic Steps
|
||||||
|
|
||||||
|
1. **Run the diagnostic script:**
|
||||||
|
```bash
|
||||||
|
chmod +x diagnose_webdav.sh
|
||||||
|
sudo ./diagnose_webdav.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Test local connection:**
|
||||||
|
```bash
|
||||||
|
curl -k -X PROPFIND https://localhost:5006
|
||||||
|
# or
|
||||||
|
curl -k -X PROPFIND https://127.0.0.1:5006
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Test from internal network:**
|
||||||
|
```bash
|
||||||
|
curl -k -X PROPFIND https://<NAS_INTERNAL_IP>:5006
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Test from external network:**
|
||||||
|
```bash
|
||||||
|
curl -k -X PROPFIND https://jimmygan.myds.me:5006
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Check if port is reachable externally:**
|
||||||
|
```bash
|
||||||
|
# From external network
|
||||||
|
telnet jimmygan.myds.me 5006
|
||||||
|
# or
|
||||||
|
nc -zv jimmygan.myds.me 5006
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Fix Checklist
|
||||||
|
|
||||||
|
- [ ] Service is bound to `0.0.0.0:5006` (not `127.0.0.1:5006`)
|
||||||
|
- [ ] Firewall allows port 5006
|
||||||
|
- [ ] Router port forwarding configured (External 5006 → Internal NAS IP:5006)
|
||||||
|
- [ ] Router firewall allows incoming connections on port 5006
|
||||||
|
- [ ] WebDAV service is running
|
||||||
|
- [ ] Tested local connection (works)
|
||||||
|
- [ ] Tested internal network connection (works)
|
||||||
|
- [ ] External connection still fails → Check ISP/port blocking
|
||||||
|
|
||||||
|
## Additional Notes
|
||||||
|
|
||||||
|
- **DDNS:** Your domain `jimmygan.myds.me` appears to be a DDNS service. Ensure it's properly configured and pointing to your current external IP.
|
||||||
|
- **HTTPS:** Since you're using HTTPS, ensure SSL certificate is valid and the service is configured for SSL/TLS.
|
||||||
|
- **IPv6:** The error shows IPv6 connection attempts. If your router/NAS doesn't support IPv6 properly, you may need to disable IPv6 or configure it separately.
|
||||||
|
|
||||||
Executable
+118
@@ -0,0 +1,118 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Port Forwarding Test Script
|
||||||
|
# Tests if port 5006 is accessible from external networks
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Port Forwarding Test for WebDAV (Port 5006)"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get external IP
|
||||||
|
echo "1. Checking external IP address..."
|
||||||
|
EXTERNAL_IP=$(curl -s ifconfig.me 2>/dev/null || curl -s icanhazip.com 2>/dev/null)
|
||||||
|
if [ -z "$EXTERNAL_IP" ]; then
|
||||||
|
echo "❌ Unable to determine external IP"
|
||||||
|
else
|
||||||
|
echo "✅ External IP: $EXTERNAL_IP"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get internal IP
|
||||||
|
echo "2. Checking internal IP address..."
|
||||||
|
if command -v ip &> /dev/null; then
|
||||||
|
INTERNAL_IP=$(ip route get 8.8.8.8 2>/dev/null | grep -oP 'src \K\S+' | head -1)
|
||||||
|
elif command -v hostname &> /dev/null; then
|
||||||
|
INTERNAL_IP=$(hostname -I | awk '{print $1}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$INTERNAL_IP" ]; then
|
||||||
|
echo "⚠️ Unable to determine internal IP"
|
||||||
|
else
|
||||||
|
echo "✅ Internal IP: $INTERNAL_IP"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test local port
|
||||||
|
echo "3. Testing local port 5006..."
|
||||||
|
if command -v nc &> /dev/null; then
|
||||||
|
if timeout 2 nc -zv localhost 5006 2>&1 | grep -q "succeeded"; then
|
||||||
|
echo "✅ Port 5006 is open locally"
|
||||||
|
else
|
||||||
|
echo "❌ Port 5006 is NOT open locally"
|
||||||
|
echo " → Service may not be running or bound incorrectly"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "⚠️ netcat not available, skipping local test"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test internal network port
|
||||||
|
if [ -n "$INTERNAL_IP" ]; then
|
||||||
|
echo "4. Testing internal network access..."
|
||||||
|
if command -v nc &> /dev/null; then
|
||||||
|
if timeout 2 nc -zv "$INTERNAL_IP" 5006 2>&1 | grep -q "succeeded"; then
|
||||||
|
echo "✅ Port 5006 accessible from internal network"
|
||||||
|
else
|
||||||
|
echo "❌ Port 5006 NOT accessible from internal network"
|
||||||
|
echo " → Service may be bound to localhost only"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Test external port (if external IP service available)
|
||||||
|
echo "5. Testing external port accessibility..."
|
||||||
|
echo " (This requires an external service - may not work in all environments)"
|
||||||
|
if command -v nc &> /dev/null && [ -n "$EXTERNAL_IP" ]; then
|
||||||
|
echo " Attempting to test from external perspective..."
|
||||||
|
echo " Note: This test may not work if your network blocks outbound connections"
|
||||||
|
echo ""
|
||||||
|
echo " Manual test recommended:"
|
||||||
|
echo " From a device outside your network, run:"
|
||||||
|
echo " telnet $EXTERNAL_IP 5006"
|
||||||
|
echo " or"
|
||||||
|
echo " nc -zv $EXTERNAL_IP 5006"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Port forwarding checklist
|
||||||
|
echo "6. Port Forwarding Configuration Checklist"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
echo "On your router, ensure:"
|
||||||
|
echo ""
|
||||||
|
echo " External Port: 5006"
|
||||||
|
echo " Internal IP: $INTERNAL_IP (your NAS IP)"
|
||||||
|
echo " Internal Port: 5006"
|
||||||
|
echo " Protocol: TCP"
|
||||||
|
echo ""
|
||||||
|
echo " Status: [ ] Configured"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Firewall checklist
|
||||||
|
echo "7. Firewall Configuration Checklist"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
echo "On your NAS/router:"
|
||||||
|
echo " [ ] Port 5006 allowed in firewall"
|
||||||
|
echo " [ ] Incoming connections on port 5006 allowed"
|
||||||
|
echo " [ ] Service bound to 0.0.0.0:5006 (not 127.0.0.1:5006)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Next Steps"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo "If local test fails:"
|
||||||
|
echo " 1. Check if WebDAV service is running"
|
||||||
|
echo " 2. Check service configuration (Listen directive)"
|
||||||
|
echo ""
|
||||||
|
echo "If local test passes but internal fails:"
|
||||||
|
echo " 1. Service is likely bound to localhost only"
|
||||||
|
echo " 2. Change Listen/ServerName to 0.0.0.0:5006"
|
||||||
|
echo ""
|
||||||
|
echo "If internal test passes but external fails:"
|
||||||
|
echo " 1. Check router port forwarding configuration"
|
||||||
|
echo " 2. Check router firewall settings"
|
||||||
|
echo " 3. Verify ISP is not blocking port 5006"
|
||||||
|
echo ""
|
||||||
|
|
||||||
Executable
+142
@@ -0,0 +1,142 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# WebDAV External Access Diagnostic Script
|
||||||
|
# This script helps diagnose why WebDAV is not accessible from external networks
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "WebDAV External Access Diagnostic Tool"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if running as root (needed for some checks)
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "⚠️ Some checks may require root privileges"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1. Check what's listening on port 5006
|
||||||
|
echo "1. Checking what's listening on port 5006..."
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
if command -v netstat &> /dev/null; then
|
||||||
|
echo "Using netstat:"
|
||||||
|
netstat -tuln | grep 5006 || echo "❌ Nothing found listening on port 5006"
|
||||||
|
elif command -v ss &> /dev/null; then
|
||||||
|
echo "Using ss:"
|
||||||
|
ss -tuln | grep 5006 || echo "❌ Nothing found listening on port 5006"
|
||||||
|
else
|
||||||
|
echo "⚠️ netstat or ss not available"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 2. Check if service is bound to localhost only
|
||||||
|
echo "2. Checking if service is bound to localhost only..."
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
if command -v netstat &> /dev/null; then
|
||||||
|
netstat -tuln | grep 5006 | grep "127.0.0.1\|::1" && echo "❌ Service is bound to localhost only!" || echo "✅ Service is not bound to localhost only"
|
||||||
|
elif command -v ss &> /dev/null; then
|
||||||
|
ss -tuln | grep 5006 | grep "127.0.0.1\|::1" && echo "❌ Service is bound to localhost only!" || echo "✅ Service is not bound to localhost only"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 3. Check if port 5006 is open in firewall
|
||||||
|
echo "3. Checking firewall status..."
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
if command -v ufw &> /dev/null; then
|
||||||
|
echo "UFW Status:"
|
||||||
|
ufw status | grep 5006 || echo "⚠️ Port 5006 not found in UFW rules"
|
||||||
|
elif command -v firewall-cmd &> /dev/null; then
|
||||||
|
echo "firewalld Status:"
|
||||||
|
firewall-cmd --list-ports | grep 5006 || echo "⚠️ Port 5006 not found in firewalld rules"
|
||||||
|
elif command -v iptables &> /dev/null; then
|
||||||
|
echo "iptables rules for port 5006:"
|
||||||
|
iptables -L -n | grep 5006 || echo "⚠️ No iptables rules found for port 5006"
|
||||||
|
else
|
||||||
|
echo "⚠️ No common firewall tool detected"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 4. Check WebDAV service status (common services)
|
||||||
|
echo "4. Checking WebDAV service status..."
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
if systemctl list-units --type=service | grep -i webdav &> /dev/null; then
|
||||||
|
systemctl list-units --type=service | grep -i webdav | while read service; do
|
||||||
|
servicename=$(echo $service | awk '{print $1}')
|
||||||
|
echo "Service: $servicename"
|
||||||
|
systemctl status $servicename --no-pager | head -5
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "⚠️ No WebDAV systemd service found"
|
||||||
|
echo "Checking common WebDAV processes:"
|
||||||
|
ps aux | grep -i webdav | grep -v grep || echo "No WebDAV processes found"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 5. Test local connection
|
||||||
|
echo "5. Testing local connection to port 5006..."
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
if command -v nc &> /dev/null; then
|
||||||
|
if nc -zv localhost 5006 2>&1; then
|
||||||
|
echo "✅ Local connection successful"
|
||||||
|
else
|
||||||
|
echo "❌ Local connection failed"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "⚠️ netcat (nc) not available for connection test"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 6. Check network interfaces
|
||||||
|
echo "6. Network interface information..."
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
if command -v ip &> /dev/null; then
|
||||||
|
ip addr show | grep -E "^[0-9]+:|inet " | head -10
|
||||||
|
elif command -v ifconfig &> /dev/null; then
|
||||||
|
ifconfig | grep -E "^[a-z]|inet " | head -10
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 7. Check router/NAT configuration hints
|
||||||
|
echo "7. Router/NAT Configuration Checklist..."
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
echo "Please verify on your router/NAS:"
|
||||||
|
echo " □ Port forwarding: External port 5006 → Internal NAS IP:5006"
|
||||||
|
echo " □ Firewall rules allow incoming connections on port 5006"
|
||||||
|
echo " □ NAT/UPnP is configured correctly"
|
||||||
|
echo " □ External IP matches: $(curl -s ifconfig.me 2>/dev/null || echo 'Unable to determine')"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 8. Common WebDAV configuration files to check
|
||||||
|
echo "8. Common WebDAV configuration locations..."
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
config_locations=(
|
||||||
|
"/etc/apache2/sites-available/*webdav*"
|
||||||
|
"/etc/apache2/conf.d/*webdav*"
|
||||||
|
"/etc/nginx/sites-available/*webdav*"
|
||||||
|
"/etc/nginx/conf.d/*webdav*"
|
||||||
|
"/etc/lighttpd/lighttpd.conf"
|
||||||
|
"/etc/httpd/conf.d/*webdav*"
|
||||||
|
"/usr/local/etc/apache2/*webdav*"
|
||||||
|
)
|
||||||
|
|
||||||
|
for pattern in "${config_locations[@]}"; do
|
||||||
|
for file in $pattern; do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
echo "Found: $file"
|
||||||
|
echo " Checking for Listen/ServerName directives..."
|
||||||
|
grep -E "Listen|ServerName|<VirtualHost|listen" "$file" | head -3 || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "Diagnostic Complete"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo "Common Issues and Solutions:"
|
||||||
|
echo "1. If service is bound to 127.0.0.1: Change Listen directive to 0.0.0.0:5006"
|
||||||
|
echo "2. If firewall blocks port: Open port 5006 in firewall"
|
||||||
|
echo "3. If router blocks: Configure port forwarding for port 5006"
|
||||||
|
echo "4. If service not running: Start the WebDAV service"
|
||||||
|
echo ""
|
||||||
|
|
||||||
Reference in New Issue
Block a user