Created
March 9, 2026 14:10
-
-
Save galinio/03bfc83a50d19b2cb3fb94434b27f937 to your computer and use it in GitHub Desktop.
WordPress cleanup script - remove unused tags, close comments, delete spam, export 404 URLs (WP-CLI)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # ============================================================ | |
| # WordPress Site Cleanup Script | |
| # Run this on your WordPress server to: | |
| # 1. Backup and remove unused tags | |
| # 2. Close comments on all posts and pages | |
| # 3. Disable pingbacks | |
| # 4. Delete spam comments | |
| # 5. Export 404 URLs from Apache logs | |
| # ============================================================ | |
| set -e | |
| # ------- CONFIGURATION (edit these) ------- | |
| WP_PATH="/opt/bitnami/wordpress" | |
| BACKUP_DIR="/tmp/wp-cleanup-$(date +%Y%m%d)" | |
| LOG_DIR="/opt/bitnami/apache/logs" | |
| CONTENT_PATHS="^/(blog|topics|tutorials|devops)" | |
| # ------------------------------------------ | |
| WP="sudo wp --path=$WP_PATH --allow-root" | |
| mkdir -p "$BACKUP_DIR" | |
| echo "" | |
| echo "============================================" | |
| echo " WordPress Cleanup Script" | |
| echo " Backup directory: $BACKUP_DIR" | |
| echo "============================================" | |
| echo "" | |
| # -------------------------------------------------- | |
| # STEP 1: Backup and remove unused tags | |
| # -------------------------------------------------- | |
| echo "[1/5] Backing up all tags..." | |
| $WP term list post_tag --fields=term_id,name,slug,count --format=csv > "$BACKUP_DIR/tags-backup.csv" 2>/dev/null | |
| TAG_TOTAL=$(tail -n +2 "$BACKUP_DIR/tags-backup.csv" | wc -l) | |
| echo " Saved $TAG_TOTAL tags to $BACKUP_DIR/tags-backup.csv" | |
| echo "" | |
| echo "[1/5] Finding unused tags (count = 0)..." | |
| UNUSED_IDS=$(awk -F"," 'NR>1 && $NF==0 {print $1}' "$BACKUP_DIR/tags-backup.csv") | |
| UNUSED_COUNT=$(echo "$UNUSED_IDS" | grep -c . || true) | |
| if [ "$UNUSED_COUNT" -gt 0 ]; then | |
| echo " Found $UNUSED_COUNT unused tags. Deleting..." | |
| for id in $UNUSED_IDS; do | |
| $WP term delete post_tag "$id" 2>/dev/null | |
| done | |
| echo " Deleted $UNUSED_COUNT unused tags." | |
| else | |
| echo " No unused tags found. Skipping." | |
| fi | |
| # -------------------------------------------------- | |
| # STEP 2: Close comments on all posts and pages | |
| # -------------------------------------------------- | |
| echo "" | |
| echo "[2/5] Closing comments on all posts..." | |
| OPEN_POSTS=$($WP post list --post_type=post --comment_status=open --fields=ID --format=ids 2>/dev/null || true) | |
| if [ -n "$OPEN_POSTS" ]; then | |
| echo "$OPEN_POSTS" | xargs $WP post update --comment_status=closed 2>/dev/null | |
| POST_COUNT=$(echo "$OPEN_POSTS" | wc -w) | |
| echo " Closed comments on $POST_COUNT posts." | |
| else | |
| echo " All posts already have comments closed." | |
| fi | |
| echo "" | |
| echo "[2/5] Closing comments on all pages..." | |
| OPEN_PAGES=$($WP post list --post_type=page --comment_status=open --fields=ID --format=ids 2>/dev/null || true) | |
| if [ -n "$OPEN_PAGES" ]; then | |
| echo "$OPEN_PAGES" | xargs $WP post update --comment_status=closed 2>/dev/null | |
| PAGE_COUNT=$(echo "$OPEN_PAGES" | wc -w) | |
| echo " Closed comments on $PAGE_COUNT pages." | |
| else | |
| echo " All pages already have comments closed." | |
| fi | |
| # -------------------------------------------------- | |
| # STEP 3: Set default comment and ping status | |
| # -------------------------------------------------- | |
| echo "" | |
| echo "[3/5] Setting default comment status to closed..." | |
| $WP option update default_comment_status closed 2>/dev/null | |
| echo " Done." | |
| echo "" | |
| echo "[3/5] Disabling pingbacks..." | |
| $WP option update default_ping_status closed 2>/dev/null | |
| echo " Done." | |
| # -------------------------------------------------- | |
| # STEP 4: Delete spam comments | |
| # -------------------------------------------------- | |
| echo "" | |
| echo "[4/5] Checking for spam comments..." | |
| SPAM_IDS=$($WP comment list --status=spam --fields=comment_ID --format=ids 2>/dev/null || true) | |
| if [ -n "$SPAM_IDS" ]; then | |
| # Backup spam before deleting | |
| $WP comment list --status=spam --fields=comment_ID,comment_author,comment_author_email,comment_date --format=csv > "$BACKUP_DIR/spam-comments-backup.csv" 2>/dev/null | |
| SPAM_COUNT=$(echo "$SPAM_IDS" | wc -w) | |
| echo " Found $SPAM_COUNT spam comments. Backed up to $BACKUP_DIR/spam-comments-backup.csv" | |
| echo " Deleting spam..." | |
| echo "$SPAM_IDS" | xargs $WP comment delete --force 2>/dev/null | |
| echo " Deleted $SPAM_COUNT spam comments." | |
| else | |
| echo " No spam comments found." | |
| fi | |
| # Show approved comments count (untouched) | |
| APPROVED=$($WP comment count 2>/dev/null | grep -A1 approved | tail -1 | tr -d ' ' || echo "0") | |
| echo " Approved comments (untouched): $APPROVED" | |
| # -------------------------------------------------- | |
| # STEP 5: Export 404 URLs from Apache logs | |
| # -------------------------------------------------- | |
| echo "" | |
| echo "[5/5] Scanning Apache logs for 404 content URLs..." | |
| { | |
| sudo grep ' 404 ' "$LOG_DIR/access_log" 2>/dev/null | awk '{print $7}' | |
| sudo zgrep ' 404 ' "$LOG_DIR/access_log"*.gz 2>/dev/null | awk -F'"' '{print $2}' | awk '{print $2}' | |
| } | grep -E "$CONTENT_PATHS" | sort | uniq -c | sort -rn > "$BACKUP_DIR/404-urls.txt" 2>/dev/null || true | |
| URL_COUNT=$(wc -l < "$BACKUP_DIR/404-urls.txt" 2>/dev/null || echo "0") | |
| echo " Found $URL_COUNT unique 404 content URLs." | |
| echo " Saved to $BACKUP_DIR/404-urls.txt" | |
| if [ "$URL_COUNT" -gt 0 ]; then | |
| echo "" | |
| echo " Top 10 most-hit 404 URLs:" | |
| head -10 "$BACKUP_DIR/404-urls.txt" | while read count url; do | |
| printf " %6s hits %s\n" "$count" "$url" | |
| done | |
| fi | |
| # -------------------------------------------------- | |
| # SUMMARY | |
| # -------------------------------------------------- | |
| echo "" | |
| echo "============================================" | |
| echo " Cleanup Complete" | |
| echo "============================================" | |
| echo "" | |
| echo " Tags backup: $BACKUP_DIR/tags-backup.csv" | |
| echo " Unused tags deleted: ${UNUSED_COUNT:-0}" | |
| echo " Comments closed: all posts and pages" | |
| echo " Pingbacks: disabled" | |
| echo " Spam deleted: ${SPAM_COUNT:-0}" | |
| echo " 404 URLs exported: $BACKUP_DIR/404-urls.txt" | |
| echo "" | |
| echo " NEXT STEP: Review $BACKUP_DIR/404-urls.txt" | |
| echo " and create redirect rules in the Redirection plugin." | |
| echo "" | |
| echo " Approved comments were NOT touched." | |
| echo " All backups saved in: $BACKUP_DIR" | |
| echo "" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment