Как мне создать crontab через скрипт

153

Мне нужно добавить задание cron через скрипт, который я запускаю для настройки сервера. Я в настоящее время использую Ubuntu. Я могу использовать, crontab -eно это откроет редактор для редактирования текущего crontab. Я хочу сделать это программно.

Возможно ли это сделать?

Gaurav
источник
Если вы хотите изменить или удалить запись в crontab, см. Мое решение ниже.
Брайан Смит

Ответы:

11

Задания Cron обычно хранятся в пользовательском файле в /var/spool/cron

Самое простое, что вы можете сделать, это, вероятно, просто создать текстовый файл с настроенным заданием, затем скопировать его в папку спулинга cron и убедиться, что у него есть необходимые разрешения (600).

Джейсон Стелцер
источник
20
Изменение файлов непосредственно в / var / spool / cron не одобряется. Фактически, если вы посмотрите на файлы там, они обычно содержат предупреждения, такие как «НЕ РЕДАКТИРОВАТЬ ЭТОТ ФАЙЛ» в качестве первой строки.
Джаред
12
@ Джаред Хотя я вполне согласен с этой идеей, сказать, что она "осуждается", не очень помогает. Скорее сообщите, какой другой файл следует редактировать, если таковой имеется, или объясните риски редактирования файлов вручную. Я планирую создавать некоторые задания cron с помощью автоматизированной командной строки, и если редактирование этого файла является единственной возможностью и без значительных побочных эффектов, я не понимаю, почему мне не следует его использовать.
Balmipour
47
Прокрутите вниз для реального ответа.
Джон Ред
1
На мой взгляд, этот ответ гораздо лучше: stackoverflow.com/a/610860/2681752
galaux
2
Я принял этот подход и пожалел об этом. В RHEL каталог / var / spool / cron не является исполняемым в мире, поэтому пользователи не могут просматривать каталог и редактировать свои файлы вручную. Если вы сделаете / var / spool / cron world исполняемым, ваш дружественный локальный системный администратор будет зол на вас, плюс изменение разрешения может быть перезаписано, если пакет cronie когда-либо переустанавливается или обновляется.
functionvoid
384

Вот одна строка, которая не использует / не требует, чтобы новая работа была в файле:

(crontab -l 2>/dev/null; echo "*/5 * * * * /path/to/job -with args") | crontab -

Это 2>/dev/nullважно для того, чтобы вы не получили no crontab for usernameсообщение, которое выдают некоторые * nixes, если в настоящее время нет записей crontab.

Джо Касадонте
источник
14
Это должен быть принятый ответ. Просто нужен способ, чтобы проверить, есть ли там
строка, которую
7
... о, подождите, вот как проверить, есть ли что-то в crontab моего пользователя, прежде чем я добавлю его с помощью скрипта: stackoverflow.com/a/14451184/3686125
ChrisPrime
1
если этот скрипт предназначен для повторения и изменения существующей задачи cron, было бы неплохо заменить существующую строку в crontab. несколько маркеров могут использоваться для управления различными задачами cron (control-marker-1, control-marker-2 и т. д.): (crontab -l 2> / dev / null | grep -v control-marker-1; echo '* / 5 * * * * / path / to / job -with args # control-marker-1') | crontab -
шеф-повар
7
Я обнаружил, что это удаляло существующие записи в crontab, а также мне нужно было использовать другого пользователя (root), поэтому я использовал следующее для поддержки существующих записей: echo -e "$(sudo crontab -u root -l)\n* * * * * echo hello > /home/danny/temp.log 2>&1" | sudo crontab -u root -Надеюсь, это кому-нибудь поможет
Дэнни
60

Для пользовательских crontabs (включая root) вы можете сделать что-то вроде:

crontab -l -u user | cat - filename | crontab -u user -

где файл с именем «filename» содержит элементы для добавления. Вы также можете сделать манипуляцию с текстом sedили другой инструмент вместо cat. Вы должны использовать crontabкоманду вместо прямого изменения файла.

Аналогичная операция будет:

{ crontab -l -u user; echo 'crontab spec'; } | crontab -u user -

