Я хочу выполнить сценарий оболочки буквально после каждых 3 дней. Используя crontab с 01 00 */3 * *
на самом деле не выполнит условие, потому что оно работало бы 31-й и с другой стороны в 1-й день месяца. */3
синтаксис совпадает с высказыванием 1,4,7... 25,28,31.
Должны быть способы заставить сам сценарий проверить условия и выход, если 3 дня не передали. Таким образом, crontab каждый день выполняет сценарий, но сам сценарий проверил бы, передали ли 3 дня.
Я даже нашел некоторый код, но он дал мне синтаксическую ошибку, любая справка будет цениться.
if (! (date("z") % 3)) {
exit;
}
main.sh: line 1: syntax error near unexpected token `"z"'
main.sh: line 1: `if (! (date("z") % 3)) {'
Чтобы сразу прервать и выйти из сценария, если последнее выполнение еще не было, по крайней мере, определенное время назад, Вы могли бы использовать этот метод, который требует внешнего файла, который хранит последнюю дату и время выполнения.
Добавьте эти строки к верхней части Вашего сценария Bash:
#!/bin/bash
# File that stores the last execution date in plain text:
datefile=/path/to/your/datefile
# Minimum delay between two script executions, in seconds.
seconds=$((60*60*24*3))
# Test if datefile exists and compare the difference between the stored date
# and now with the given minimum delay in seconds.
# Exit with error code 1 if the minimum delay is not exceeded yet.
if test -f "$datefile" ; then
if test "$(($(date "+%s")-$(date -f "$datefile" "+%s")))" -lt "$seconds" ; then
echo "This script may not yet be started again."
exit 1
fi
fi
# Store the current date and time in datefile
date -R > "$datefile"
# Insert your normal script here:
Не забывайте устанавливать значимое значение как datefile=
и адаптируйте значение seconds=
к Вашим потребностям ($((60*60*24*3))
оценивает к 3 дням).
Если Вы не хотите отдельный файл, Вы могли бы также сохранить прошлое время выполнения в штампе времени изменения Вашего сценария. Это означает однако, что внесение любых изменений в Ваш файл сценария сбросит эти 3 счетчика и рассматриваться как то, если сценарий успешно работал.
Для реализации этого добавьте отрывок ниже к вершине файла сценария:
#!/bin/bash
# Minimum delay between two script executions, in seconds.
seconds=$((60*60*24*3))
# Compare the difference between this script's modification time stamp
# and the current date with the given minimum delay in seconds.
# Exit with error code 1 if the minimum delay is not exceeded yet.
if test "$(($(date "+%s")-$(date -r "$0" "+%s")))" -lt "$seconds" ; then
echo "This script may not yet be started again."
exit 1
fi
# Store the current date as modification time stamp of this script file
touch -m -- "$0"
# Insert your normal script here:
Снова, не забывайте адаптировать значение seconds=
к Вашим потребностям ($((60*60*24*3))
оценивает к 3 дням).
Во-первых, приведенный выше фрагмент кода имеет недопустимый синтаксис Bash, выглядит как Perl. Во-вторых, параметр z
для date
заставляет его выводить числовой часовой пояс. +%j
номер дня. Вам нужно:
if [[ ! $(( $(date +%j) % 3 )) ]] ;then
exit
fi
Но вы все равно увидите странность в конце года:
$ for i in 364 365 1 ; do echo "Day $i, $(( $i % 3 ))"; done
Day 364, 1
Day 365, 2
Day 1, 1
Возможно, вам повезет больше с ведением счета в файле и тестированием / обновить это.
Если можно просто оставить сценарий, работающий постоянно, Вы могли бы сделать:
while true; do
[inert code here]
sleep 259200
done
Этот цикл всегда верен, таким образом, он будет всегда выполнять код, затем ожидать в течение трех дней прежде, чем запустить цикл снова.
Вы можете использовать анакрон вместо cron, он предназначен именно для того, чтобы делать то, что вам нужно. С man-страницы:
Anacron может использоваться для периодического выполнения команд с частотой, указанной в днях. В отличие от cron (8), он не предполагает, что машина работает непрерывно. Следовательно, его можно использовать на машинах, которые не работают 24 часа в сутки, для контроля ежедневных, еженедельных и ежемесячных заданий, которые обычно контролируются cron.
При выполнении Anacron считывает список заданий из файла конфигурации, обычно это / etc / anacrontab (см. Anacrontab (5)). Этот файл содержит список заданий, которые контролирует Anacron. Каждая запись задания указывает период в днях, задержку в минутах, уникальный идентификатор задания и команду оболочки.
Для каждого задания Anacron проверяет, было ли это задание выполнено за последние n дней, где n - период, указанный для этого задания. Если нет, Anacron запускает команду оболочки задания, ожидая количества минут, указанных в качестве параметра задержки.
После выхода из команды Anacron записывает дату в специальный файл метки времени для этого задания, чтобы он мог знать, когда его выполнить снова. Только дата используется для расчета времени. Час не используется.
BLOCKQUOTE>
Крон действительно является неправильным инструментом для этого. Существует на самом деле наиболее часто используемый и underloved инструмент, в который заходят, который мог бы работать. at's, главным образом разработанный для интерактивного использования и я уверен, что кто-то нашел бы лучший способ сделать это.
В моем случае у меня был бы скрипт, который я запускаю перечисленный в testjobs.txt и включаю строку, которая читает.
Как пример, у меня было бы это как testjobs.txt
echo "cat" >> foo.txt
date >> foo.txt
at now + 3 days < testjobs.txt
У меня есть две невинных команды, которые могли бы быть Вашими сценариями оболочки. Я выполняю эхо, чтобы удостовериться, что у меня есть детерминированный вывод и дата для подтверждения выполнений команды по мере необходимости. Когда при выполнениях эта команда, это закончится путем добавления нового задания к в в течение 3 дней. (Я протестировал с одной минутой - который работает),
Я вполне уверен, я буду вызван для способа, в котором я злоупотребил, но это - удобный инструмент для планирования команды, которая будет выполнена за один раз или x дни после предыдущей команды.