Як запустити роботу cron всередині контейнера docker?


275

Я намагаюся запустити cronjob всередині контейнера docker, який викликає сценарій оболонки.

Вчора я шукав по всьому Інтернету і переповнював стеки, але не міг знайти рішення, яке працює.
Як я можу це зробити?

Редагувати:

Я створив (прокоментував) сховище github з робочим контейнером cron-докера, який викликає скрипт оболонки через заданий інтервал.

Відповіді:


365

Ви можете скопіювати свій crontab у зображення, щоб контейнер, запущений із зазначеного зображення, виконував завдання.

Дивіться " Робота з крон з Докером " від Жульєна Булай у його статті Ekito/docker-cron:

Створимо новий файл під назвою " hello-cron" для опису нашої роботи.

* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.

Наступний Dockerfile описує всі кроки зі створення вашого зображення

FROM ubuntu:latest
MAINTAINER docker@ekito.fr

RUN apt-get update && apt-get -y install cron

# Copy hello-cron file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron

# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron

# Apply cron job
RUN crontab /etc/cron.d/hello-cron

# Create the log file to be able to run tail
RUN touch /var/log/cron.log

# Run the command on container startup
CMD cron && tail -f /var/log/cron.log

(Див Gaafar «сек коментар і Як зробити apt-getустановку менш шумним? :
apt-get -y install -qq --force-yes cronМоже працювати теж)

Як зазначив у коментарях Натан Ллойд :

Коротка примітка про gotcha:
Якщо ви додаєте файл сценарію і говорите cron запустити його, пам’ятайте, що Cron виходить з ладу, якщо ви забудете .
RUN chmod 0744 /the_script


АБО, переконайтеся , що ваша робота сама переадресувати безпосередньо на стандартний висновок / STDERR замість лог - файл, як описано в hugoShaka «s відповідь :

 * * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2

Замініть останній рядок Dockerfile на

CMD ["cron", "-f"]

Дивіться також (про cron -f, що означає cron "передній план") " docker ubuntu cron -fне працює "


Побудуйте та запустіть:

sudo docker build --rm -t ekito/cron-example .
sudo docker run -t -i ekito/cron-example

Будьте терплячі, почекайте 2 хвилини, і ваш командний рядок повинен відображати:

Hello world
Hello world

Ерік додає в коментарях :

Зверніть увагу, що tailможе не відображатися правильний файл, якщо він створений під час створення зображення.
Якщо це так, вам потрібно створити або торкнутися файлу під час виконання контейнера, щоб хвіст зібрав правильний файл.

Див. " Виведення tail -fв кінці докера CMDне відображається ".


1
Я мав спочатку встановити cron, оскільки він не входить. Але додавши це до Dockerfile, це працює. Дякую! RUN apt-get update && apt-get install cron
C Heyer

2
вам, мабуть, слід додати -yвстановлення cron, щоб уникнути виходу збірки докерів
gafi

1
@Gaafar Правильно! Я включив ваш коментар у відповідь для більшої наочності та додав ще один варіант.
VonC

6
Чи все ще працює це рішення? Коли я дотримуюсь наведених вказівок, коли я входжу в контейнер як корінь та тип crontab -l, я не встановлюю crontab для root , а також мій екран залишається порожнім. Однак, коли я перевіряю '/etc/cron.d/', я бачу, що файл crontab є там (і ще дивніше), коли я перевіряю /var/log/cron.log, я бачу, що сценарій працює (додається вміст файлу Hello World). Я потягнувши цей образ в моєму Dockerfile: FROM phusion/baseimage:0.10.0. Будь-які уявлення про розбіжність у поведінці?
Homunculus Reticulli

11
Станом на 2018 рік такий підхід вже не працює; хтось міг домогтися своєї роботи на Ubuntu як базового зображення? Мене не цікавить альпійський образ, який поставляється із кроном, котрий закінчується
пелікан

147

Прийняте рішення може бути небезпечним у виробничих умовах .

У докері вам слід виконати лише один процес на контейнер, тому що якщо цього не зробити, процес, який розщедрився та перейшов фон, не контролюється і може зупинитися, не знаючи про це.

