Leí de una instrucción para programar un guión el último día del mes:
Nota:
El lector astuto podría estar preguntándose cómo podría configurar un comando para que se ejecute el último día de cada mes porque no puede configurar el valor de dayofmonth para cubrir cada mes. Este problema ha afectado a los programadores de Linux y Unix, y ha generado varias soluciones diferentes. Un método común es agregar una instrucción if-then que use el comando date para verificar si la fecha de mañana es 01:00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command1
Esto verifica todos los días a las 12 del mediodía para ver si es el último día del mes, y si es así, cron ejecuta el comando.
Como [`date +%d -d tomorrow` = 01 ]
funciona
¿Es correcto declarar then; command1
?
shell-script
cron
date
test
Cálculo
fuente
fuente
; endif
?[
y nofi
al final. Además,%
es especial en crontabs.Respuestas:
Resumen
El código correcto debería ser:
Llame a este script
end_of_month.sh
y la llamada en cron es simplemente: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:
fi
.[
y lo siguiente`
.`…`
."$(…)"
;
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 aceptatomorrow
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):
Llame a este script
end_of_month.sh
y la llamada en cron es simplemente: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:
%
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:fuente
date
(o eldate
incorporado de ksh93 si ksh93 fue construido como parte de ast-open) admitedate -d tomorrow +%s
odate +%s tomorrow
).* * * * * echo "$(date -u +'date %c')" >>~/testfile
no funcionará porque uno olvidó citar el\%
(que se vuelve difícil de depurar si solo es posible un intento cada mes). @KusalanandaSuponiendo que los errores de sintaxis son fijos, y el comando se reformuló ligeramente para ser menos detallado:
Esto se ejecuta
date +%d -d tomorrow
(suponiendo que sedate
utilice GNU ) para obtener la fecha de mañana como un número de dos dígitos. Si el número no es01
, entonces hoy no es el último día del mes. En ese caso, las pruebas tiene éxito ycommand1
se no ejecutados. El trabajo se ejecuta al mediodía en los días que posiblemente podrían ser el último día del mes.El comando original:
Esto tiene algunos problemas:
[
.;
directamente despuésthen
.%
es especial en las especificaciones de trabajo cron y debe escaparse como\%
(verman 5 crontab
).fi
al final que coincida con elif
.fuente
[ ... ] && command1
lugar deif...
es que en los días que no son el último día del mes, el trabajo cron finalizará con un estado de salida distinto de cero y es posible que deba informarse de ese error . Usar[ "$(...)" != 01 ] || command1
es otra forma de evitar el problema.;
entrethen
ycommand1
."
o'
(excepto\
), el signo de porcentaje%
hará que cron rompa la línea en dos partes. Esa es una forma habitual de hacer que cron falle.Para programar el último día de cada mes, puede intentar:
0 0 15,L * *
.fuente