Анотація
Правильний код повинен бути:
#!/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
Цей сайт працює, тому що те, що було написано - "код оболонки". Це синтаксис, який працює у багатьох оболонках.
Деякі проблеми, які шелчек не згадує, є:
Передбачається, що команда дата є версією дати GNU. Той, у якому є -dпараметр, який приймає tomorrowяк значення (busybox має опцію -d, але не розуміє завтра, а BSD має -dваріант, але не пов'язаний з "відображенням" часу).
Краще встановити формат після всіх варіантів date -d tomorrow +'%d'.
Час запуску крона завжди знаходиться за місцевим часом, що може зробити одне завдання на 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 розбиває командний рядок на будь-який,
%навіть якщо його цитують 'або "( \тут працює лише твір). Це звичайний спосіб, коли крон не працює.
Ви можете перевірити, чи end_of_month.shправильно працює скрипт на якусь дату (не чекаючи кінця місяця, щоб виявити, що він не працює), перевіривши його за факетом:
$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....