Коли ви використовуєте CMD cron && tail -f /var/log/cron.logпроцес cron в основному fork для виконання cronу фоновому режимі, основний процес виходить з роботи і дозволяє виконувати tailfна передньому плані. Процес фонового крона може зупинитися або вийти з ладу, якого ви не помітите, ваш контейнер все ще буде працювати безшумно, а ваш інструмент для оркестрування не перезапустить його.

Ви можете уникнути подібного, перенаправляючи безпосередньо команди команд cron у ваш докер stdoutі stderrякі розташовані відповідно у /proc/1/fd/1та /proc/1/fd/2.

Використовуючи основні переадресації оболонки, можливо, ви хочете зробити щось подібне:

* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2

І ваш CMD буде: CMD ["cron", "-f"]


14
Приємно: cron -fє для "cron foreground". Я включив вашу відповідь у моє вище, для більшої наочності. +1
VonC

Скажімо, моя програма нічого не дає. Чи можу я все-таки використовувати цей метод і бути впевненим, що мій процес не зупиниться у фоновому режимі?
Арсектор

1
@Arcsector Цей метод уникає відтворення процесу на задньому плані, ось чому він не виходить з ладу. Фоновий процес у контейнері докера не простий. Якщо ви хочете мати запущений фоновий процес, ви можете скористатися процесом init для контролю кількох процесів, які ви запускаєте в контейнері. Інший спосіб - запустити процес в інший контейнер поруч з основним, який називається "коляска". Найкращий спосіб - це уникати декількох процесів у контейнері.
hugoShaka

Приємно і чисто! Love it :)
AmaelH

1
Це хороше рішення і добре працює для нас, окрім одного питання. Коли контейнер отримує сигнал SIGTERM, він, схоже, не чекає завершення запланованого процесу та витонченого завершення роботи, натомість він вбиває процес, який може спричинити проблеми.
Джеймс Хулз

107

Для тих, хто хоче скористатися простим і легким зображенням:

FROM alpine:3.6

# copy crontabs for root user
COPY config/cronjobs /etc/crontabs/root

# start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]

Де cronjobs - це файл, який містить ваші cronjobs, у такій формі:

* * * * * echo "hello stackoverflow" >> /test_file 2>&1
# remember to end this file with an empty new line

10
Просте, легке та стандартне зображення. Це має бути прийнятою відповіддю. Також використовуйте > /proc/1/fd/1 2> /proc/1/fd/2перенаправлення, щоб отримати доступ до виводу кронштейнів безпосередньо з журналів докер.
HenriTel

2
Для людей, які не використовують альпійський: crond, що підтримує -d 8параметр, не є стандартним cron, це команда crond з busybox. Наприклад, з ubuntu, ви можете запустити це як busybox crond -f -d 8. Для старих версій, які ви повинні використовувати -L /dev/stdout/.
Trendfischer

2
Я дав би це +100, якби міг. Це, безумовно, найкращий спосіб запускати крон-завдання в середовищі Докера.
Джитсусама

1
Якщо ви не хочете створювати нове зображення щоразу, коли ви змінюєте завдання cron (або якщо вам потрібно кілька), ви можете просто запустити Alpine і використовувати гучність для встановлення крона. Я перевірив його, використовуючи наступне: docker run -v ${PWD}/cronjobs:/etc/crontabs/root alpine:3.6 crond -f -d 8. @Groostav ви можете використовувати подібну річ у Docker Compose.
подвійність_

