Як я можу програматично створити нову роботу з cron?


129

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

З мого дослідження , здається, я міг би скинути поточний crontab, а потім додати новий, перекочуючи його назад у crontab:

(crontab -l ; echo "0 * * * * wget -O - -q http://www.example.com/cron.php") | crontab -

Чи є кращий спосіб?


2
Ваше рішення здається хорошим.
Крейг S

На Solaris просто зніміть тире для останнього кронтабу. Ви можете додати греп, щоб уникнути додавання рядка.
lacroix1547


фігурні дужки замість дужок будуть робити це без нерестування процесу. Не забудьте залишити пробіли навколо брекетів, {...; }.
Джей Вінстон

Відповіді:


-25

Це завжди добре працювало для мене.

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

  1. Додайте лінію кронтабу; запевняючи, що його не існувало. Додавання, коли воно вже є, погано.

  2. Видаліть лінію crontab. Можливо, лише попередження, якщо його не існувало.

  3. Поєднання перерахованих вище двох можливостей для заміни лінії crontab.


78
Він запитує, як і ти йому що?
Серін

1
Що робити, якщо користувач ще не має кронтабу?
Максим Єгорушкін

132

Найкращий спосіб, якщо ви працюєте як root, - це скинути файл у /etc/cron.d

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

Ім'я файлу: /etc/cron.d/per_minute

Зміст: * * * * * root /bin/sh /home/root/script.sh


5
Просто переконайтеся, що версія cron у використанні підтримує /etc/cron.d/. Більшість сучасних дистрибутивів Linux.
sleske

8
Це найпростіше, найелегантніше рішення. Впевнені удари, які повинні розібрати та відредагувати наявний crontab з іншими не пов'язаними записами.
Серін

13
Одним із можливих застережень до цього є частота, з якою крон збирає нові доповнення до цієї папки (один раз на годину). Якщо ви очікуєте, що ваша робота почне працювати відразу, будьте обережні.
JonathanK

6
@JonathanK, чи знаєте ви, чи можна попросити cron повторно сканувати /etc/cron.d/*? Важко дізнатися, чи щось працює, якщо треба чекати годину, щоб перевірити!
півзахисник

4
як слід встановити для цього файлу хімічні речовини? chmod + x /etc/cron.d/per_minute?
giò

101

Рішення OP має помилку, воно може дозволити додавати записи двічі, скористайтеся нижче, щоб виправити.

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -

5
Це насправді краще, якщо не описане рішення. Це гарантує, що команда не додається двічі до crontab.
Bufke

2
Це навряд чи вдале виправлення для запису дублікатів. Що робити, якщо тим часом до crontab було додано ще один рядок?
hmn

6
Щоб забезпечити унікальність, безпосередньо sortперед цим uniq, наприклад:(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
mway

6
Не потрібно uniq. Використовуйте -uопцію на sort.
папіро

6
Як уникнути відсутності crontab для користувача під час першого редагування crontab.
wyx

23

Щоб додати щось у cron

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | sort | uniq | crontab -

Щоб вилучити це з cron

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | grep -v hupChannel.sh |  sort | uniq | crontab -

сподівання допоможе комусь


Це саме те, що я шукав, я просто додам це: | grep -v '^ #' | щоб відфільтрувати коментарі
Тюнкі

2
Насправді вам не потрібно, 2>&1 | grep -v "no crontab"тому що коли немає crontab, вихідний рядок crontab: no crontab for...надсилається до stderr. Немає причин захоплювати цей вихід, надсилати його до stdout, а потім відфільтрувати за допомогою grep. Якщо ваша мета - уникнути появи crontab: no crontab for...у ваших результатах, тоді використовуйте 2> /dev/null | sort.....
матовий

6

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


6

Просто змініть редактор на команду tee:

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e

3
Остерігайтеся - це видаляє будь-які наявні записи.
starfry

5

Якщо припустити, що у вашому crontab вже є запис, наступна команда повинна працювати досить добре. Зауважте, що $CMDзмінна існує лише для читабельності. Сортування перед фільтруванням дублікатів є важливим, оскільки uniqпрацює лише на суміжних лініях.

CMD='wget -O - -q http://www.example.com/cron.php"'
(crontab -l ; echo "0 * * * * $CMD") | sort | uniq | crontab -

Якщо у вас зараз порожній crontab, ви отримаєте таку помилку в stderr:

no crontab for user

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

(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//"  | sort | uniq | crontab -

5

Більшість рішень тут - для додавання ліній до кронтабу. Якщо вам потрібен додатковий контроль, ви хочете мати можливість контролювати весь вміст кронтабу.

Ви можете використовувати трубопроводи, щоб зробити це досить елегантно.

Щоб повністю переписати crontab, зробіть

echo "2 2 2 2 2 /bin/echo foobar" |crontab -

Це слід легко поєднувати з іншими описаними тут відповідями

crontab -l | <something> | tee |crontab -

Або, якщо у вас є вміст у файлі, це ще простіше

cat <file> |crontab -

3

Ось ще один однолінійний спосіб, який дозволяє уникнути дублікатів

(crontab -l 2>/dev/null | fgrep -v "*/1 *  *  *  * your_command"; echo "*/1 *  *  *  * your_command") | crontab -

