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

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

24 ответа

Решение

Вы можете добавить в 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.

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

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

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

Этот более короткий не требует временного файла, он защищен от нескольких вставок и позволяет изменять расписание существующей записи.

Скажем, у вас есть эти:

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

Спасибо всем за вашу помощь. Собирая воедино то, что я нашел здесь и в другом месте, я придумал это:

Код

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 с новым, эффективно действуя как функция "добавить" или "обновить". Чтобы использовать это, все, что вам нужно сделать, это поменять значения для command а также job переменные.

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

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

Было много хороших ответов относительно использования 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

Такое управление кронами проще и более масштабируемо с точки зрения системы, но не всегда будет лучшим решением.

Итак, в 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/


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

Скорее всего, вы автоматизируете это, и вам не нужно добавлять ни одного задания дважды. В этом случае используйте:

__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

Нашел те в другом вопросе ТАК.

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

crontab <<EOF
00 09 * * 1-5 echo hello
EOF
echo "0 * * * * docker system prune --force >/dev/null 2>&1" | sudo tee /etc/cron.daily/dockerprune
(2>/dev/null crontab -l ; echo "0 3 * * * /usr/local/bin/certbot-auto renew") | crontab -
cat <(crontab -l 2>/dev/null) <(echo "0 3 * * * /usr/local/bin/certbot-auto renew") | crontab -

# записать текущий crontab

crontab -l > mycron 2>/dev/null

# вывод нового cron в файл cron

echo "0 3 * * * /usr/local/bin/certbot-auto renew" >> mycron

# установить новый файл cron

crontab mycron

rm mycron

Вариант, который редактирует crontab только в том случае, если нужная строка там не найдена:

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

Bash скрипт для добавления задания cron без интерактивного редактора. Ниже код помогает добавить cron job, используя файлы 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

Если вы используете Vixie Cron, например, в большинстве дистрибутивов Linux, вы можете просто поместить файл в /etc/cron.d с отдельным cronjob.

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

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

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

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

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

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

Вот функция 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"

Допустим, вы вошли в систему как пользователь «ubuntu», но хотите добавить задание в crontab другого пользователя, например, «john». Вы можете сделать следующее:

      (sudo crontab -l -u john; echo "* * * * * command") | awk '!x[$0]++' | sudo crontab -u john -

Источник большей части этого решения: https://www.baeldung.com/linux/create-crontab-script

У меня возникло множество проблем при попытке добавить задание в crontab другого пользователя . Он постоянно дублировал crontab или просто полностью их удалял. Однако после некоторого тестирования я уверен, что эта строка кода добавит новое задание в crontab указанного пользователя без разрушения, в том числе без создания уже существующего задания.

Довольно просто: добавьте свои сценарии в формате . Я хочу перезапустить какой-то конвейерdaily at 4 AM, Итак, я создал один bash-скриптdaily_restart.sh

      #daily_restart.sh

docker-compose -f /mnt/ssd/workspace/facesense_final_release_2023/client_release_edge/docker-compose-facesense-050523.yml down
docker-compose -f /mnt/ssd/workspace/facesense_final_release_2023/client_release_edge/docker-compose-facesense-050523.yml up -d

Я добавил этот скрипт в/etc/crontab

      # /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
* 4 * * * root /home/mic-710ail/restart.sh
#

мой cronjob это* 4 * * * root /home/mic-710ail/restart.shэто задание будет выполняться ежедневно в 4 утра

Дополнительные примеры cronjob можно найти у crontab Guru.

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

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

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

ТОО, Андреа

Я хотел найти такой пример, так что, возможно, это поможет:

      COMMAND="/var/lib/postgresql/backup.sh"
CRON="0 0 * * *"
USER="postgres"
CRON_FILE="postgres-backup"
# At CRON times, the USER will run the COMMAND
echo "$CRON $USER $COMMAND" | sudo tee /etc/cron.d/$CRON_FILE
echo "Cron job created. Remove /etc/cron.d/$CRON_FILE to stop it."

Функция скрипта для добавления 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

источник: мой мозг;)

Для тестирования, когда ваш cron будет запущен, рекомендую

https://crontab.guru/

Он показывает результат вашей настройки в удобочитаемом формате. Также вы можете нажать случайную кнопку, и вы получите примеры.

Вы можете изменить редактор по умолчанию на ed и использовать heredoc для редактирования.

EDITOR=ed
export EDITOR

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

Обратите внимание, что начальный > в этом коде означает, что клавиша возврата / ввода нажата для создания новой строки.

Средство APPEND означает, что оно ничего не будет перезаписывать.

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

W означает ЗАПИСАТЬ изменения.

Q означает выход или выход из ed.

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

crontab -l

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

EDITOR=ed
export EDITOR

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

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

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

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

crontab -l

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

Другие вопросы по тегам