абстрактный
Правильный код должен быть:
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Вызовите этот скрипт, end_of_month.sh
и вызов в cron просто:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Это запустит сценарий end_of_month
(который внутренне проверит, что день является последним днем месяца) только в дни 28, 29, 30 и 31. Нет необходимости проверять конец месяца в любой другой день.
Старый пост.
Это цитата из книги Ричарда Блюма «Командная строка Linux и библейские сценарии», Кристина Бреснахан, стр. 442, третье издание, John Wiley & Sons © 2015.
Да, это то, что говорится, но это неправильно / неполно:
- Отсутствует закрытие
fi
.
- Необходимо пространство между
[
и следующим `
.
- Он настоятельно рекомендуется использовать $ (...) вместо
`…`
.
- Важно использовать кавычки вокруг расширений, таких как
"$(…)"
- Есть дополнительный
;
послеthen
Откуда мне знать? (ну, по опыту ☺) но вы можете попробовать Shellcheck . Вставьте код из книги (после звездочек), и он покажет вам ошибки, перечисленные выше, плюс «недостающий шебанг». Сценарий без каких-либо ошибок в Shellcheck это:
#!/bin/sh
if [ "$(date +%d -d tomorrow)" = 01 ] ; then script.sh; fi
Этот сайт работает, потому что написано "код оболочки". Это синтаксис, который работает во многих оболочках.
Некоторые проблемы, которые не затрагивает shellcheck:
Предполагается, что команда date является версией даты GNU. Тот, у которого есть -d
опция, которая принимает tomorrow
в качестве значения (busybox имеет опцию -d, но не понимает завтра, а BSD имеет -d
опцию, но не связана с «отображением» времени).
Лучше установить формат после всех опций date -d tomorrow +'%d'
.
Время запуска cron всегда указывается по местному времени, что может означать, что одно задание запускается на 1 час раньше, чем точный счетчик дней, если установлено летнее время (DST) или не установлено.
То, что мы сделали, - это скрипт оболочки, который можно вызвать с помощью cron. Мы можем дополнительно изменить скрипт, чтобы он принимал аргументы программы или команды для выполнения, например так (наконец, правильный код):
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Вызовите этот скрипт, end_of_month.sh
и вызов в cron просто:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Это запустит сценарий end_of_month
(который внутренне проверит, что день является последним днем месяца) только в дни 28, 29, 30 и 31. Нет необходимости проверять конец месяца в любой другой день.
Убедитесь, что указан правильный путь. PATH внутри cron не будет (маловероятно) таким же, как пользовательский PATH.
Обратите внимание, что есть один протестированный скрипт на конец месяца (как указано ниже), который может вызывать многие другие утилиты или скрипты.
Это также позволит избежать дополнительной проблемы, которую cron генерирует с полной командной строкой:
- Cron разделяет командную строку на любую,
%
даже если она заключена в кавычки или '
или "
(только здесь \
работает). Это распространенный способ провалов заданий cron.
Вы можете проверить, end_of_month.sh
правильно ли работает скрипт на какой-либо дате (не дожидаясь конца месяца, чтобы обнаружить, что он не работает), протестировав его с помощью faketime:
$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....