如何使用PHP的shell_exec编辑crontab?附现有crontab任务示例
Alright, let's walk through how to edit your crontab using PHP, building on the code you already have to list existing entries.
1. First: Confirm Existing Crontab Entries (Your Current Code)
You're already using this snippet to pull up your current crontab tasks, which is a great starting point:
$output = shell_exec('crontab -l'); echo "<pre>"; print_r($output); echo "</pre>";
From your output, here's the existing crontab structure you're working with:
MAILTO="admin@example.com"
*/2 * * * * /usr/bin/php5 /var/www/vhosts/example.com/streaming.example.com/index.php admin cron > /dev/null
MAILTO=""
*/1 * * * * /opt/psa/admin/sbin/fetch_url 'https://www.example.com/referral/send_referral_email'
MAILTO=""
*/5 * * * * /opt/psa/admin/sbin/fetch_url 'https://www.example.com/members/send_notif'
...
2. Core Logic for Editing Crontab
The process boils down to three steps: fetch existing content → modify it → write it back to crontab. Let's break down common use cases.
2.1 Adding a New Crontab Task
Say you want to add a daily backup task that runs at 1 AM. Here's how to do it safely (with checks to avoid duplicates):
// Grab existing crontab content $existingCrontab = shell_exec('crontab -l'); // Handle empty crontab case (shell_exec returns null if no entries exist) if ($existingCrontab === null) $existingCrontab = ''; // Define your new task (follow crontab format strictly) $newTask = "MAILTO=\"backup@example.com\"\n0 1 * * * /usr/bin/tar -czf /var/backups/site_backup.tar.gz /var/www/vhosts/example.com\n"; // Check if the task already exists to avoid duplicates if (strpos($existingCrontab, trim($newTask)) === false) { $updatedCrontab = rtrim($existingCrontab, "\n") . "\n" . $newTask; } else { $updatedCrontab = $existingCrontab; // No change needed } // Use a temp file to write the updated content (more reliable than direct piping) $tempFile = tempnam(sys_get_temp_dir(), 'crontab'); file_put_contents($tempFile, $updatedCrontab); // Apply the updated crontab shell_exec('crontab ' . $tempFile); // Clean up the temp file unlink($tempFile); // Verify the change echo "<pre>Updated Crontab:\n"; print_r(shell_exec('crontab -l')); echo "</pre>";
2.2 Removing an Existing Crontab Task
If you want to delete the minute-ly send_referral_email task, use this approach:
// Fetch existing entries $existingCrontab = shell_exec('crontab -l'); if ($existingCrontab === null) $existingCrontab = ''; // Define the exact task line you want to remove (match spacing/quotes exactly) $taskToRemove = "*/1 * * * * /opt/psa/admin/sbin/fetch_url 'https://www.example.com/referral/send_referral_email'"; // Split content into lines, filter out the target task $lines = explode("\n", $existingCrontab); $updatedLines = array_filter($lines, function($line) use ($taskToRemove) { $trimmedLine = trim($line); // Keep non-empty lines that don't match the task to remove return $trimmedLine !== '' && $trimmedLine !== $taskToRemove; }); // Reassemble the crontab content $updatedCrontab = implode("\n", $updatedLines); // Write to temp file and apply $tempFile = tempnam(sys_get_temp_dir(), 'crontab'); file_put_contents($tempFile, $updatedCrontab); shell_exec('crontab ' . $tempFile); unlink($tempFile); // Verify removal echo "<pre>Crontab After Removal:\n"; print_r(shell_exec('crontab -l')); echo "</pre>";
3. Critical Notes to Avoid Headaches
- Permissions: The user running PHP (usually
www-data) needs permission to executecrontabcommands and access any scripts referenced in tasks. If you hit permission errors, check sudoers config (but restrict access tightly to avoid security risks). - Format Accuracy: Crontab time rules are strict (
minute hour day month weekday). Double-check your task syntax—one wrong character breaks everything. - Error Handling: Use
exec()instead ofshell_exec()if you want to capture exit codes to debug failures:exec('crontab -l', $output, $returnCode); if ($returnCode !== 0) { // Handle empty crontab or permission issues here $existingCrontab = ''; } else { $existingCrontab = implode("\n", $output); } - Temp File Safety: Always use
tempnam()to create temporary files (it sets secure permissions) and delete them immediately after use.
内容的提问来源于stack exchange,提问作者mdnba50

