Как автоматически создать cron-задачу с помощью Bash без интерактивного редактора?
Существует ли возможность в crontab
создать задания Cron без использования редактора (crontab -e
)? Если да, то каков будет код для создания задания Cron из Bash-скрипта?
5 ответ(ов)
Вы можете сделать это на лету:
crontab -l | { cat; echo "0 0 0 0 0 some entry"; } | crontab -
Этот подход работает, поскольку команда crontab -l
выводит текущие задания crontab, cat
выводит их (из стандартного ввода), echo
добавляет новую команду, а crontab -
записывает все напечатанное в файл crontab. Чтобы увидеть изменения, просто выполните команду crontab -l
снова.
Обратите внимание: если у пользователя нет существующего crontab, вы можете увидеть следующее сообщение:
no crontab for <username>
Тем не менее, это по-прежнему работает, даже если вы видите это сообщение.
Этот более короткий способ не требует временного файла, не подвержен множественным вставкам и позволяет менять расписание уже существующей записи.
Допустим, у вас есть следующие команды:
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
и добавляет к нему данные о расписании. Мне нужны обе переменные отдельно в строке кода, выполняющей работу.
Подробности
- Благодарность duckyflip — я использую этот маленький редирект (
<(*command*)
), чтобы превратить выводcrontab -l
в ввод для командыfgrep
. - Затем
fgrep
фильтрует все совпадения с$command
(опция-v
), игнорируя регистр (опция-i
). - Снова используется маленький редирект (
<(*command*)
), чтобы вернуть результат в ввод для командыcat
. - Команда
cat
также получаетecho "$job"
(это и так понятно), вновь через использование редиректа (<(*command*)
). - Таким образом, отфильтрованный вывод из
crontab -l
и простоеecho "$job"
, в совокупности, передаются ('|') вcrontab -
, чтобы в итоге записаться. - И они все жили долго и счастливо!
В двух словах:
Эта строка кода фильтрует любые задания cron, которые совпадают с командой, затем записывает оставшиеся задания cron с новым, что фактически действует как функция "добавить" или "обновить".
Чтобы воспользоваться этим, вам достаточно заменить значения переменных command
и job
.
Используя команду cat
с подстановочными файлами, вы можете добавить новую задачу в crontab, не перезаписывая существующие задачи. Вот исправленный вариант, который решает проблему с перезаписью:
cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -
В этом примере crontab -l
выводит существующие задачи расписания, а echo
добавляет новую задачу scripty.sh
, которая будет выполняться в указанные время. Затем объединенные результаты передаются в crontab -
, чтобы обновить расписание. Обратите внимание, что этот метод работает, если вы хотите добавить только одну задачу, не удаляя текущие.
На StackOverflow было много хороших ответов по использованию crontab, но не упомянута более простая методика с использованием cron
.
Использование cron
позволяет воспользоваться системными файлами и директориями, расположенными по путям /etc/crontab
, /etc/cron.daily
, /etc/cron.weekly
, /etc/cron.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/
, указываем переменные среды для успешного выполнения команды, а также пользователя и саму команду. Этот файл не должен быть исполняемым, и его имя должно содержать только буквы, цифры и дефисы (подробности ниже).
Чтобы ответ был более полным, давайте рассмотрим различия между crontab
и cron/crond
:
crontab -- поддержка таблиц для запуска cron для отдельных пользователей
Для тех, кто хочет запускать задания от имени своего пользователя в системе, использование crontab
может быть разумным выбором.
cron -- демон для выполнения запланированных команд
Для тех, кто использует управление конфигурацией или хочет управлять заданиями для других пользователей, в этом случае стоит использовать cron
.
Небольшой отрывок из man-страниц дает несколько примеров того, что можно и чего нельзя делать:
/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 (см. run-parts(8) для получения дополнительной информации).
Источник: http://manpages.ubuntu.com/manpages/trusty/man8/cron.8.html
Управление cron таким образом проще и более масштабируемо с точки зрения системы, однако это не всегда будет лучшим решением.
Как выводить команды оболочки по мере их выполнения
Назначение значений по умолчанию для переменных оболочки одной командой в bash
Как указать приватный SSH-ключ для выполнения команды shell в Git?
Как узнать, в какой интерактивной оболочке я нахожусь (командная строка)
Расширение переменных внутри одинарных кавычек в команде Bash