Як створити роботу cron за допомогою Bash автоматично без інтерактивного редактора?


395

Чи має crontab аргумент для створення завдань cron без використання редактора (crontab -e). Якщо так, то який би код створив cronjob із сценарію Bash?



5
На жаль, більшість найкращих відповідей тут лише показують, як змінити кронтаб - хоч і досить безпечними способами - але я думаю, що це взагалі неправильний підхід. Краще, безпечніше і простіше - ввести файл у {{cron.d}}, і є (на даний момент) відповіді з низьким голосом, що пояснюють, як це зробити, якщо подивитися далі.
gregmac

Відповіді:


539

Ви можете додати до crontab наступним чином:

#write out current crontab
crontab -l > mycron
#echo new cron into cron file
echo "00 09 * * 1-5 echo hello" >> mycron
#install new cron file
crontab mycron
rm mycron

Пояснення лінії Крона

* * * * * "command to be executed"
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

Джерело nixCraft .


14
Ви повинні використовувати tempfile або mktemp
Paweł Polewicz

166
(crontab -l; відлуння "00 09 * * 1-5 ехо привіт") | crontab -
Edo

32
(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -- простіше скопіювати
одяг

8
Я хотів би запропонувати , щоб змінити це ;з &&як безпечним стережіться випадку , якщо crontab -lне вдається. так, як:(crontab -l && echo "0 0 0 0 0 some entry") | crontab -
MacUsers

12
@MacUsers crontab -lвиходить з ладу, якщо немає кронтабуляції, тому використання &&сценарію неможливо додати перший запис до crontab.
JPhi1618

312

Ви можете зробити це на ходу

crontab -l | { cat; echo "0 0 0 0 0 some entry"; } | crontab -

crontab -lперелічує поточні завдання crontab, catдрукує його, echoдрукує нову команду та crontab -додає всі надруковані речі у файл crontab. Ви можете побачити ефект, зробивши новий crontab -l.


3
дякую, ви могли б пояснити синтаксис або вказати на URL, який пояснює це?
сайти

9
crontab -lперелічує поточні завдання crontab, catдрукує його, echoдрукує нову команду та crontab -додає всі надруковані речі у файл crontab. Ви можете побачити ефект, роблячи новийcrontab -l
НСЗ

3
Працює для мене частування. Якщо у користувача немає жодного повідомлення, ви працюєте no crontab for <username>, але він все одно працює.
fazy

21
не працює на моєму екземплярі Amazon EC2. Натомість (crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -працює.
Stéphane Bruckert

11
Це виглядає як кандидат в UUcatA .
припинення

86

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

Скажіть, у вас це:

croncmd="/home/me/myfunction myargs > /home/me/myfunction.log 2>&1"
cronjob="0 */15 * * * $croncmd"

Щоб додати його до crontab, без дублювання:

( crontab -l | grep -v -F "$croncmd" ; echo "$cronjob" ) | crontab -

Щоб видалити його з crontab незалежно від поточного розкладу:

( crontab -l | grep -v -F "$croncmd" ) | crontab -

Примітки:

  • grep -F відповідає рядку буквально, оскільки ми не хочемо інтерпретувати його як регулярний вираз
  • Ми також ігноруємо планування часу і лише шукаємо команду. Сюди; графік можна змінити, не ризикуючи додати новий рядок до crontab

@moeseth: ти можеш детальніше розібратися?
MoonCactus

ви повинні спробувати його на своєму комп’ютері
moeseth

2
@moeseth: Я, очевидно, спробував це на своєму комп’ютері (Linux). Я б не радив випадкових неробочих матеріалів: /
MoonCactus

2
До речі, 27 людей не можуть помилитися (станом на сьогодні). Опишіть, будь ласка, чому це не працює для вашого налаштування, щоб ми могли допомогти.
MoonCactus

2
Це може бути проблема з OSX.
moeseth

40

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

Код

command="php $INSTALL/indefero/scripts/gitcron.php"
job="0 0 * * 0 $command"
cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -

Я не міг зрозуміти, як усунути потребу в двох змінних, не повторюючись.

commandце, очевидно, команда, яку я хочу запланувати. jobприймає $commandта додає дані планування. Мені були потрібні обидві змінні окремо в рядку коду, який робить роботу.

Деталі

  1. Я маю на увазі duckyflip, я використовую цю маленьку штучку перенаправлення ( <(*command*)), щоб перетворити висновок crontab -lвхід для fgrepкоманди.
  2. fgrepпотім фільтрує будь-які збіги $command( -vопція), нечутливі до регістру ( -iопція).
  3. Знову ж таки, маленька штучка перенаправлення ( <(*command*)) використовується для повернення результату назад у вхід для catкоманди.
  4. catКоманда також отримує echo "$job"(Пояснень), знову - таки, за рахунок використання редиректу штуковина ( <(*command*)).
  5. Тож відфільтрований вихід із crontab -lта простий echo "$job", комбінований, переносяться ('|'), crontab -щоб остаточно записати.
  6. І всі вони жили щасливо досі!

Коротко:

Цей рядок коду фільтрує будь-які завдання cron, які відповідають команді, а потім виписує залишки cron з новим, ефективно діючи як функція "add" або "update". Щоб використати це, все, що вам потрібно зробити, це поміняти місцями значення змінних commandта jobзмінних.


5
На користь інших, хто читає, перевага такого підходу полягає в тому, що ви можете запустити його кілька разів, не турбуючись про дублюючі записи в crontab (на відміну від усіх інших рішень). Це черезfgrep -v
aleemb

5
Якщо ви віддаєте перевагу традиційному способу трубопроводів, замініть останній рядок таким чином: crontab -l | fgrep -i -v "$command" | { cat; echo "$job"; } | crontab -l
Антуан Лізе

1
@ AntoineLizée, у відповідь ви маєте додаткові "l" зрештою, чого там не повинно бути.
Генрі

26

EDIT (фіксований перезапис):

cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -

Це замінить будь-який вміст
кронатобу

1
@TheBonsai о, я бачу, я виправив це зараз, тому він повинен ДОПУСКАТИ нову команду до наявного вмісту crontab
duckyflip

3
Майте на увазі, що заміна процесу Баша поглинає помилки. Якщо crontab -lне вдасться, але crontab -вдасться, ваш кронтаб буде однолінійним.
припинення

13

Навколо використання кронтабу було багато хороших відповідей, однак про більш простий метод, наприклад використання cron.

Використання cronскористається системними файлами та каталогами, розташованими в /etc/crontab, /etc/cron.daily,weekly,hourlyабо /etc/cron.d/:

cat > /etc/cron.d/<job> << EOF
SHELL=/bin/bash 
PATH=/sbin:/bin:/usr/sbin:/usr/bin 
MAILTO=root HOME=/  
01 * * * * <user> <command>
EOF

У цьому вище прикладі ми створили файл у /etc/cron.d/, надали змінні середовища для успішного виконання команди та надали userкоманду і commandсаму. Цей файл не повинен бути виконаним, а ім'я має містити лише буквено-цифрові знаки та дефіси (детальніше нижче).

Щоб дати ґрунтовну відповідь, давайте розглянемо відмінності між crontabvs cron/crond:

crontab -- maintain tables for driving cron for individual users

Для тих, хто хоче виконати завдання в контексті свого користувача в системі, використання crontabможе мати ідеальний сенс.

cron -- daemon to execute scheduled commands

Для тих, хто використовує управління конфігурацією або хоче керувати роботами для інших користувачів, і в такому випадку ми повинні їх використовувати cron.

Швидкий уривок із рукописів дає кілька прикладів того, що робити, а що не робити:

/ etc / crontab та файли в /etc/cron.d повинні належати root, і не повинні бути груповими чи іншими, що можна записати. На відміну від області котушки, файли під /etc/cron.d або файли під /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly та /etc/cron.monthly також можуть бути символьні посилання за умови, що як посилання, так і файл, на який він вказує, належать root. Файли під /etc/cron.d не потрібно виконувати, тоді як файли під /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly та /etc/cron.monthly роблять, як вони виконуються запускними частинами (для отримання додаткової інформації див. пробіг (8)).

Джерело: http://manpages.ubuntu.com/manpages/trusty/man8/cron.8.html

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


1
Можливо, варто згадати, що <job>не повинно містити розширення файлу.
jww

7

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

__cron="1 2 3 4 5 /root/bin/backup.sh"
cat <(crontab -l) |grep -v "${__cron}" <(echo "${__cron}")

Це працює лише якщо ви використовуєте BASH. Мені невідомий правильний shсинтаксис DASH ( ).

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

(crontab -l ; echo "1 2 3 4 5 /root/bin/backup.sh") | sort - | uniq - | crontab - 

Якщо ваш дистрибутив підтримує його, ви також можете використовувати окремий файл:

echo "1 2 3 4 5 /root/bin/backup.sh" |sudo tee /etc/crond.d/backup

Знайшли їх в іншому питанні .


Можливо, використовуючи sh замість bash?
kvz

Ще sh: 1: Syntax error: "(" unexpectedвикористовую ш .
Батандва

Це працює лише якщо ви використовуєте BASH. Я не знаю правильного синтаксису DASH (sh). Оновлено відповідь також
kvz

1
fwiw, я отримую цю помилку за допомогою bash, якщо між <і (. Це означає, що < (не вдається, але <(працює, якщо у вашому графіку немає зірочок ...
подвоєння Шар

Я вважаю, що це правильний шлях:cat <(crontab -l |grep -v "${CRON}") <(echo "${CRON}") | crontab -
Станіслав

5

Для приємного швидкого та брудного створення / заміни літопису на сценарій BASH, я використав це позначення:

crontab <<EOF
00 09 * * 1-5 echo hello
EOF

5

Варіант, який редагує crontab лише у тому випадку, якщо потрібна рядок там не знайдена:

CMD="/sbin/modprobe fcpci"
JOB="@reboot $CMD"
TMPC="mycron"
grep "$CMD" -q <(crontab -l) || (crontab -l>"$TMPC"; echo "$JOB">>"$TMPC"; crontab "$TMPC")

3

Якщо ви використовуєте Vixie Cron, наприклад, для більшості дистрибутивів Linux, ви можете просто помістити файл у /etc/cron.d з окремою cronjob.

Це працює тільки для кореня. Якщо ваша система підтримує це, ви повинні побачити кілька прикладів там. (Зверніть увагу на ім’я користувача, що входить у рядок, у тому ж синтаксисі, що і старий / etc / crontab)

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


2

Так, у Debian, Ubuntu та багатьох подібних дистрибутивах на основі Debian ...

Існує механізм з’єднання завдань cron, який бере конфігураційний файл, зв'язує їх і додає їх до вашої служби cron, що працює.

Ви можете помістити файл під /etc/cron.d/somefilename, де ім'я певного файлу - все, що вам потрібно.

sudo echo "0,15,30,45 * * * * ntpdate -u time.nist.gov" >> /etc/cron.d/vmclocksync

Розберемо це:

sudo - тому що вам потрібні підвищені привілеї, щоб змінити конфігурації cron в каталозі / etc

echo - транспортний засіб для створення виводу на std out. printf, cat ... також працювали б

"- використовуйте подвійну цитату на початку рядка, ви професіонал

0,15,30,45 * * * * - стандартний графік запуску кронів, цей працює кожні 15 хвилин

ntpdate -u time.nist.gov - фактична команда, яку я хочу виконати

"- тому що мої перші подвійні цитати потребують приятеля, щоб закрити вихідний рядок

>> - подвійне переадресація додається замість перезаписів *

/etc/cron.d/vmclocksync - vmclocksync - це вибране ім'я файлу, воно входить у /etc/cron.d/


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


2

Сценарій Bash для додавання завдання cron без інтерактивного редактора. Нижче код допомагає додати cronjob за допомогою файлів Linux.

#!/bin/bash

cron_path=/var/spool/cron/crontabs/root

#cron job to run every 10 min.
echo "*/10 * * * * command to be executed" >> $cron_path

#cron job to run every 1 hour.
echo "0 */1 * * * command to be executed" >> $cron_path

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

1
Цей не встановлює cron. Він просто додає його до файлу. Вам доведеться якось сповістити процес cron, щоб встановити новий запис.
Апоорв Паріят

1

Ось функція bash для додавання команди crontabбез дублювання

function addtocrontab () {
  local frequency=$1
  local command=$2
  local job="$frequency $command"
  cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -
}
addtocrontab "0 0 1 * *" "echo hello"

1
CRON="1 2 3 4 5 /root/bin/backup.sh" 
cat < (crontab -l) |grep -v "${CRON}" < (echo "${CRON}")

параметр add -w в точну команду grep, без параметра -w додавання cronjob "testing" викликає видалення завдання cron "testing123"

функція сценарію для додавання / видалення кроні. жодних записів дублювання:

cronjob_editor () {         
# usage: cronjob_editor '<interval>' '<command>' <add|remove>

if [[ -z "$1" ]] ;then printf " no interval specified\n" ;fi
if [[ -z "$2" ]] ;then printf " no command specified\n" ;fi
if [[ -z "$3" ]] ;then printf " no action specified\n" ;fi

if [[ "$3" == add ]] ;then
    # add cronjob, no duplication:
    ( crontab -l | grep -v -F -w "$2" ; echo "$1 $2" ) | crontab -
elif [[ "$3" == remove ]] ;then
    # remove cronjob:
    ( crontab -l | grep -v -F -w "$2" ) | crontab -
fi 
} 
cronjob_editor "$1" "$2" "$3"

перевірено:

$ ./cronjob_editor.sh '*/10 * * * *' 'echo "this is a test" > export_file' add
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file

Якщо у вас є одна і та ж команда в crontab двічі (працює в різний час), видалення видалить обидва рядки.
Michaelkay

1

Моїм кращим рішенням було б таке:

(crontab -l | grep . ; echo -e "0 4 * * * myscript\n") | crontab -

Це переконається, що ви правильно обробляєте порожній новий рядок внизу. Щоб уникнути проблем із crontab, зазвичай слід закінчувати файл crontab порожнім новим рядком. А вищезазначений сценарій гарантує, що він спочатку видаляє будь-які порожні рядки з "grep". частину, а потім додайте новий пустий рядок в кінці з "\ n" в кінці сценарію. Це також запобіжить отримання порожнього рядка над вашою новою командою, якщо ваш існуючий файл crontab закінчується порожнім рядком.



0

Ні, в crontab немає можливості змінювати файли cron.

Вам потрібно: взяти поточний файл cron (crontab -l> newfile), змінити його і поставити новий файл на місце (crontab newfile).

Якщо ви знайомі з perl, ви можете використовувати цей модуль Config :: Crontab .

ТОО, Андреа


0

функція сценарію для додавання кроні. перевірити дублікати записів, корисні вирази *> "

cronjob_creator () {         
# usage: cronjob_creator '<interval>' '<command>'

  if [[ -z $1 ]] ;then
    printf " no interval specified\n"
elif [[ -z $2 ]] ;then
    printf " no command specified\n"
else
    CRONIN="/tmp/cti_tmp"
    crontab -l | grep -vw "$1 $2" > "$CRONIN"
    echo "$1 $2" >> $CRONIN
    crontab "$CRONIN"
    rm $CRONIN
fi
}

перевірено:

$ ./cronjob_creator.sh '*/10 * * * *' 'echo "this is a test" > export_file'
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file

джерело: мій мозок;)


-5

Ви можете, можливо, змінити редактор за замовчуванням на ed та використовувати heredoc для редагування.

EDITOR=ed
export EDITOR

crontab -e << EOF
> a
> * * * * * Myscript
> * * * * * AnotherScript
> * * * * * MoreScript
> .
> w
> q
> EOF

Зверніть увагу на головний > у цьому коді означає, що для створення нового рядка натискається клавіша повернення / введення.

У а засіб APPEND , тому він не буде переписувати що - небудь.

The .означає, що ви закінчили редагування.

The w засіб запису змін.

В Q означає QUIT або вихід ред.

ви можете це перевірити

crontab -l

Ви також можете видалити запис.

EDITOR=ed
export EDITOR

crontab -e << EOF
> /Myscript/
> d
> .
> w
> q
> EOF

Це видалить запис crontab з Myscript у ньому.

В д засіб видалення малюнка всередині / / .

Не перевіряйте це ще раз

crontab -l

Це рішення працює всередині сценарію занадто менше > звичайно :-)

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