Resumen
El código correcto debería ser:
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Llame a este script end_of_month.sh
y la llamada en cron es simplemente:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Eso ejecutaría el script end_of_month
(que verificará internamente que el día sea el último día del mes) solo los días 28, 29, 30 y 31. No hay necesidad de verificar el final del mes en ningún otro día.
Post antiguo
Esa es una cita del libro "Linux Command Line and Shell Scripting Bible" de Richard Blum, Christine Bresnahan pp 442, Tercera edición, John Wiley & Sons © 2015.
Sí, eso es lo que dice, pero eso está mal / incompleto:
- Falta un cierre
fi
.
- Necesita espacio entre
[
y lo siguiente `
.
- Se recomienda encarecidamente usar $ (...) en lugar de
`…`
.
- Es importante que use comillas alrededor de expansiones como
"$(…)"
- Hay un adicional
;
despuésthen
¿Cómo puedo saber? (bueno, por experiencia ☺) pero puedes probar Shellcheck . Pegue el código del libro (después de los asteriscos) y le mostrará los errores enumerados anteriormente más un "shebang faltante". Un script sin ningún error en Shellcheck es este:
#!/bin/sh
if [ "$(date +%d -d tomorrow)" = 01 ] ; then script.sh; fi
Ese sitio funciona porque lo que se escribió es "código shell". Esa es una sintaxis que funciona en muchos shells.
Algunos problemas que Shellcheck no menciona son:
Se supone que el comando date es la versión de fecha GNU. El que tiene una -d
opción que acepta tomorrow
como valor (busybox tiene una opción -d pero no comprende mañana y BSD tiene una -d
opción pero no está relacionada con la "visualización" de la hora).
Es mejor configurar el formato después de todas las opciones date -d tomorrow +'%d'
.
La hora de inicio del cron siempre es la hora local, lo que puede hacer que un trabajo comience 1 hora antes o después de un recuento exacto de días si el horario de verano (horario de verano) se configuró o no.
Lo que hicimos es un script de shell que podría llamarse con cron. Podemos modificar aún más el script para aceptar argumentos del programa o comando a ejecutar, de esta manera (finalmente, el código correcto):
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Llame a este script end_of_month.sh
y la llamada en cron es simplemente:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Eso ejecutaría el script end_of_month
(que verificará internamente que el día sea el último día del mes) solo los días 28, 29, 30 y 31. No hay necesidad de verificar el final del mes en ningún otro día.
Asegúrese de que se incluya la ruta correcta. La RUTA dentro del cron no será (probablemente) igual que la RUTA del usuario.
Tenga en cuenta que hay una secuencia de comandos de fin de mes probada (como se indica a continuación) que podría llamar a muchas otras utilidades o secuencias de comandos.
Esto también evitará el problema adicional que cron genera con la línea de comando completa:
- Cron divide la línea de comando en cualquiera,
%
incluso si se cita con '
o "
(solo \
funciona aquí). Esa es una forma común en la que fallan los trabajos cron.
Puede probar si el end_of_month.sh
script funciona correctamente en alguna fecha (sin esperar hasta el final del mes para descubrir que no funciona) probándolo con faketime:
$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....