#!/bin/bash ################################################################################ # WordPress Cron Manager ################################################################################ # Purpose: Disable wp-cron and convert to real system cron jobs # Features: # - Detect all WordPress installations # - Disable DISABLE_WP_CRON in wp-config.php # - Add proper cron jobs for scheduled tasks # - Server-wide, per-user, or per-domain operations ################################################################################ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" source "$SCRIPT_DIR/lib/common-functions.sh" source "$SCRIPT_DIR/lib/system-detect.sh" if [ "$EUID" -ne 0 ]; then print_error "This script must be run as root" exit 1 fi # Global counter for staggering cron times CRON_OFFSET=0 # Function to generate staggered cron time # Distributes jobs across 15 minutes to avoid load spikes generate_staggered_cron() { local minute=$((CRON_OFFSET % 15)) # Create pattern: 0,15,30,45 but offset by the calculated minute local minutes="" for base in 0 15 30 45; do local actual_minute=$(( (base + minute) % 60 )) if [ -z "$minutes" ]; then minutes="$actual_minute" else minutes="$minutes,$actual_minute" fi done # Increment offset for next site (wraps at 15) CRON_OFFSET=$((CRON_OFFSET + 1)) echo "$minutes * * * *" } # Function to safely modify wp-config.php to disable wp-cron # Returns 0 on success, 1 on failure disable_wpcron_in_config() { local wp_config="$1" # Check if file exists and is writable if [ ! -f "$wp_config" ] || [ ! -w "$wp_config" ]; then return 1 fi # Check if DISABLE_WP_CRON already exists (not commented) if grep -E "^[^/]*define\s*\(\s*['\"]DISABLE_WP_CRON['\"]" "$wp_config" >/dev/null 2>&1; then # Line exists, modify it to set true sed -i.wpbak "s/^\([^/]*\)define\s*(\s*['\"]DISABLE_WP_CRON['\"]\s*,\s*[^)]*)/\1define('DISABLE_WP_CRON', true)/" "$wp_config" else # Line doesn't exist, add it after /dev/null 2>&1; then # Remove backup if successful rm -f "${wp_config}.wpbak" return 0 else # Restore backup if verification failed if [ -f "${wp_config}.wpbak" ]; then mv "${wp_config}.wpbak" "$wp_config" fi return 1 fi } # Function to safely re-enable wp-cron (revert changes) # Returns 0 on success, 1 on failure enable_wpcron_in_config() { local wp_config="$1" # Check if file exists and is writable if [ ! -f "$wp_config" ] || [ ! -w "$wp_config" ]; then return 1 fi # Check if DISABLE_WP_CRON exists and is set to true if grep -E "^[^/]*define\s*\(\s*['\"]DISABLE_WP_CRON['\"]\s*,\s*true\s*\)" "$wp_config" >/dev/null 2>&1; then # Remove or comment out the line sed -i.wpbak "/^[^/]*define\s*(\s*['\"]DISABLE_WP_CRON['\"]\s*,\s*true\s*)/d" "$wp_config" # Verify removal was successful if ! grep -E "^[^/]*define\s*\(\s*['\"]DISABLE_WP_CRON['\"]\s*,\s*true\s*\)" "$wp_config" >/dev/null 2>&1; then rm -f "${wp_config}.wpbak" return 0 else # Restore backup if removal failed if [ -f "${wp_config}.wpbak" ]; then mv "${wp_config}.wpbak" "$wp_config" fi return 1 fi else # DISABLE_WP_CRON not found or already disabled return 0 fi } clear print_banner "WordPress Cron Manager" echo "" echo -e "${BOLD}What would you like to do?${NC}" echo "" echo -e "${GREEN}Enable System Cron:${NC}" echo " 1) Scan for WordPress installations" echo " 2) Disable wp-cron for specific domain" echo " 3) Disable wp-cron for specific user (all their WP sites)" echo " 4) Disable wp-cron server-wide (all WordPress sites)" echo "" echo -e "${YELLOW}Revert to WP-Cron:${NC}" echo " 6) Re-enable wp-cron for specific domain" echo " 7) Re-enable wp-cron for specific user (all their WP sites)" echo " 8) Re-enable wp-cron server-wide (all WordPress sites)" echo "" echo -e "${CYAN}Status & Information:${NC}" echo " 5) Check wp-cron status for domain/user" echo "" echo " 0) Return to menu" echo "" echo -n "Select option [0]: " read -r choice choice="${choice:-0}" case "$choice" in 1) # Scan for WordPress installations echo "" print_banner "WordPress Installation Scanner" echo "" echo "Scanning for WordPress installations..." echo "" # Find all wp-config.php files in home directories wp_sites=$(find /home/*/public_html -name "wp-config.php" -type f 2>/dev/null) if [ -z "$wp_sites" ]; then echo -e "${YELLOW}No WordPress installations found${NC}" else count=0 echo -e "${BOLD}Found WordPress Installations:${NC}" echo "" while IFS= read -r config_file; do count=$((count + 1)) # Extract info site_path=$(dirname "$config_file") user=$(echo "$site_path" | cut -d'/' -f3) # Try to find domain domain="(unknown domain)" if [ -f "/var/cpanel/userdata/$user/main" ]; then domain=$(grep -m1 "^servername:" "/var/cpanel/userdata/$user/main" 2>/dev/null | awk '{print $2}') fi # Check if wp-cron is disabled if grep -q "define.*DISABLE_WP_CRON.*true" "$config_file" 2>/dev/null; then status="${GREEN}✓ Disabled (using system cron)${NC}" else status="${YELLOW}⚠ Enabled (default wp-cron)${NC}" fi echo -e "${count}. ${BOLD}$domain${NC}" echo " Path: $site_path" echo " User: $user" echo " Status: $status" echo "" done <<< "$wp_sites" echo -e "${CYAN}Total WordPress installations: $count${NC}" fi ;; 2) # Disable wp-cron for specific domain echo "" echo -n "Enter domain name (or 0 to cancel): " read -r domain if [ -z "$domain" ] || [ "$domain" = "0" ]; then echo "Operation cancelled." press_enter exit 0 fi # Find WordPress installation for this domain echo "" echo "Searching for WordPress installation for $domain..." # Try to find via cPanel user data wp_config="" for userdata_file in /var/cpanel/userdata/*/main; do if grep -q "^servername: $domain" "$userdata_file" 2>/dev/null; then user=$(basename "$(dirname "$userdata_file")") potential_config="/home/$user/public_html/wp-config.php" if [ -f "$potential_config" ]; then wp_config="$potential_config" break fi fi done if [ -z "$wp_config" ]; then print_error "WordPress installation not found for $domain" press_enter exit 1 fi echo -e "${GREEN}Found WordPress:${NC} $wp_config" echo "" # Check if already disabled if grep -q "define.*DISABLE_WP_CRON.*true" "$wp_config" 2>/dev/null; then echo -e "${YELLOW}wp-cron is already disabled for this site${NC}" echo "" echo -n "Re-configure anyway? (y/n) [n]: " read -r confirm if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then press_enter exit 0 fi fi # Backup wp-config.php cp "$wp_config" "${wp_config}.backup-$(date +%Y%m%d-%H%M%S)" echo -e "${GREEN}✓${NC} Backed up wp-config.php" # Safely disable wp-cron in wp-config.php if disable_wpcron_in_config "$wp_config"; then echo -e "${GREEN}✓${NC} Set DISABLE_WP_CRON to true in wp-config.php" else print_error "Failed to modify wp-config.php" echo " Please check file permissions and syntax" press_enter exit 1 fi # Add cron job with staggered timing site_path=$(dirname "$wp_config") cron_cmd="cd $site_path && /usr/bin/php -q wp-cron.php >/dev/null 2>&1" # Add to user's crontab user=$(echo "$site_path" | cut -d'/' -f3) # Check if cron job already exists if crontab -u "$user" -l 2>/dev/null | grep -q "$site_path.*wp-cron.php"; then echo -e "${YELLOW}⚠${NC} Cron job already exists for this site" else # Generate staggered cron time cron_time=$(generate_staggered_cron) (crontab -u "$user" -l 2>/dev/null; echo "$cron_time $cron_cmd") | crontab -u "$user" - echo -e "${GREEN}✓${NC} Added cron job ($cron_time)" fi echo "" print_success "WordPress cron converted to system cron for $domain" echo "" echo "Changes made:" echo " • DISABLE_WP_CRON set to true in wp-config.php" echo " • System cron job added (every 15 minutes)" echo " • Backup saved: ${wp_config}.backup-*" ;; 3) # Disable wp-cron for specific user echo "" echo -n "Enter cPanel username (or 0 to cancel): " read -r target_user if [ -z "$target_user" ] || [ "$target_user" = "0" ]; then echo "Operation cancelled." press_enter exit 0 fi if [ ! -d "/home/$target_user" ]; then print_error "User $target_user does not exist" press_enter exit 1 fi echo "" echo "Searching for WordPress installations for user: $target_user" echo "" wp_configs=$(find "/home/$target_user" -name "wp-config.php" -type f 2>/dev/null) if [ -z "$wp_configs" ]; then print_error "No WordPress installations found for $target_user" press_enter exit 1 fi count=0 echo "$wp_configs" | while IFS= read -r wp_config; do count=$((count + 1)) site_path=$(dirname "$wp_config") echo -e "${BOLD}Site $count:${NC} $site_path" # Backup cp "$wp_config" "${wp_config}.backup-$(date +%Y%m%d-%H%M%S)" 2>/dev/null echo " • Backed up wp-config.php" # Safely disable wp-cron if disable_wpcron_in_config "$wp_config"; then echo " • Set DISABLE_WP_CRON to true" else echo " • ${YELLOW}Warning: Could not modify wp-config.php${NC}" echo "" continue fi # Add cron job with staggered timing cron_cmd="cd $site_path && /usr/bin/php -q wp-cron.php >/dev/null 2>&1" if ! crontab -u "$target_user" -l 2>/dev/null | grep -q "$site_path.*wp-cron.php"; then cron_time=$(generate_staggered_cron) (crontab -u "$target_user" -l 2>/dev/null; echo "$cron_time $cron_cmd") | crontab -u "$target_user" - echo " • Added cron job ($cron_time)" else echo " • Cron job already exists" fi echo "" done print_success "All WordPress sites for $target_user converted to system cron" ;; 4) # Server-wide conversion echo "" echo -e "${RED}${BOLD}WARNING: Server-Wide wp-cron Conversion${NC}" echo "" echo "This will:" echo " • Find ALL WordPress installations on the server" echo " • Disable wp-cron in each wp-config.php" echo " • Add system cron jobs for each user" echo "" echo -n "Are you sure? Type 'yes' to confirm: " read -r confirm if [ "$confirm" != "yes" ]; then echo "Cancelled" press_enter exit 0 fi echo "" echo "Scanning entire server for WordPress installations..." echo "" total=0 converted=0 wp_configs=$(find /home/*/public_html -name "wp-config.php" -type f 2>/dev/null) if [ -z "$wp_configs" ]; then echo -e "${YELLOW}No WordPress installations found${NC}" press_enter exit 0 fi while IFS= read -r wp_config; do total=$((total + 1)) site_path=$(dirname "$wp_config") user=$(echo "$site_path" | cut -d'/' -f3) echo -e "${BOLD}Processing:${NC} $site_path (user: $user)" # Backup cp "$wp_config" "${wp_config}.backup-$(date +%Y%m%d-%H%M%S)" 2>/dev/null # Safely disable wp-cron if ! disable_wpcron_in_config "$wp_config"; then echo -e "${YELLOW}⚠ Failed to modify wp-config.php${NC}" echo "" continue fi # Add cron job with staggered timing cron_cmd="cd $site_path && /usr/bin/php -q wp-cron.php >/dev/null 2>&1" if ! crontab -u "$user" -l 2>/dev/null | grep -q "$site_path.*wp-cron.php"; then cron_time=$(generate_staggered_cron) (crontab -u "$user" -l 2>/dev/null; echo "$cron_time $cron_cmd") | crontab -u "$user" - 2>/dev/null echo " Cron: $cron_time" fi converted=$((converted + 1)) echo -e "${GREEN}✓${NC} Converted" echo "" done <<< "$wp_configs" echo "" print_success "Server-wide conversion complete" echo "" echo "Summary:" echo " • Total WordPress sites found: $total" echo " • Successfully converted: $converted" ;; 5) # Check status echo "" echo "Check wp-cron status for:" echo " 1) Specific domain" echo " 2) Specific user" echo " 0) Cancel" echo "" echo -n "Select [1]: " read -r check_choice check_choice="${check_choice:-1}" if [ "$check_choice" = "0" ]; then echo "Operation cancelled." press_enter exit 0 elif [ "$check_choice" = "1" ]; then echo "" echo -n "Enter domain name (or 0 to cancel): " read -r domain if [ -z "$domain" ] || [ "$domain" = "0" ]; then echo "Operation cancelled." press_enter exit 0 fi # Find WordPress for domain wp_config="" for userdata_file in /var/cpanel/userdata/*/main; do if grep -q "^servername: $domain" "$userdata_file" 2>/dev/null; then user=$(basename "$(dirname "$userdata_file")") potential_config="/home/$user/public_html/wp-config.php" if [ -f "$potential_config" ]; then wp_config="$potential_config" break fi fi done if [ -z "$wp_config" ]; then print_error "WordPress not found for $domain" press_enter exit 1 fi echo "" echo -e "${BOLD}WordPress Cron Status for $domain${NC}" echo "" echo "Config file: $wp_config" echo "" if grep -q "define.*DISABLE_WP_CRON.*true" "$wp_config" 2>/dev/null; then echo -e "wp-cron: ${GREEN}DISABLED${NC} (using system cron)" # Check for cron job site_path=$(dirname "$wp_config") user=$(echo "$site_path" | cut -d'/' -f3) if crontab -u "$user" -l 2>/dev/null | grep -q "wp-cron.php"; then echo -e "System cron: ${GREEN}CONFIGURED${NC}" echo "" echo "Cron jobs:" crontab -u "$user" -l 2>/dev/null | grep "wp-cron.php" else echo -e "System cron: ${RED}NOT CONFIGURED${NC}" fi else echo -e "wp-cron: ${YELLOW}ENABLED${NC} (default WordPress cron)" echo "" echo "Recommendation: Disable wp-cron and use system cron for better performance" fi else echo "" echo -n "Enter cPanel username (or 0 to cancel): " read -r check_user if [ -z "$check_user" ] || [ "$check_user" = "0" ]; then echo "Operation cancelled." press_enter exit 0 fi if [ ! -d "/home/$check_user" ]; then print_error "User $check_user does not exist" press_enter exit 1 fi echo "" echo -e "${BOLD}WordPress Cron Status for user: $check_user${NC}" echo "" wp_configs=$(find "/home/$check_user" -name "wp-config.php" -type f 2>/dev/null) if [ -z "$wp_configs" ]; then echo "No WordPress installations found" else count=0 while IFS= read -r wp_config; do count=$((count + 1)) site_path=$(dirname "$wp_config") echo -e "${count}. ${BOLD}$site_path${NC}" if grep -q "define.*DISABLE_WP_CRON.*true" "$wp_config" 2>/dev/null; then echo " wp-cron: ${GREEN}DISABLED${NC}" else echo " wp-cron: ${YELLOW}ENABLED${NC}" fi echo "" done <<< "$wp_configs" # Show cron jobs echo -e "${BOLD}Cron Jobs:${NC}" if crontab -u "$check_user" -l 2>/dev/null | grep -q "wp-cron.php"; then crontab -u "$check_user" -l 2>/dev/null | grep "wp-cron.php" else echo " No wp-cron jobs found" fi fi fi ;; 6) # Re-enable wp-cron for specific domain echo "" echo -n "Enter domain name (or 0 to cancel): " read -r domain if [ -z "$domain" ] || [ "$domain" = "0" ]; then echo "Operation cancelled." press_enter exit 0 fi # Find WordPress installation wp_config="" for userdata_file in /var/cpanel/userdata/*/main; do if grep -q "^servername: $domain" "$userdata_file" 2>/dev/null; then user=$(basename "$(dirname "$userdata_file")") potential_config="/home/$user/public_html/wp-config.php" if [ -f "$potential_config" ]; then wp_config="$potential_config" break fi fi done if [ -z "$wp_config" ]; then print_error "WordPress installation not found for $domain" press_enter exit 1 fi echo -e "${GREEN}Found WordPress:${NC} $wp_config" echo "" # Backup wp-config.php cp "$wp_config" "${wp_config}.backup-$(date +%Y%m%d-%H%M%S)" echo -e "${GREEN}✓${NC} Backed up wp-config.php" # Re-enable wp-cron if enable_wpcron_in_config "$wp_config"; then echo -e "${GREEN}✓${NC} Removed DISABLE_WP_CRON from wp-config.php" else echo -e "${YELLOW}⚠${NC} DISABLE_WP_CRON not found or already enabled" fi # Remove cron job site_path=$(dirname "$wp_config") user=$(echo "$site_path" | cut -d'/' -f3) if crontab -u "$user" -l 2>/dev/null | grep -q "$site_path.*wp-cron.php"; then crontab -u "$user" -l 2>/dev/null | grep -v "$site_path.*wp-cron.php" | crontab -u "$user" - echo -e "${GREEN}✓${NC} Removed cron job from user crontab" else echo -e "${YELLOW}⚠${NC} No cron job found for this site" fi echo "" print_success "WordPress cron reverted to default for $domain" ;; 7) # Re-enable wp-cron for specific user echo "" echo -n "Enter cPanel username (or 0 to cancel): " read -r target_user if [ -z "$target_user" ] || [ "$target_user" = "0" ]; then echo "Operation cancelled." press_enter exit 0 fi if [ ! -d "/home/$target_user" ]; then print_error "User $target_user does not exist" press_enter exit 1 fi echo "" echo "Reverting WordPress installations for user: $target_user" echo "" wp_configs=$(find "/home/$target_user" -name "wp-config.php" -type f 2>/dev/null) if [ -z "$wp_configs" ]; then print_error "No WordPress installations found for $target_user" press_enter exit 1 fi count=0 echo "$wp_configs" | while IFS= read -r wp_config; do count=$((count + 1)) site_path=$(dirname "$wp_config") echo -e "${BOLD}Site $count:${NC} $site_path" # Backup cp "$wp_config" "${wp_config}.backup-$(date +%Y%m%d-%H%M%S)" 2>/dev/null echo " • Backed up wp-config.php" # Re-enable wp-cron if enable_wpcron_in_config "$wp_config"; then echo " • Removed DISABLE_WP_CRON" else echo " • Already using default wp-cron" fi echo "" done # Remove all wp-cron jobs for this user if crontab -u "$target_user" -l 2>/dev/null | grep -q "wp-cron.php"; then crontab -u "$target_user" -l 2>/dev/null | grep -v "wp-cron.php" | crontab -u "$target_user" - echo -e "${GREEN}✓${NC} Removed all wp-cron jobs from user crontab" fi print_success "All WordPress sites for $target_user reverted to default wp-cron" ;; 8) # Server-wide revert echo "" echo -e "${RED}${BOLD}WARNING: Server-Wide Revert${NC}" echo "" echo "This will:" echo " • Find ALL WordPress installations on the server" echo " • Remove DISABLE_WP_CRON from each wp-config.php" echo " • Remove all wp-cron system cron jobs" echo "" echo -n "Are you sure? Type 'yes' to confirm: " read -r confirm if [ "$confirm" != "yes" ]; then echo "Cancelled" press_enter exit 0 fi echo "" echo "Scanning entire server for WordPress installations..." echo "" total=0 reverted=0 wp_configs=$(find /home/*/public_html -name "wp-config.php" -type f 2>/dev/null) if [ -z "$wp_configs" ]; then echo -e "${YELLOW}No WordPress installations found${NC}" press_enter exit 0 fi while IFS= read -r wp_config; do total=$((total + 1)) site_path=$(dirname "$wp_config") user=$(echo "$site_path" | cut -d'/' -f3) echo -e "${BOLD}Processing:${NC} $site_path (user: $user)" # Backup cp "$wp_config" "${wp_config}.backup-$(date +%Y%m%d-%H%M%S)" 2>/dev/null # Re-enable wp-cron if enable_wpcron_in_config "$wp_config"; then reverted=$((reverted + 1)) echo -e "${GREEN}✓${NC} Reverted" else echo -e "${YELLOW}⚠${NC} Already using default wp-cron" fi echo "" done <<< "$wp_configs" # Remove all wp-cron jobs from all users echo "" echo "Removing wp-cron jobs from user crontabs..." for user_home in /home/*; do user=$(basename "$user_home") if crontab -u "$user" -l 2>/dev/null | grep -q "wp-cron.php"; then crontab -u "$user" -l 2>/dev/null | grep -v "wp-cron.php" | crontab -u "$user" - 2>/dev/null echo " • Removed cron jobs for user: $user" fi done echo "" print_success "Server-wide revert complete" echo "" echo "Summary:" echo " • Total WordPress sites found: $total" echo " • Successfully reverted: $reverted" ;; 0) exit 0 ;; *) print_error "Invalid option" ;; esac echo "" press_enter