Changes:
- Add history -c && history -r after cleaning file
- Reloads cleaned history into current session
- Prevents bash from appending dirty history on shell exit
Issue:
- Trace eraser cleaned file but current session kept dirty history
- On shell exit, bash appended current session to file
- All curl commands were re-added to ~/.bash_history
Solution:
- After cleaning file, clear and reload current session history
- Current session now has only cleaned history
- On exit, only clean commands are appended
Tested:
✓ File cleaned with grep -Ev
✓ Current session reloaded from cleaned file
Changes:
- Move bash history cleaning BEFORE directory removal prompt
- Ensures history is always cleaned regardless of directory choice
- Remove exit 0 that was skipping history cleaning
Issue:
- When user answered "yes" to remove directory, script exited immediately
- History cleaning code never executed (was after exit 0)
- User's curl commands remained in ~/.bash_history
Solution:
- Restructure: clean history first, then ask about directory
- History cleaning always runs now
Tested:
✓ History cleaning happens before directory prompt
✓ Works whether user keeps or removes directory
Changes:
- Clean ~/.bash_history file directly after in-memory cleaning
- Handles commands from other terminal sessions
- Ensures complete cleanup even if history not yet written
Issue:
- history -d only cleans current session's in-memory history
- Commands from other sessions remain in ~/.bash_history file
- User's curl command persisted because it was from different session
Solution:
- After history -w, also grep -Ev on the history file
- Removes toolkit commands regardless of which session added them
Tested:
✓ Pattern matches user's curl command format
✓ Extracts correct entry numbers
Changes:
- Remove all 'history' command entries after toolkit cleanup
- Prevents showing investigation/debugging commands
- Uses same history -d approach for consistency
Removes:
- history
- history | grep curl
- cat .bash_history
- Any other history command variants
Tested:
✓ Removed 3 history command entries from test
✓ Only clean commands remain in history
Changes:
- Replace complex awk/grep file manipulation with history -d
- Use in-memory history deletion instead of file parsing
- Delete entries in reverse order to maintain numbering
- Write cleaned history back to file with history -w
Benefits:
- Much simpler and more reliable
- Works with any HISTTIMEFORMAT configuration
- Native bash command handling (no awk complexity)
- Automatically handles timestamps correctly
- User-suggested improvement
Tested:
✓ Deletes 3 toolkit entries from 7-line test history
✓ Preserves normal commands
✓ Timestamps handled automatically by history -d
Changes:
- Replace grep with awk to handle timestamp lines
- Remove matching commands AND their preceding timestamp lines
- Properly handle history format: #timestamp followed by command
Issue:
- Systems with HISTTIMEFORMAT set store timestamps as #<unix_time>
- Simple grep only removed command lines, left orphaned timestamps
- User's history showed toolkit commands still present (lines 990-1030)
Solution:
- awk script that tracks timestamp lines
- Only prints timestamp if following command is kept
- Removes both timestamp and command together atomically
Tested:
✓ Removes 16 lines (8 commands + 8 timestamps) from 32-line test
✓ Preserves normal commands with their timestamps
✓ No toolkit patterns found after cleaning
Changes:
- Replace chained grep -v with single grep -Ev for efficiency
- Fix critical bug: history -w was overwriting cleaned file
- Use history -r instead of history -w to reload cleaned history
- Single-pass filtering instead of 5 separate grep processes
- Better user messaging about other terminal sessions
Technical improvements:
- Escaped regex metacharacters in pattern (git\.mull\.lol)
- Use 3988207 for unique temp file names
- More efficient: 1 process vs 5 processes
Tested:
✓ Removes all toolkit commands regardless of position
✓ Preserves normal commands
✓ No temp file errors
✓ History properly reloaded into memory
✓ 7 toolkit entries removed from 20-line test history
Changes:
- Calculate lines removed before deleting temp files
- Add error handling to line count calculations
- Prevent 'No such file or directory' error on line 163
Tested:
✓ Pattern-based removal works correctly
✓ Removes toolkit entries regardless of position
✓ No temp file access errors
Added 'set +o history' to prevent the trace eraser commands from being re-added to history.
Changes:
• Disable history recording before cleaning (set +o history)
• Clear in-memory history with history -c
• Write empty history with history -w
• Added note to run 'exec bash' for clean shell
• Prevents script commands from being saved
This ensures the last 10 entries are properly removed and the cleanup commands themselves don't get recorded.
Reduced from 50 to 10 entries for more targeted cleanup.
Changes:
• Only removes last 10 bash history entries
• More conservative approach
• Still covers toolkit download and usage
• Less impact on normal command history
Tested and confirmed working.
Bash history cleaning was happening too early, causing script commands to be re-added to history.
Changes:
• Moved history cleaning to the very end of the script
• History is now cleaned after all other operations complete
• Prevents script commands from being re-added to history
• Clear in-memory history as final action
Now properly removes the last 50 bash history entries including all toolkit-related commands.
User bash histories are now completely skipped. The script only cleans root's bash history.
Changes:
• Removed user history detection and cleaning
• Removed prompt for user history cleaning
• Only root bash history is cleaned (last 50 entries)
• Faster execution, no prompts for user accounts
IMPORTANT: All future commits should NOT include:
- Claude Code attribution
- Any AI-related signatures
Commits should be clean and professional without AI attribution.
User bash history cleaning is now optional with a prompt, since most users only work as root.
Changes:
• Added user count detection
• Prompts: "Clean user bash histories too? (y/n) [n]"
• Default is "no" (skip user histories)
• If no users exist, automatically skips
• Only cleans root history by default (faster, covers 99% of use cases)
This makes the script faster and more sensible for typical usage where only root is used to run the toolkit.
The trace eraser was failing with "no previous regular expression" sed errors and wasn't effectively cleaning bash history.
Problems fixed:
• Broken sed pattern matching (caused errors, unreliable)
• Pattern-based deletion doesn't catch all toolkit usage
• In-memory history wasn't being cleared
New approach:
• Simply removes last 50 entries from bash history files
• More reliable than pattern matching (catches downloads, usage, everything)
• Clears in-memory history with history -c && history -w
• Creates .bak backup before cleaning
• Handles both root and user histories
• Changed system log cleaning from sed to grep -v (more reliable)
• Added symlink check for log files
This ensures the last 50 commands (covering toolkit download, installation, and usage) are completely removed from bash history.
The bot analyzer was silently processing thousands of log files with no progress feedback, appearing to stall on large servers.
Changes:
• Added progress counter showing every 50 log files parsed
• Displays current domain being processed
• Shows format: "Parsed 150 log files... (current: domain.com)"
• Clears progress line when complete to avoid clutter
• Interval set to 50 files (adjustable via progress_interval variable)
Example output:
Parsing logs from: /var/log/apache2/domlogs
Parsed 50 log files... (current: example.com)
Parsed 100 log files... (current: another.com)
Logs parsed successfully (125432 entries)
This gives real-time feedback on servers with 1000+ log files without overwhelming the output.
The domain lookup was failing because it only searched for 'servername:' in /var/cpanel/userdata/*/main files, but cPanel stores domain information differently:
- main files use 'main_domain: domain.com' (YAML format)
- domain-specific files use 'servername: domain.com' (YAML format)
Changes:
• Added two-step domain lookup process
• Method 1: Check main_domain in /var/cpanel/userdata/*/main files
• Method 2: Fallback to search all domain files for servername
• Skip cache files (.cache, cache, cache.json) during search
• Applied fix to all three domain lookup locations (options 2, 5, 6)
This fixes the "WordPress installation not found for domain" error that occurred when domains weren't configured as main_domain.
Tested with pickledperil.com - lookup now works correctly.
Changes:
- Modified disable_wpcron_in_config() to place DISABLE_WP_CRON before "stop editing" comment
- This follows WordPress convention for custom constants
- Removes any existing DISABLE_WP_CRON lines first (clean placement)
- Falls back to after <?php if "stop editing" not found
Placement Logic:
1. Remove any existing DISABLE_WP_CRON (anywhere in file)
2. Add before "/* That's all, stop editing! */" comment (line ~93)
3. Fallback: Add after <?php if no "stop editing" found
Example Placement:
```
if ( ! defined( 'WP_DEBUG' ) ) {
define( 'WP_DEBUG', false );
}
define('DISABLE_WP_CRON', true); ← Added here
/* That's all, stop editing! Happy publishing. */
```
Benefits:
- Follows WordPress conventions
- Placed with other custom constants
- Clean, predictable location
- Easy to find for manual edits
https://claude.com/claude-code
Created DEVELOPMENT-GUIDELINES.md as reference for maintaining consistency:
Structure:
- Complete project file map with quick reference table
- Standard script template with proper path resolution
- User experience guidelines (cancel options, messaging)
- Shared resources documentation (reference DB, IP reputation, user manager)
- Testing checklist and guidelines
- Git workflow and commit message template
- Menu structure standards
- Quick reference for common tasks
Key Standards Documented:
- Mandatory cancel/back options on all inputs
- Consistent messaging (print_success, print_error, etc.)
- Proper path resolution for nested scripts
- Reference database usage patterns
- IP reputation system integration
- Common function usage
Purpose:
- Ensure consistency across all scripts
- Quick reference for file locations
- Guidelines for adding new features
- Testing requirements before commits
- Uniform user experience standards
This document serves as the single source of truth for development
practices and helps maintain code quality as the toolkit grows.
https://claude.com/claude-code
Changes:
- Added "0) Cancel" option to all menu prompts
- Added "(or 0 to cancel)" to all text input prompts
- Ensures users can back out of any operation at any time
- Scripts affected:
- website-error-analyzer.sh (scope selection, time range)
- 500-error-tracker.sh (time range selection)
- wordpress-cron-manager.sh (all domain/user input prompts, status checks)
User Experience Improvements:
- No more being trapped in prompts
- Clear cancel instructions on every input
- Consistent "Operation cancelled" messaging
- Proper exit codes (0 for user cancellation)
Tested:
✓ website-error-analyzer.sh - cancel on scope selection
✓ 500-error-tracker.sh - cancel on time selection
✓ wordpress-cron-manager.sh - cancel on domain/user input
✓ All cancellations return cleanly to menu
https://claude.com/claude-code
Changes:
- Created modules/website/wordpress/ subdirectory for CMS-specific tools
- Moved wordpress-cron-manager.sh to new subdirectory
- Created wordpress-menu.sh submenu for WordPress tools
- Updated launcher.sh Website Management menu:
- Simplified to show general tools and CMS submenu options
- WordPress Management is now a submenu (option 3)
- Prepared structure for Joomla/Drupal/other CMS support
- Fixed script paths in wordpress-cron-manager.sh for new location
- Tested complete navigation: Main → Website → WordPress → Cron Manager
Menu Structure Now:
Website Management
├── Website Error Analyzer
├── 500 Error Tracker
└── WordPress Management (submenu)
└── WordPress Cron Manager
└── (All cron management options working)
https://claude.com/claude-code
New Revert Options:
- Option 6: Re-enable wp-cron for specific domain
- Option 7: Re-enable wp-cron for specific user (all sites)
- Option 8: Re-enable wp-cron server-wide (all sites)
Revert Function Features:
✅ Safely removes DISABLE_WP_CRON from wp-config.php
✅ Automatic backup before changes
✅ Verification of successful removal
✅ Auto-rollback on failure
✅ Removes cron jobs from user crontabs
✅ Batch processing for multiple sites
✅ Summary reporting
Menu Organization:
- Grouped options by function (Enable/Revert/Status)
- Color-coded sections (Green/Yellow/Cyan)
- Clear labeling of what each option does
Revert Process:
1. Backup wp-config.php
2. Remove DISABLE_WP_CRON line completely
3. Verify removal was successful
4. Remove wp-cron.php entries from user crontab
5. Provide feedback and summary
Safety Features:
- Won't break sites if DISABLE_WP_CRON not found
- Preserves other cron jobs when removing wp-cron entries
- Individual site failures don't stop batch operations
- Clear feedback on what was changed
Critical Safety Improvements:
- Prevent duplicate DISABLE_WP_CRON entries
- Detect and modify existing definitions (commented or not)
- Automatic rollback on failure
- Verification of changes before committing
Safety Function Features:
✅ Checks file exists and is writable before modification
✅ Detects existing DISABLE_WP_CRON (even if set to false)
✅ Modifies existing line instead of adding duplicate
✅ Ignores commented lines when detecting existing definitions
✅ Creates temporary backup (.wpbak) during modification
✅ Verifies change was successful after modification
✅ Automatically restores backup if verification fails
✅ Removes temporary backup only on success
Prevents Issues:
❌ No duplicate define() statements
❌ No syntax errors from malformed sed commands
❌ No broken wp-config.php files
❌ No accumulation of multiple entries on repeated runs
Error Handling:
- Returns 0 on success, 1 on failure
- Calling code can gracefully handle failures
- User feedback when modification fails
- Skips sites that fail instead of breaking entire batch
Features:
- Scan for all WordPress installations on server
- Disable wp-cron for specific domain, user, or server-wide
- Check wp-cron status for any domain or user
- Automatic wp-config.php backups before changes
- Intelligent cron job staggering to prevent load spikes
Load Distribution:
- Staggers cron times across 15-minute windows
- Example with 300 sites: distributes across minutes 0-14
- Site 1: runs at 0,15,30,45
- Site 2: runs at 1,16,31,46
- Site 3: runs at 2,17,32,47
- ...continues up to minute 14, then wraps
- Prevents all sites from running simultaneously
- Uses user crontabs (not system cron) for proper permissions
Technical Details:
- Adds DISABLE_WP_CRON to wp-config.php
- Creates user-specific crontab entries
- Prevents duplicate cron jobs
- Shows cron timing when adding jobs
- Handles multiple WP installations per user
- Add detection for when no CLI-managed plans exist
- Clarify that cloud-managed plans (web console) aren't visible via acrocmd
- Explain distinction between CLI-managed vs cloud-managed plans
- Provide guidance for both web console and CLI plan management
- Note that API credentials would be needed for cloud plan access
Simplified flow:
1. Shows available plans from acrocmd
2. Prompts user to enter plan name/ID directly
3. Press Enter to cancel and see web console instructions
4. Then proceeds to backup type and performance selection
Removed:
- Confusing numbered options (1,2,3)
- "Run all plans" option (too dangerous)
- Redundant web console option
Now more intuitive - users just type the plan name they see.
Enhanced backup trigger script with:
Backup Type Selection:
- Auto (use plan's default)
- Full backup (--backuptype=full)
- Incremental (--backuptype=incremental) - faster, changes only
- Differential (--backuptype=differential) - changes since last full
Performance Optimizations:
- Lower compression (--compression=normal) - faster, larger size
- High priority (--priority=high) - use more resources
- Both combined
Users can now choose backup type and optimization level per backup,
allowing CLI operations to be faster than web console when needed.
Improved "Cloud Connectivity Test" section:
- Now shows as dedicated section with bold header
- Displays full URL being tested (https://us5-cloud.acronis.com)
- Shows HTTP status code on success (e.g., "✓ Reachable (HTTP 200)")
- Provides troubleshooting steps on failure:
• Check internet connectivity
• Verify firewall allows HTTPS (port 443)
• Manual test command provided
This makes it easy to verify the agent can reach Acronis cloud
and diagnose connectivity issues.
Removed interactive Quick Actions (start/stop/restart/logs/version)
from agent status screen. These were redundant with existing menu
options and cluttered the status display.
Status screen now shows info and returns to menu immediately.
Log analysis will be handled in the troubleshoot script instead,
which will comprehensively check all Acronis logs for issues.
Cannot reliably determine total cloud storage quota via CLI.
Removed hardcoded 50GB assumption since plans vary.
Now shows:
- Available: 30.96 GB (accurate from acrocmd)
- Used: (Check web console for accurate usage)
This is the safest approach since:
- Total quota not exposed via acrocmd or config files
- acrocmd list licenses fails for cloud-managed agents
- Web console always has accurate real-time usage data
When acrocmd shows "Occupied: 0 GB" (agent sync issue), calculate
actual usage by subtracting available from 50GB total quota.
Now displays:
Used: ~19.04 GB (50GB - 30.96GB available)
This shows the real 19GB usage that appears in web console by
reverse-calculating from remaining quota (30.96 GB).
Added "Cloud Backup Storage" section showing:
- Vault name
- Used storage (occupied)
- Available storage (free quota)
Uses 'acrocmd list vaults' to query actual cloud storage usage
that was previously only visible in web console.
This will show the 19GB backup storage usage the user was asking about.
Changed "Storage Status" to "Local Storage Status" to clearly indicate
this shows agent data (130M cache/logs/config), not backup storage.
Added note directing users to Acronis web console for actual backup
storage usage (19GB cloud storage shown there).
Prevents confusion between:
- Local agent data: 130M (what script shows)
- Cloud backup storage: 19GB (shown in web interface)
Fixed Issues:
- Registration check now uses correct config file (user.config)
- Parses actual registration XML to verify cloud connection
- Shows registration URL and environment
Port Monitoring:
- Now detects actual Acronis listening ports via netstat
- Shows real local ports (9850 for MMS, dynamic ports for aakore)
- Identifies which service owns each port
- Tests actual cloud connectivity with timeout
Changes:
- Registration verified from /var/lib/Acronis/.../user.config
- Port 9850 (localhost): MMS management service
- Dynamic ports: aakore agent core
- Added cloud connectivity test to registration URL
Fixed error where 'local' keyword was used outside of a function in
the storage status section. Changed to regular variable declarations
and added null check for use_percent to prevent integer expression errors.
Completely rewrote acronis-update.sh to actually perform upgrades:
Features:
- Checks current version before upgrade
- Shows service status
- Two upgrade methods:
1. Automatic (web console instructions)
2. Manual (downloads and runs upgrade)
Manual Upgrade Process:
- Detects existing installation automatically
- Extracts cloud URL from /etc/Acronis/Global.config
- Downloads latest installer from correct region
- Runs installer in unattended mode (-a flag)
- Installer automatically upgrades over existing installation
- Preserves configuration and registration
- Shows version before/after upgrade
- Verifies services running after upgrade
- Offers to restart services if needed
- Cleans up download files
What Gets Preserved During Upgrade:
✓ Agent registration (stays connected to account)
✓ Backup plan configurations
✓ Connection settings
✓ Service configurations
Based on Acronis documentation research:
- Running installer over existing installation = automatic upgrade
- No uninstall needed
- No re-registration needed
Better approach per user suggestion:
- Downloads to: /root/server-toolkit/downloads/acronis-install-YYYYMMDD-HHMMSS/
- Keeps toolkit directory organized
- Avoids polluting /root
- Avoids /tmp noexec issues
- Added downloads/ to .gitignore
- Cleanup removes timestamped installation directory after completion
Benefits:
- All downloads in one place
- Easy to find if debugging needed
- Cleaner than scattered in /root
- Still allows execution (not in /tmp)
Root cause: /tmp is mounted with noexec flag preventing execution.
Changed TEMP_DIR from /tmp/acronis-install to /root/acronis-install
This allows the installer binary to execute properly.
Verified: mount shows /tmp with noexec option
Solution: Use /root which allows execution
Removed the -x check that was failing despite file being executable.
Changed to simple file existence and size validation instead.
Back to direct execution (./ ) instead of bash wrapper.
The file shows -rwxr-xr-x so it has execute permissions.
The issue was the test itself, not the permissions.
Changes:
- Added verification after chmod +x to ensure permissions were set
- Changed execution from './file' to 'bash ./file' for better compatibility
- Added detailed error handling if chmod fails
- Shows file permissions on error for debugging
This fixes 'Permission denied' error (exit code 126) when running installer.
Changed confirmation check from exact 'yes' match to regex pattern that accepts:
- y, Y
- yes, Yes, YES
- Any case variation
This prevents user frustration when typing 'y' instead of full 'yes'.