Me pasó esto en un servidor Debian, y me volvió loco durante varios días, hasta que logré descubrir qué estaba pasando. run-parts
es una herramienta utilizada por crond en sistemas Debian y derivados para correr todos los scripts en los directorios de cron /etc/crond.*/
.
Como muchos sabrán, crond tiene cuatro cronjobs (o tareas "programadas") especiales que corren cada hora, día, semana y mes. Estas tareas simplemente invocan al utilitario run-parts
sobre los directorios /etc/cron.hourly/
, /etc/cron.daily/
, /etc/cron.weekly/
y /etc/cron.monthly
respectivamente.
run-parts
corre todos los ejecutables que encuentre en un directorio pasado como parámetro. El problema es que los nombres de los ejecutables deben respetar ciertas restricciones: sólo se admiten letras mayúsculas, minúsculas, dígitos, guiones bajos y guiones del medio (símbolo menos). Esto significa que si el nombre de un ejecutable contiene un punto, éste será ignorado de manera silenciosa.
Veamos un ejemplo: el directorio /etc/cron.daily/
contiene dos enlaces simbólicos a scripts Bash llamados check_disks.sh
y check_updates.sh
:
root@debian:/etc/cron.daily# ll total 60 -rwxr-xr-x 1 root root 268 May 6 2012 00logwatch -rwxr-xr-x 1 root root 311 May 22 2012 0anacron -rwxr-xr-x 1 root root 15000 Dec 11 2016 apt -rwxr-xr-x 1 root root 314 Nov 7 2012 aptitude -rwxr-xr-x 1 root root 355 Jun 11 2012 bsdmainutils lrwxrwxrwx 1 root root 28 Aug 18 13:13 check_disks.sh -> /root/scripts/check_disks.sh lrwxrwxrwx 1 root root 30 Aug 18 13:13 check_updates.sh -> /root/scripts/check_updates.sh -rwxr-xr-x 1 root root 1597 May 2 2016 dpkg -rwxr-xr-x 1 root root 4125 Mar 14 2016 exim4-base -rwxr-xr-x 1 root root 89 May 17 2012 logrotate -rwxr-xr-x 1 root root 1293 Dec 31 2014 man-db -rwxr-xr-x 1 root root 435 Jun 13 2013 mlocate -rwxr-xr-x 1 root root 249 May 25 2012 passwd
Al ejecutar run-parts
sobre este directorio, ambos scripts son ignorados:
root@debian:~/scripts# run-parts -v /etc/cron.daily run-parts: executing /etc/cron.daily/00logwatch run-parts: executing /etc/cron.daily/0anacron run-parts: executing /etc/cron.daily/apt run-parts: executing /etc/cron.daily/aptitude run-parts: executing /etc/cron.daily/bsdmainutils run-parts: executing /etc/cron.daily/dpkg run-parts: executing /etc/cron.daily/exim4-base run-parts: executing /etc/cron.daily/logrotate run-parts: executing /etc/cron.daily/man-db run-parts: executing /etc/cron.daily/mlocate run-parts: executing /etc/cron.daily/passwd
Veamos qué ocurre al renombrar ambos enlaces simbólicos:
root@debian:/etc/cron.daily# mv check_updates.sh check_updates root@debian:/etc/cron.daily# mv check_disks.sh check_disks
Ahora los enlaces simbólicos no contienen la extensión .sh
, aunque los targets sí:
root@debian:/etc/cron.daily# ll total 60 -rwxr-xr-x 1 root root 268 May 6 2012 00logwatch -rwxr-xr-x 1 root root 311 May 22 2012 0anacron -rwxr-xr-x 1 root root 15000 Dec 11 2016 apt -rwxr-xr-x 1 root root 314 Nov 7 2012 aptitude -rwxr-xr-x 1 root root 355 Jun 11 2012 bsdmainutils lrwxrwxrwx 1 root root 28 Aug 18 13:13 check_disks -> /root/scripts/check_disks.sh lrwxrwxrwx 1 root root 30 Aug 18 13:13 check_updates -> /root/scripts/check_updates.sh -rwxr-xr-x 1 root root 1597 May 2 2016 dpkg -rwxr-xr-x 1 root root 4125 Mar 14 2016 exim4-base -rwxr-xr-x 1 root root 89 May 17 2012 logrotate -rwxr-xr-x 1 root root 1293 Dec 31 2014 man-db -rwxr-xr-x 1 root root 435 Jun 13 2013 mlocate -rwxr-xr-x 1 root root 249 May 25 2012 passwd
Al ejecutar run-parts
nuevamente sobre el directorio ambos son ejecutados.
root@debian:/etc/cron.daily# run-parts -v /etc/cron.daily run-parts: executing /etc/cron.daily/00logwatch run-parts: executing /etc/cron.daily/0anacron run-parts: executing /etc/cron.daily/apt run-parts: executing /etc/cron.daily/aptitude run-parts: executing /etc/cron.daily/bsdmainutils run-parts: executing /etc/cron.daily/check_disks run-parts: executing /etc/cron.daily/check_updates run-parts: executing /etc/cron.daily/dpkg run-parts: executing /etc/cron.daily/exim4-base run-parts: executing /etc/cron.daily/logrotate run-parts: executing /etc/cron.daily/man-db run-parts: executing /etc/cron.daily/mlocate run-parts: executing /etc/cron.daily/passwd
¡Al fin!
Moraleja de la historia: nunca dejar scripts o ejecutables con extensión en los directorios de cron. Pequeños detalles que pasan desapercibidos en las manpages:
man cron man run-parts