Automating WordPress Security Tasks with Cron Jobs
Set up automated security scanning, log cleanup, and maintenance tasks using WordPress cron and server cron jobs.
Introduction
Security requires constant vigilance, but manual checks are impractical. Automating security tasks through WordPress cron and server cron ensures continuous protection without daily manual intervention.
WordPress Cron vs Server Cron
Understanding the difference:
- WordPress Cron - Triggered by site visits, may be delayed on low-traffic sites
- Server Cron - Runs at exact times regardless of traffic
- Recommendation - Use server cron for critical security tasks
Setting Up Security Cron Jobs
Create reliable automated security tasks:
Disable WordPress Cron for Server Cron
// Add to wp-config.php
define('DISABLE_WP_CRON', true);
// Set up server cron (crontab -e)
// Run WP-Cron every 5 minutes
*/5 * * * * wget -q -O - https://yoursite.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
// Or use WP-CLI
*/5 * * * * cd /path/to/wordpress && wp cron event run --due-now
Automated Security Scanning
// Schedule daily malware scan
function schedule_security_scan() {
if (!wp_next_scheduled('wpfs_daily_security_scan')) {
wp_schedule_event(strtotime('03:00:00'), 'daily', 'wpfs_daily_security_scan');
}
}
add_action('init', 'schedule_security_scan');
// Perform the scan
add_action('wpfs_daily_security_scan', function() {
$scanner = new WPFS_Malware_Scanner();
// Scan core files
$core_issues = $scanner->scan_core_files();
// Scan plugins
$plugin_issues = $scanner->scan_plugins();
// Scan uploads for PHP
$upload_issues = $scanner->scan_uploads_for_php();
$all_issues = array_merge($core_issues, $plugin_issues, $upload_issues);
if (!empty($all_issues)) {
// Send alert
$message = "Security scan found issues:
";
foreach ($all_issues as $issue) {
$message .= "- {$issue['file']}: {$issue['type']}
";
}
wp_mail(
get_option('admin_email'),
'[ALERT] Security Issues Detected',
$message
);
}
// Log scan result
update_option('wpfs_last_scan', array(
'time' => current_time('mysql'),
'issues' => count($all_issues),
));
});
Log Rotation and Cleanup
// Schedule log cleanup
function schedule_log_cleanup() {
if (!wp_next_scheduled('wpfs_log_cleanup')) {
wp_schedule_event(time(), 'daily', 'wpfs_log_cleanup');
}
}
add_action('init', 'schedule_log_cleanup');
add_action('wpfs_log_cleanup', function() {
global $wpdb;
// Clean security logs older than 90 days
$wpdb->query("
DELETE FROM {$wpdb->prefix}security_logs
WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY)
");
// Clean login attempt logs older than 30 days
$wpdb->query("
DELETE FROM {$wpdb->prefix}login_attempts
WHERE attempt_time < DATE_SUB(NOW(), INTERVAL 30 DAY)
");
// Archive important logs before deletion
$critical_logs = $wpdb->get_results("
SELECT * FROM {$wpdb->prefix}security_logs
WHERE event_type IN ('breach_detected', 'malware_found')
AND created_at BETWEEN DATE_SUB(NOW(), INTERVAL 90 DAY) AND DATE_SUB(NOW(), INTERVAL 89 DAY)
");
if (!empty($critical_logs)) {
// Archive to file
$archive_file = WP_CONTENT_DIR . '/security-archives/' . date('Y-m') . '.json';
file_put_contents($archive_file, json_encode($critical_logs), FILE_APPEND);
}
// Log cleanup completion
error_log('Security log cleanup completed');
});
Automated Backup Verification
// Weekly backup integrity check
function schedule_backup_check() {
if (!wp_next_scheduled('wpfs_backup_verification')) {
wp_schedule_event(time(), 'weekly', 'wpfs_backup_verification');
}
}
add_action('init', 'schedule_backup_check');
add_action('wpfs_backup_verification', function() {
$backup_dir = WP_CONTENT_DIR . '/backups/';
// Check for recent backup
$recent_backup = false;
$files = glob($backup_dir . '*.zip');
foreach ($files as $file) {
$age_days = (time() - filemtime($file)) / DAY_IN_SECONDS;
if ($age_days < 7) {
$recent_backup = true;
// Verify integrity
$zip = new ZipArchive();
if ($zip->open($file) !== true) {
wp_mail(
get_option('admin_email'),
'[WARNING] Backup File Corrupted',
"Backup file appears corrupted: {$file}"
);
}
$zip->close();
break;
}
}
if (!$recent_backup) {
wp_mail(
get_option('admin_email'),
'[WARNING] No Recent Backup Found',
'No backup file found in the last 7 days. Please verify your backup system.'
);
}
});
SSL Certificate Monitoring
// Check SSL certificate expiration
function schedule_ssl_check() {
if (!wp_next_scheduled('wpfs_ssl_check')) {
wp_schedule_event(time(), 'daily', 'wpfs_ssl_check');
}
}
add_action('init', 'schedule_ssl_check');
add_action('wpfs_ssl_check', function() {
$domain = parse_url(home_url(), PHP_URL_HOST);
$context = stream_context_create(array(
'ssl' => array('capture_peer_cert' => true),
));
$stream = @stream_socket_client(
"ssl://{$domain}:443",
$errno, $errstr, 30,
STREAM_CLIENT_CONNECT, $context
);
if (!$stream) {
wp_mail(get_option('admin_email'), '[CRITICAL] SSL Connection Failed', $errstr);
return;
}
$params = stream_context_get_params($stream);
$cert = openssl_x509_parse($params['options']['ssl']['peer_certificate']);
fclose($stream);
$expires = $cert['validTo_time_t'];
$days_until_expiry = ($expires - time()) / DAY_IN_SECONDS;
if ($days_until_expiry < 14) {
wp_mail(
get_option('admin_email'),
'[WARNING] SSL Certificate Expiring Soon',
"SSL certificate expires in {$days_until_expiry} days. Please renew immediately."
);
}
});
Blocked IP Cleanup
// Clean expired IP blocks
add_action('wpfs_hourly_cleanup', function() {
$blocked_ips = get_option('wpfs_blocked_ips', array());
$updated = false;
foreach ($blocked_ips as $ip => $data) {
if (isset($data['expires']) && $data['expires'] < time()) {
unset($blocked_ips[$ip]);
$updated = true;
}
}
if ($updated) {
update_option('wpfs_blocked_ips', $blocked_ips);
}
});
// Schedule hourly cleanup
if (!wp_next_scheduled('wpfs_hourly_cleanup')) {
wp_schedule_event(time(), 'hourly', 'wpfs_hourly_cleanup');
}
Conclusion
Automated security tasks ensure continuous protection. Schedule malware scanning, log cleanup, backup verification, and SSL monitoring through cron jobs for reliable unattended security maintenance.
Written by Sarah Chen
WP Folder Shield Team