1
CMD ["crond"або CMD ["cron"?
кодек

38

Те, що запропонував @VonC, добре, але я вважаю за краще робити конфігурацію роботи в одному рядку. Це дозволить уникнути проблем із міжплатформою, як-от розташування cronjob, і вам не потрібен окремий файл cron.

FROM ubuntu:latest

# Install cron
RUN apt-get -y install cron

# Create the log file to be able to run tail
RUN touch /var/log/cron.log

# Setup cron job
RUN (crontab -l ; echo "* * * * * echo "Hello world" >> /var/log/cron.log") | crontab

# Run the command on container startup
CMD cron && tail -f /var/log/cron.log

Запустивши контейнер докера, ви можете переконатися, що служба cron працює:

# To check if the job is scheduled
docker exec -ti <your-container-id> bash -c "crontab -l"
# To check if the cron service is running
docker exec -ti <your-container-id> bash -c "pgrep cron"

Якщо ви віддаєте перевагу мати ENTRYPOINT замість CMD, тоді ви можете замінити CMD вище

ENTRYPOINT cron start && tail -f /var/log/cron.log

1
Цікава альтернатива. +1
VonC

2
RUN apt-get update && apt-get -y install cronінакше він не зможе знайти пакунокcron
alphabetasoup

2
Дякую Юнес, ти дав мені ідею зробити наступне, що працювало в моєму випадку, коли кожен крон вказаний в іншому файлі: RUN cat $APP_HOME/crons/* | crontab Як принадність :)
marcostvz

додавання cronдо сценарію вхідної точки здається найкращим варіантом: ENTRYPOINT ["entrypoint.sh"]
bozdoz

20

Є ще один спосіб зробити це - використовувати Tasker , завдань, який підтримує cron (планувальник).

Чому? Іноді, щоб запустити роботу cron, вам доведеться змішати ваше базове зображення (python, java, nodejs, ruby) з кроном. Це означає, що потрібно підтримувати інший образ. Завдання уникнути цього, від’єднавши кульку та контейнер. Ви можете просто зосередитись на зображенні, яке ви хочете виконати, і налаштувати Tasker для його використання.

Ось docker-compose.ymlфайл, який виконує деякі завдання для вас

version: "2"

services:
    tasker:
        image: strm/tasker
        volumes:
            - "/var/run/docker.sock:/var/run/docker.sock"
        environment:
            configuration: |
                logging:
                    level:
                        ROOT: WARN
                        org.springframework.web: WARN
                        sh.strm: DEBUG
                schedule:
                    - every: minute
                      task: hello
                    - every: minute
                      task: helloFromPython
                    - every: minute
                      task: helloFromNode
                tasks:
                    docker:
                        - name: hello
                          image: debian:jessie
                          script:
                              - echo Hello world from Tasker
                        - name: helloFromPython
                          image: python:3-slim
                          script:
                              - python -c 'print("Hello world from python")'
                        - name: helloFromNode
                          image: node:8
                          script:
                              - node -e 'console.log("Hello from node")'

Там є три завдання, усі вони будуть працювати щохвилини ( every: minute), і кожне з них виконуватиме scriptкод, усередині зображення, визначеного вimage розділі.

Просто запустіть docker-compose upі побачите, як це працює. Ось репортаж Tasker з повною документацією:

http://github.com/opsxcq/tasker


Докерцепція (запуск докерних контейнерів з іншого контейнера) є поганою практикою і повинна обмежуватися постійною інтеграцією. Приблизним рішенням буде використання docker execпевних контейнерів.
HenriTel

1
Tasker не використовує docker в docker (Dind / Dockerception), зауважте, що передається гніздо докера як відображення, всі породжені контейнери знаходяться в породі демона, на якому працює запускник. І якщо ви не хочете запускати задачу в докер, ви можете просто розгорнути його як будь-який інший додаток.
OPSXCQ

1
Я не отримую переваг використання Tasker. Мені здається, надмірна навантаження за допомогою java та sh *** просто для того, щоб запустити роботу з крон.
Карл Адлер

Змішування крона та базового зображення, яке вам потрібно (наприклад, python / node), створює додаткову залежність, яку потрібно підтримувати та розгортати, за цим сценарієм усі завдання мають один і той же контейнер, це означає, що вам доведеться турбуватися про очищення всього після кожна робота працює. Роботи, які працюють на завданні, є безсильними, тому вам доведеться менше турбуватися.
OPSXCQ

13

Відповідь VonC досить ґрунтовна. Крім того, я хотів би додати одне, що мені допомогло. Якщо ви просто хочете запустити завдання cron, не вкладаючи файл, ви будете спокушені просто видалити && tail -f /var/log/cron.logкоманду cron.

Однак це призведе до того, що контейнер Docker вийде незабаром після запуску, оскільки після завершення команди cron Докер вважає, що остання команда закінчилася і, отже, вбиває контейнер. Цього можна уникнути, запустивши крон на передньому плані через cron -f.


9

Хоча це спрямовано на виконання завдань поруч із запущеним процесом у контейнері через Docker's exec інтерфейс , це може зацікавити вас.

Я написав демон, який спостерігає за ними контейнери та планує завдання, визначені в їх метаданих. Приклад:

version: '2'

services:
  wordpress:
    image: wordpress
  mysql:
    image: mariadb
    volumes:
      - ./database_dumps:/dumps
    labels:
      deck-chores.dump.command: sh -c "mysqldump --all-databases > /dumps/dump-$$(date -Idate)"
      deck-chores.dump.interval: daily

Можливо також "класичне", схоже на крон конфігурацію.

Ось документи , ось сховище зображень .


Дякую. Ця відповідь найбільш правильна для середовища контейнерів Docker. Жодних змін у зображеннях Докера немає, лише додаючи спеціальний контейнер для виконання завдань, він працює як команда docker exec <container_name> <some_command>за графіком.
PRIHLOP

Це найпростіша найпростіша відповідь "виконати роботу".
Ібрагім Авад

9

Я створив зображення Докера на основі інших відповідей, які можна використовувати як

docker run -v "/path/to/cron:/etc/cron.d/crontab" gaafar/cron

де /path/to/cron: абсолютний шлях до файлу crontab, або ви можете використовувати його як базу в Dockerfile:

FROM gaafar/cron

# COPY crontab file in the cron directory
COPY crontab /etc/cron.d/crontab

# Add your commands here

Для довідки, зображення тут .


Цікавий образ. +1
VonC

5

Коли ви розгортаєте контейнер на іншому хості, просто зауважте, що він не запустить жодних процесів автоматично. Вам потрібно переконатися, що служба "cron" працює у вашому контейнері. У нашому випадку я використовую Supervisord разом з іншими службами для запуску служби cron.

[program:misc]
command=/etc/init.d/cron restart
user=root
autostart=true
autorestart=true
stderr_logfile=/var/log/misc-cron.err.log
stdout_logfile=/var/log/misc-cron.out.log
priority=998

Я отримую помилку в supervisor.log, що служба керування зупинялася кілька разів і перейшла у стан FATAL. Однак, схоже, cron працює вгорі і виконує роботу cronjobs як правило. Дякую за це!
lephleg

Так, те саме трапилося і зі мною, але воно працює як нормально, тому не потрібно турбуватися.
Sagar Ghuge

5

Визначте cronjob у спеціальному контейнері, який виконує команду через docker exec до вашої служби.

Це вища згуртованість і запущений скрипт матиме доступ до змінних оточення, які ви визначили для своєї послуги.

#docker-compose.yml
version: "3.3"
services:
    myservice:
      environment:
        MSG: i'm being cronjobbed, every minute!
      image: alpine
      container_name: myservice
      command: tail -f /dev/null

    cronjobber:
     image: docker:edge
     volumes:
      - /var/run/docker.sock:/var/run/docker.sock
     container_name: cronjobber
     command: >
          sh -c "
          echo '* * * * * docker exec myservice printenv | grep MSG' > /etc/crontabs/root
          && crond -f"

Мені не вдалося змусити це працювати за допомогою докерського рою. Отримання myservice unknownпомилок.
Марк Гримс

Повинно бути попередження про високу безпеку для встановлення гнізда докера
випадковий

4

Якщо ви використовуєте docker для Windows, пам’ятайте, що вам потрібно змінити формат закінчення рядка з CRLF на LF (тобто з dos до unix), якщо ви збираєтесь імпортувати файл crontab з Windows у ваш контейнер ubuntu. Якщо ні, то ваша робота не працюватиме. Ось робочий приклад:

FROM ubuntu:latest

RUN apt-get update && apt-get -y install cron
RUN apt-get update && apt-get install -y dos2unix

# Add crontab file (from your windows host) to the cron directory
ADD cron/hello-cron /etc/cron.d/hello-cron

# Change line ending format to LF
RUN dos2unix /etc/cron.d/hello-cron

# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron

# Apply cron job
RUN crontab /etc/cron.d/hello-cron

# Create the log file to be able to run tail
RUN touch /var/log/hello-cron.log

# Run the command on container startup
CMD cron && tail -f /var/log/hello-cron.log

Це фактично зайняло у мене години, щоб розібратися, так як налагодження роботи Cron у контейнерах докера - це копітка задача. Сподіваюся, це допомагає комусь іншому там, хто не може змусити свій код працювати!


3

З наведених вище прикладів я створив таке поєднання:

Альпійські зображення та редагування за допомогою Crontab у Нано (ненавиджу vi)

FROM alpine

RUN apk update
RUN apk add curl nano

ENV EDITOR=/usr/bin/nano 

# start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]

# Shell Access
# docker exec -it <CONTAINERID> /bin/sh

# Example Cron Entry
# crontab -e
# * * * * * echo hello > /proc/1/fd/1 2>/proc/1/fd/2
# DATE/TIME WILL BE IN UTC

2

Налаштуйте крон паралельно одноразовій роботі

Створіть файл сценарію, скажімо run.sh, із завданням, яке повинно виконуватися періодично.

#!/bin/bash
timestamp=`date +%Y/%m/%d-%H:%M:%S`
echo "System path is $PATH at $timestamp"

Збережіть і вийдіть.

Використовуйте Entrypoint замість CMD

Якщо у вас є кілька завдань, які потрібно розпочати під час контейнерної докері, використовуйте файл вхідних даних, щоб запустити їх усі.

Файл вступу - це файл сценарію, який вступає в дію при видачі команди запуску докера. Отже, всі кроки, які ми хочемо виконати, можна помістити в цей файл сценарію.

Наприклад, у нас є 2 завдання для запуску:

Запустити один раз завдання : відлуння "Контейнер Docker запущений"

Виконайте періодичну роботу : run.sh

Створіть entrypoint.sh

#!/bin/bash

# Start the run once job.
echo "Docker container has been started"

# Setup a cron schedule
echo "* * * * * /run.sh >> /var/log/cron.log 2>&1
# This extra line makes it a valid cron" > scheduler.txt

crontab scheduler.txt
cron -f

Давайте розберемося з кронтабом, який було встановлено у файлі

* * * * *: Графік Cron; робота повинна працювати щохвилини. Ви можете оновити графік, виходячи зі своєї вимоги.

/run.sh: Шлях до файлу сценарію, який потрібно запускати періодично

/var/log/cron.log: Ім'я файлу для збереження виводу запланованого завдання cron.

2>&1: Журнали помилок (якщо такі є) також будуть перенаправлені на той самий вихідний файл, який використовується вище.

Примітка . Не забудьте додати додатковий новий рядок, оскільки це робить його дійсним кроном. Scheduler.txt: повна установка крона буде переспрямована у файл.

Використання змінних середовища / специфічного для користувача середовища в cron

Моє фактичне завдання cron очікувало більшості аргументів, оскільки змінні середовища переходили до команди run docker. Але, з bash, я не зміг використати жодну із змінних оточення, що належать до системи або контейнера докера.

Потім це було вирішенням цієї проблеми:

  1. Додайте наступний рядок у entrypoint.sh
declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env
  1. Оновіть установку cron і вкажіть-
SHELL=/bin/bash
BASH_ENV=/container.env

Нарешті, ваше entrypoint.shмає виглядати так

#!/bin/bash

# Start the run once job.
echo "Docker container has been started"

declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env

# Setup a cron schedule
echo "SHELL=/bin/bash
BASH_ENV=/container.env
* * * * * /run.sh >> /var/log/cron.log 2>&1
# This extra line makes it a valid cron" > scheduler.txt

crontab scheduler.txt
cron -f

І останнє, але не менш важливе: створіть Dockerfile

FROM ubuntu:16.04
MAINTAINER Himanshu Gupta

# Install cron
RUN apt-get update && apt-get install -y cron

# Add files
ADD run.sh /run.sh
ADD entrypoint.sh /entrypoint.sh

RUN chmod +x /run.sh /entrypoint.sh

ENTRYPOINT /entrypoint.sh

Це воно. Побудувати та запустити зображення Docker!


1
@himanshuIIITian Я спробував це, проблема полягає в тому, що сценарій "запустити один раз роботу" ніколи не повертається, а також і кукурудза -f не повертається так ... це не працює для мене, будь-які ідеї? дякую
Дорон Леві

@DoronLevi - чи можете ви поділитися журналами, щоб переглянути проблему? Або ви можете перевірити весь код звідси - github.com/nehabhardwaj01/docker-cron
himanshuIIITian

Дякуємо за відгук. Я радий, що відповідь була корисною.
himanshuIIITian

1

Завдання Cron зберігаються в / var / spool / cron / crontabs (Загальне місце у всіх відомих мені дистрибутивах). До речі, ви можете створити вкладку cron в bash, використовуючи щось подібне:

crontab -l > cronexample
echo "00 09 * * 1-5 echo hello" >> cronexample
crontab cronexample
rm cronexample

Це створить тимчасовий файл із завданням cron, а потім запрограмує його за допомогою crontab. Останній рядок видалити тимчасовий файл.


cronДемон зазвичай не працює в контейнері.
Метт

@BhargavNanekalva це потрібно спеціально встановити в контейнер, на який ця відповідь не звертається.
Метт

@Matt, чи не могли б ви вказати, як саме його слід вказати в контейнері? . Я роблю crontab -l і показана команда - kagda.ru/i/6d014816d43_29-06-2017-11:38:59_6d01.png, але все ще не запускається
Tebe

@ Копать_Шо_я_нашел Вам потрібно бігти crond крім служби, яку ви запускаєте в контейнері, як правило, з диспетчером сервісів, як s6. Напевно, задайте це як питання, щоб отримати належну відповідь
Метт

1

Під час запуску деяких обрізаних зображень, що обмежують кореневий доступ, мені довелося додати свого користувача до судерів і запустити як sudo cron

FROM node:8.6.0
RUN apt-get update && apt-get install -y cron sudo

COPY crontab /etc/cron.d/my-cron
RUN chmod 0644 /etc/cron.d/my-cron
RUN touch /var/log/cron.log

# Allow node user to start cron daemon with sudo
RUN echo 'node ALL=NOPASSWD: /usr/sbin/cron' >>/etc/sudoers

ENTRYPOINT sudo cron && tail -f /var/log/cron.log

Можливо, це комусь допомагає


Я вважаю, що зображення вузла використовує користувач вузла; тому, можливо, вам потрібно було додати дозволи для цього користувача
bozdoz

1

Отже, моя проблема була однаковою. Виправленням було зміна командного розділу в docker-compose.yml.

З

команда: crontab / etc / crontab && tail -f / etc / crontab

До

команда: crontab / etc / crontab

команда: хвіст -f / etc / crontab

Проблема була «&&» між командами. Після видалення цього все було добре.


-1

Найбільш надійний спосіб, який я знайшов поки що, це запустити незалежний контейнер cron - встановити клієнт докера та прив’язати кріплення шкарпетки докера, щоб ви могли поговорити з сервером докера на хості.

Тоді просто використовуйте env vars для кожного завдання cron та сценарій вхідної точки для створення / etc / crontab

Ось зображення, яке я створив, використовуючи цей принцип і використовуючи його у виробництві протягом останніх 3-4 років.

https://www.vip-consult.solutions/post/better-docker-cron#content


Відповіді мають бути самостійними та не мати посилання на зовнішні ресурси
Nicolas Bouliane

-2

Спробуйте використовувати дорогоцінний камінь для годинника для планування завдань. Дотримуйтесь кроків, наведених у цьому посиланні.

http://fuzzyblog.io/blog/rails/2017/05/11/adding-cron-to-a-dockerized-rails-application-using- clockwork.html

Ви можете викликати завдання граблі у файлі lib / clock.rb, як показано нижче.

every(1.day, 'Import large data from csv files', :at => '5:00') do |job|
  `rake 'portal:import_data_from_csv'`
end

Створіть окремий контейнер у файлі докер-композиції та запустіть команду нижче всередині контейнера.

command: bundle exec clockwork lib/clock.rb

1
Хороша ідея використовувати якийсь інший інструмент для планування. Однак це запитання було задано спеціально для cron, тому Вашу пропозицію було б краще, як коментар до питання, на мою думку.
Річард Кіфер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.