Анотація
Правильний код повинен бути:
#!/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....