La orden funciona en tu terminal y no produce nada a las tres de la madrugada. Cron no está roto. Ejecuta tu orden en un entorno que casi no se parece en nada a tu shell, y esa diferencia es toda la respuesta.
Mira qué ocurrió
grep CRON /var/log/syslog | tail -20
Si tu tarea no aparece ahí, cron ni lo intentó. Si aparece, cron la ejecutó y lo que falló fue otra cosa.
1. PATH está casi vacío
Tu shell sabe dónde está php. Cron no: su PATH suele ser solo /usr/bin:/bin. Usa siempre la ruta completa.
which php
# /usr/bin/php8.3
# in the crontab
0 3 * * * /usr/bin/php8.3 /var/www/site/cron.php
2. La salida no va a ninguna parte
Una tarea sin redirección manda su salida a un correo que no está configurado, así que los errores se evaporan. Mándala a un archivo y el próximo fallo se explicará solo.
0 3 * * * /usr/bin/php8.3 /var/www/site/cron.php >> /var/log/site-cron.log 2>&1
3. El usuario equivocado
Una tarea en la crontab de root escribe archivos que pertenecen a root, y el servidor web ya no puede cambiarlos. Ponla en la crontab del usuario dueño del sitio.
crontab -u youruser -l
4. Un signo de porcentaje
% significa salto de línea. Un formato de fecha como +%Y-%m-%d se convierte en silencio en tres líneas y la orden se rompe. Escápalo: \%.Pruébala como la ejecutará cron
env -i /bin/sh -c "/usr/bin/php8.3 /var/www/site/cron.php"
Eso la ejecuta con un entorno vacío, que es lo que hace cron. Si falla aquí, fallará a las tres.