Ось спосіб зробити відповідь JohnZ і уникнути no crontab for userповідомлення, або якщо вам потрібно працювати в типовому set -euсередовищі і нічого не може повернути помилку (у такому випадку 2>/dev/nullдеталь не є обов'язковою):

( (crontab -l 2>/dev/null || echo "")  ; echo "0 * * * * your_command") | sort -u - | crontab -

Або якщо ви хочете розділити речі так, щоб вони були більш зрозумілими:

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
(echo "$preceding_cron_jobs" ; echo "$new_job") | sort - | uniq - | crontab -

Або необов'язково видаліть будь-які посилання на your_command (наприклад: якщо графік змінився, ви хочете, щоб він колись був закреслений один раз). У цьому випадку ми більше не потребуємо uniq(додається бонус, порядок вставки також зберігається):

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
preceding_cron_jobs=$(echo "$preceding_cron_jobs" | grep -v your_command )
(echo "$preceding_cron_jobs" ; echo "$new_job") | crontab -

2

man crontab також корисний:

CRONTAB (1)

ІМ’Я

   crontab - manipulate per-user crontabs (Dillon's Cron)

СИНОПИС

   crontab file [-u user] - replace crontab from file

   crontab - [-u user] - replace crontab from stdin

   crontab -l [user] - list crontab for user

3
Частина, яка говорить "замінити кронтаб на stdin", насправді є половиною відповіді :-)
Grodriguez

2

Додавши до відповіді JohnZ, ось синтаксис планувати як root, якщо ви судодер:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -

1
function cronjob_exists($command){

    $cronjob_exists=false;

    exec('crontab -l', $crontab);


    if(isset($crontab)&&is_array($crontab)){

        $crontab = array_flip($crontab);

        if(isset($crontab[$command])){

            $cronjob_exists=true;

        }

    }
    return $cronjob_exists;
}

function append_cronjob($command){

    if(is_string($command)&&!empty($command)&&cronjob_exists($command)===FALSE){

        //add job to crontab
        exec('echo -e "`crontab -l`\n'.$command.'" | crontab -', $output);


    }

    return $output;
}

    append_cronjob('* * * * * curl -s http://localhost/cron/test.php');

1

Це перевірить, щоб переконатися, що ваша команда не існує, перш ніж її додавати.

crontab -l 2>/dev/null | grep -q '/path/to/script' || echo "5 * * * * /path/to/script" | crontab -

Ура.


0

Piping stdout у crontabне встановив для мене нову crontab на macOS, тому я знайшов це рішення замість цього, використовуючи teeредактор у підкошті:

(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)

0

Якщо ви хочете, щоб завдання виконувались як користувач:

crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | crontab -

Якщо ви хочете, щоб завдання виконувались з привілеями:

sudo crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | sudo crontab -

і перевірте завдання (із «судо» або без нього):

crontab -l | sed '/^$/d; /#/d'


-2

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


1
Мені б хотілося це викликати занепокоєння щодо можливості одночасного редагування, що спричинить пошкодження файлів. Використання команди командного рядка crontab повинно уникати цієї проблеми.
Крейг S

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

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