Как имитировать работу cron

Я хочу запустить script один раз в день (и только по выходным дням), однако я не могу использовать для этого работу cron.

Я думал о том, чтобы иметь бесконечный цикл while, спать в течение 24 часов, проверить, является ли это выходным, и если это так, выполните script.

Какое это хорошее решение под bash на linux?

моя текущая реализация:

#! /bin/bash

 while [ true ]; do
    if [[ $(date +%u) -lt 6 ]]; then
               ./program
        else
             echo Today is a weekend, processing is skipped. Back to sleep.
    fi
    sleep  86400
done

И я запустил этот script в 17:00.

Ответы

Ответ 1

В тот же день, когда не было пользовательских crontab, я часто делал это с помощью (1).

#!/bin/sh
... do stuff...
at -f /path/to/me 5pm tomorrow

Таким образом, ваш script запускает и назначает себя для следующего вызова.

Я не думаю, что вы можете указать спецификацию "на следующий уик-энд", так что вам просто нужно будет перепланировать каждый день и выйти из вашего script (после планирования следующего на задании), если это не выходной.

Изменить: Или вместо планирования каждый день, узнайте, что сегодня есть и планируйте соответствующим образом. например.

day=Saturday
if [ $(date +%u) -eq 6 ] ; then day=Sunday ; fi
at -f /path/to/me 5pm next $day

Если этот script запущен в субботу, он планирует следующий прогон следующего воскресенья, иначе он будет работать в следующую субботу. [ $(date +%A) = Saturday ] может быть более читабельным, но% A предоставит строку, специфичную для локали, поэтому может не работать, если вы меняете локаль.

Ответ 2

Для решения Perl взгляните на Schedule::Cron Модуль CPAN:

use 5.012;
use warnings;
use Schedule::Cron;

my $cron = Schedule::Cron->new( sub {} );

# add weekend run @ 05:00 
$cron->add_entry('0 5 * * Sat,Sun', sub {
    system './program';
});

$cron->run();

Ответ 3

Проблема с использованием длинного sleep заключается в том, что ваша программная идея о том, во сколько времени она будет дрейфовать. Было бы лучше просто выполнить цикл с короткими периодами sleep и проверить, не находится ли вы в нужном окне.

Если ваши администраторы не позволяют использовать cron, они могут быть недовольны тем, что вы обходите это ограничение.

Однако здесь грубая схема:

while :
do
    dow=$(date +%u)
    if (( dow == 6 || dow == 7 ))
    # you can check a flag or counter to limit the number of times it performed
    # or use a more refined date spec than just whole days (times of day, in other words)
    then
        do_something
        sleep 1h    # or use a smaller or larger interval
    fi
done

Ответ 4

Предполагая, что вы действительно не можете использовать cron или при планировании заданий, вам нужно будет написать цикл сна. Информация о том, как вы его пишете, будет зависеть от ваших требований.

Если вы хотите только один раз в день, вам придется беспокоиться о коротких снах. Системный вызов сна, находящийся под большинством функций сна, не гарантирует, что он будет спать запрошенный промежуток времени. Ваша программа может спать немного дольше, чем требуется, или намного меньше запрошенной. Вы можете запланировать спящий режим в течение 24 часов, но ОС может разбудить вашу программу, чтобы доставить сигнал через несколько часов или даже через несколько секунд. Если вы не отслеживаете последний прогон или ваш следующий ожидаемый прогон, вы можете выполнять несколько раз в день.

Если вы хотите выполнить в определенное время, вам потребуется изменить время, в которое вы спите. Частичный сон может отключить вас на полдня, и вам нужно будет спать 12 часов, чтобы вернуться в синхронизацию.

Вам необходимо учитывать Летнее время/Летнее время. Один день в году будет 23 часа, а другой будет 25.

Вы можете использовать что-то вдоль линий этого псевдокода:

set next_time_to_run
loop forever
    sleep time_difference_in_seconds(current_time, next_time_to_run)
    if current_time is close to next_time_to_run
        execute code
        update next_time_to_run
    end if
end loop

Ответ 5

Вы можете использовать snaked. Он похож на cron, но написан на Perl.