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

395

Есть ли у crontab аргумент для создания заданий cron без использования редактора (crontab -e). Если так, какой код создаст cronjob из скрипта Bash?

Рауль Роа
источник
5
К сожалению, большинство лучших ответов здесь просто показывают, как модифицировать crontab - хотя и достаточно безопасными способами - но я думаю, что в целом это неправильный подход. Лучше, безопаснее и проще поместить файл в {{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

Объяснение линии Cron

* * * * * "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
Павел Полевич
166
(crontab -l; echo "00 09 * * 1-5 echo hello") | crontab -
Эдо
32
(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -- проще скопировать ответ Эдо
WBAR
8
Я хотел бы предложить , чтобы изменить это ;с &&как безопасным берегитесь случае , если crontab -lне удается. так, как:(crontab -l && echo "0 0 0 0 0 some entry") | crontab -
MacUsers
12
@MacUsers, происходит crontab -lсбой, если нет crontab, поэтому использование &&делает невозможным для сценария добавить первую запись в crontab.
JPhi1618
312

Вы можете сделать это на лету

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

crontab -lвыводит список текущих заданий crontab, catпечатает его, echoпечатает новую команду и crontab -добавляет все напечатанные материалы в файл crontab. Вы можете увидеть эффект, сделав новый crontab -l.

TheBonsai
источник
3
спасибо, не могли бы вы объяснить синтаксис или указать URL, который объясняет это?
сайты
9
crontab -lвыводит список текущих заданий crontab, catпечатает его, echoпечатает новую команду и crontab -добавляет все напечатанные материалы в файл crontab. Вы можете увидеть эффект, выполнив новыйcrontab -l
ня
3
Работает угощение для меня. Если у пользователя нет crontab, вы увидите no crontab for <username>, но он все равно работает.
Фази
21
не работает на моем экземпляре Amazon EC2. Вместо этого (crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -работает.
Стефан Брукерт
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
MoonCactus
источник
@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, я использую этот небольшой перенаправленный thingy ( <(*command*)), чтобы превратить вывод команды crontab -lв ввод для fgrepкоманды.
  2. fgrepзатем отфильтровывает любые совпадения $command( -vопция), без учета регистра ( -iопция).
  3. Опять же, маленькая функция перенаправления thingy ( <(*command*)) используется, чтобы превратить результат обратно в ввод для catкоманды.
  4. Команда catтакже получает echo "$job"(не требует пояснений), опять же, с помощью перенаправления thingy ( <(*command*)).
  5. Таким образом, отфильтрованные выходные данные crontab -lи простые echo "$job", объединенные, передаются по конвейеру ('|'), crontab -чтобы наконец быть записанными.
  6. И все они жили долго и счастливо!

В двух словах:

Эта строка кода отфильтровывает все задания cron, которые соответствуют команде, а затем записывает оставшиеся задания cron с новым, эффективно действуя как функция «добавить» или «обновить». Чтобы использовать это, все , что вам нужно сделать , это поменять значения для commandи jobпеременных.

Stoutie
источник
5
Для удобства читателей преимущество этого подхода состоит в том, что вы можете запускать его несколько раз, не беспокоясь о дублировании записей в crontab (в отличие от всех других решений). Это потому , что изfgrep -v
aleemb
5
Если вы предпочитаете традиционный способ обвязки слева направо, замените последнюю строку на: crontab -l | fgrep -i -v "$command" | { cat; echo "$job"; } | crontab -l
Antoine Lizée
1
@ AntoineLizée, ты отвечаешь, что в конце добавляется «l», которого там быть не должно.
Генри
26

РЕДАКТИРОВАТЬ (исправлена ​​перезапись):

cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -
duckyflip
источник
Это заменит любое содержимое crontab
TheBonsai
1
@TheBonsai О, я вижу, я исправил это сейчас, так что он должен добавить новую команду к существующему содержимому crontab
duckyflip
3
Имейте в виду, что подстановка процессов в Bash поглощает ошибки. Еслиcrontab -l не crontab -получится , но удастся, ваш crontab будет однострочным.
празднование
13

Было много хороших ответов относительно использования crontab, но нет упоминаний о более простом методе, таком как использование 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саму себя. Этот файл не должен быть исполняемым, а имя должно содержать только буквенно-цифровые и дефисы (более подробно ниже).

Чтобы дать тщательный ответ , хотя, посмотрим давайте на различия между crontabпротив 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 делают, как они запускаются частями выполнения (см. раздел run-parts (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 синтаксис ).

Обновление: это не работает, если у пользователя еще нет crontab. Более надежный способ будет:

(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 21.10.15
1
fwiw, я получаю эту ошибку, используя bash, если между и <и есть пробел (. Это означает, что < (не <(работает, но работает, если в вашем расписании нет звездочек ...
doublesharp
Я считаю, что это правильный путь:cat <(crontab -l |grep -v "${CRON}") <(echo "${CRON}") | crontab -
Станислав
5

Для быстрого и удобного создания / замены crontab с помощью скрипта BASH я использовал эту запись:

crontab <<EOF
00 09 * * 1-5 echo hello
EOF
Gibbsoft
источник
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.

Это работает только для root, конечно. Если ваша система поддерживает это, вы должны увидеть там несколько примеров. (Обратите внимание на имя пользователя, включенное в строку, в том же синтаксисе, что и старый / etc / crontab)

Это печальная ошибка в cron, что нет способа справиться с этим как обычного пользователя, и что так много реализаций cron вообще не имеют возможности справиться с этим.

зажимной патрон
источник
2

Итак, в Debian, Ubuntu и многих подобных дистрибутивах на основе Debian ...

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

Вы можете поместить файл в /etc/cron.d/somefilename, где somefilename - это то, что вы хотите.

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

Давайте разберем это:

sudo - потому что вам нужны повышенные привилегии для изменения конфигураций cron в каталоге / etc

echo - средство для создания вывода на стандартный вывод. printf, кот ... будет работать так же

"- используйте двойную кавычку в начале строки, вы профессионал

0,15,30,45 * * * * - стандартное расписание запуска cron, оно запускается каждые 15 минут

ntpdate -u time.nist.gov - фактическая команда, которую я хочу запустить

"- потому что мои первые двойные кавычки нуждаются в приятеле, чтобы закрыть выводимую строку

>> - двойное перенаправление добавляется вместо перезаписи *

/etc/cron.d/vmclocksync - vmclocksync - это выбранное мной имя файла, оно находится в /etc/cron.d/


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

BradChesney79
источник
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, чтобы установить новую запись.
Apoorv Parijat
2
echo "0 * * * * docker system prune --force >/dev/null 2>&1" | sudo tee /etc/cron.daily/dockerprune
user11547308
источник
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}")

добавить параметр -w в точную команду grep, без параметра -w добавление cronjob «testing» вызывает удаление задания cron «testing123»

функция скрипта для добавления / удаления cronjobs. нет записей дублирования:

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
speefak
источник
Если в crontab одна и та же команда дважды (выполняется в разное время), команда delete удалит обе строки.
Michaelkay
1

Мое предпочтительное решение этого было бы это:

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

Это обеспечит правильную обработку новой пустой строки внизу. Чтобы избежать проблем с crontab, вы обычно должны заканчивать файл crontab пустой новой строкой. И скрипт выше гарантирует, что сначала он удаляет все пустые строки с помощью «grep». части, а затем добавьте новую пустую строку в конце с "\ n" в конце скрипта. Это также предотвратит появление пустой строки над новой командой, если существующий файл crontab заканчивается пустой строкой.

Gsus
источник
0

Нет, в crontab нет опции для изменения файлов cron.

Вы должны: взять текущий файл cron (crontab -l> newfile), изменить его и поместить новый файл на место (crontab newfile).

Если вы знакомы с Perl, вы можете использовать этот модуль Config :: Crontab .

ТОО, Андреа

andcoz
источник
0

функция скрипта для добавления cronjobs. проверять дубликаты записей, используемые выражения *> "

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 , поэтому он не будет переписывать что - нибудь.

.означает, что вы закончили редактирование.

ж средство записи изменений.

д означает QUIT или выход ред.

Вы можете проверить это

crontab -l

Вы также можете удалить запись.

EDITOR=ed
export EDITOR

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

Это удалит запись crontab с Myscript.

Символ d означает удаление шаблона внутри / / .

Не проверять это снова

crontab -l

Это решение работает внутри скрипта слишком меньше > конечно :-)

Jetchisel
источник