Если вы модифицируете или создаете системные crontabs, ими можно манипулировать, как обычными текстовыми файлами. Они хранятся в /etc/cron.d, /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthlyкаталогов и файлов /etc/crontabи /etc/anacrontab.

Приостановлено до дальнейшего уведомления.
источник
Выглядело многообещающе, но попробовав второй подход (с echo), я получил «crontab: ошибка использования: имя файла должно быть указано для замены». Страница руководства Cron показывает синтаксис как crontab [ -u user ] file, то есть с обязательным именем файла. Есть ли какой-то трюк, чтобы заставить его принимать данные по каналу?
Марк Берри
1
@MarkBerry: К сожалению об этом. В трубе, дефис должен использоваться, чтобы указать, что ввод от stdin. Я исправлю свой ответ.
Приостановлено до дальнейшего уведомления.
29

В Ubuntu и многих других дистрибутивах вы можете просто поместить файл в /etc/cron.dкаталог, содержащий одну строку с допустимым crontab записью . Нет необходимости добавлять строку в существующий файл.

Если вам нужно что-то запускать ежедневно, просто поместите файл в /etc/cron.daily. Кроме того, вы можете также перетаскивать файлы Into /etc/cron.hourly, /etc/cron.monthlyи /etc/cron.weekly.

IvanGoneKrazy
источник
5
Но вы должны быть root, чтобы сделать это.
Кит
17

Еще более простым ответом на ваш вопрос будет:

echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/root

Вы можете настроить cronjobs на удаленных серверах, как показано ниже:

#!/bin/bash
servers="srv1 srv2 srv3 srv4 srv5"
for i in $servers
  do
  echo "0 1 * * * /root/test.sh" | ssh $i " tee -a /var/spool/cron/root"
done

В Linux, местоположение по умолчанию crontabфайла /var/spool/cron/. Здесь вы можете найти crontabфайлы всех пользователей. Вам просто нужно добавить свою запись cronjob в файл соответствующего пользователя. В приведенном выше примере к файлу crontab пользователя root добавляется cronjob, который запускается /root/test.shкаждый день в 1:00.

Ганеш Патхак
источник
Это было бы /var/spool/cron/crontabs/rootна Ubuntu.
Хор Ме
17

Файлы Crontab - это просто текстовые файлы, и поэтому они могут рассматриваться как любой другой текстовый файл. Цель crontabкоманды - сделать редактирование файлов crontab более безопасным. При редактировании с помощью этой команды файл проверяется на наличие ошибок и сохраняется только при его отсутствии.

crontab [path to file]может использоваться для указания crontab, хранящегося в файле. Мол crontab -e, это будет установить файл, только если он без ошибок.

Поэтому скрипт может либо напрямую записывать файлы вкладок cron, либо записывать их во временный файл и загружать их с помощью crontab [path to temp file]команды. Запись напрямую избавляет от необходимости записи временного файла, но также избегает проверки безопасности.

cledoux
источник
2
Для новичков, таких как я, обратите внимание, что это crontab [path to file]... Это определенно был лучший вариант для меня, так как он позволяет более разборчивый код. Я использую crontab для отслеживания посылок и смены обоев рабочего стола на статус. Когда я не ожидаю посылки, это не нужно проверять каждый час. Вот почему я хотел, чтобы скрипт автоматически редактировал частоту cron.
Расм
1
@Rasmus Это звучит как потрясающий сценарий, который я бы хотел украсть. Есть ли шанс поделиться через гист или подобное?
Cledoux
8

(У меня недостаточно репутации, чтобы комментировать, поэтому я добавляю в качестве ответа: не стесняйтесь добавлять его в качестве комментария рядом с его ответом)

Однострочник Джо Касадонте идеален, за исключением случаев, когда вы бежите сset -e , т. Если ваш скрипт настроен на ошибку при ошибке и если cronjobs еще нет. В этом случае однострочник НЕ будет создавать cronjob, но НЕ будет останавливать сценарий. Тихая ошибка может быть очень обманчивой.

Причина в том, что crontab -lвозвращается с 1кодом возврата, вызывая последующую команду (echo ) не выполняется ... таким образом, cronjob не создается. Но так как они выполняются как подпроцесс (из-за скобок), они не останавливают сценарий.

(Интересно, что если вы снова запустите эту команду, он будет работать: как только вы не выполнили crontab -один раз, crontab -lеще выводит ничего, но он не возвращает ошибку больше (вы не получите no crontab for <user>сообщение больше) Так что последующее. echoВыполняется и crontab создан)

В любом случае, если вы работаете с set -e, строка должна быть:

(crontab -l 2>/dev/null || true; echo "*/5 * * * * /path/to/job -with args") | crontab -
Фариа
источник
Да, этот еще более совершенен.
Ингве Снин Линдал
7

Как исправление для тех, кто предлагает crontab -l | crontab -: это работает не на каждой системе. Например, мне пришлось добавить задание в корневой crontab на десятках серверов со старой версией SUSE (не спрашивайте почему). Старые SUSE добавляют строки комментариев к выводу crontab -l, делая их crontab -l | crontab -неидемпотентными (Debian распознает эту проблему в справочной странице crontab и исправил свою версию Vixie Cron, чтобы изменить поведение по умолчанию crontab -l).

Чтобы редактировать crontabs программно в системах, где crontab -lдобавляются комментарии, вы можете попробовать следующее:

EDITOR=cat crontab -e > old_crontab; cat old_crontab new_job | crontab -

EDITOR=catговорит crontab использовать catв качестве редактора (не обычного по умолчанию vi), который не изменяет файл, а вместо этого копирует его в стандартный вывод. Это может все еще потерпеть неудачу, если crontab -ожидается ввод в формате, отличном от того, который crontab -eвыводит. Не пытайтесь заменить финал crontab -на crontab -e- он не будет работать.

user2845840
источник
4

Ну, /etc/crontabпросто файл ASCII, так что самое простое, чтобы просто

 echo "*/15 * * * *   root     date" >> /etc/crontab

который добавит работу, которая будет отправлять вам каждые 15 минут. Настройте по вкусу и проверьте с помощью grepили другими способами, была ли добавлена ​​строка, чтобы сделать ваш скрипт идемпотентным.

В Ubuntu и др. Вы также можете удалить файлы, в /etc/cron.*которых проще сделать тестирование, и, кроме того, вы не будете связываться с (системными) конфигурационными файлами, такими как /etc/crontab.

Дирк Эддельбюттель
источник
1
Я думаю, что технически crond не требуется для отслеживания изменений в crontab, даже если в действительности большинство реализаций делают это, поэтому я рекомендовал бы вызов crontab -e впоследствии, чтобы подтолкнуть его. crontab -e учитывает переменную EDITOR, если память не изменяет, поэтому на момент ее установки / bin / true следует просто перечитать crontab.
Ульрих Шварц
1
Правда, в любой недавней системе Linux crond есть монитор, и он, безусловно, работает на заявленной платформе OP.
Дирк Эддельбюттель
Только если вы root и хотите, чтобы скрипт запускался от имени root. Это может быть нежелательно в случае ОП.
Кит
Не так, у меня есть много некорневых записей в / etc / crontab. Вам просто нужно sudo, чтобы добавить в файл. В любом случае, как я уже говорил, есть также /etc/cron.*/, но вам также нужно иметь права root, чтобы писать туда.
Дирк Эддельбюттель
2

Вот как можно изменить запись cron без непосредственного редактирования файла cron (который осуждается).

crontab -l -u <user> | sed 's/find/replace/g' | crontab -u <user> -

Если вы хотите удалить запись cron, используйте это:

crontab -l -u <user> | sed '/find/d' | crontab -u <user> -

Я понимаю, что это не то, о чем просил Гаурав, но почему бы не иметь все решения в одном месте?

Брайан Смит
источник
1

Я написал инструмент развертывания crontab на python: https://github.com/monklof/deploycron

pip install deploycron

Установить ваш crontab очень просто, это объединит crontab в существующий crontab системы.

from deploycron import deploycron
deploycron(content="* * * * * echo hello > /tmp/hello")
monklof
источник
1

Это подход для постепенного добавления задания cron:

  ssh USER_NAME@$PRODUCT_IP nohup "echo '*/2 * * * * ping -c2 PRODUCT_NAME.com >> /var/www/html/test.html' | crontab -u USER_NAME -"
Алексей Кислицын
источник