Как я могу программно создать новую работу cron?
Я хочу иметь возможность программно добавлять новую работу cron, каков наилучший способ сделать это?
Из моего исследования кажется, что я мог бы сбросить текущий crontab, а затем добавить новый, отправив его обратно в crontab:
(crontab -l ; echo "0 * * * * wget -O - -q http://www.example.com/cron.php") | crontab -
Есть ли способ лучше?
21 ответ
Это всегда хорошо для меня.
Вы должны рассмотреть немного более сложный сценарий, который может сделать три вещи.
Добавить строку crontab; уверяя, что его не существует. Добавление, когда оно уже существует, плохо.
Удалите строку crontab. Возможно, только предупреждение, если оно не существует.
Сочетание двух вышеупомянутых функций для замены строки crontab.
Лучший способ, если вы работаете от имени пользователя root, это поместить файл в /etc/cron.d
если вы используете менеджер пакетов для упаковки вашего программного обеспечения, вы можете просто сложить файлы в этот каталог, и они будут интерпретироваться, как если бы они были crontabs, но с дополнительным полем для имени пользователя, например:
Имя файла: /etc/cron.d/per_minute
Содержание:* * * * * root /bin/sh /home/root/script.sh
В решении OP есть ошибка, она может позволить добавить записи дважды, используйте ниже для исправления.
(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
Добавить что-то в cron
(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | sort | uniq | crontab -
Чтобы удалить это из cron
(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | grep -v hupChannel.sh | sort | uniq | crontab -
надежда поможет кому-то
Большинство решений здесь для добавления строк в crontab. Если вам нужно больше контроля, вы захотите иметь возможность контролировать все содержимое crontab.
Вы можете использовать трубопровод, чтобы сделать это довольно элегантно.
Чтобы полностью переписать crontab, сделайте
echo "2 2 2 2 2 /bin/echo foobar" |crontab -
Это должно быть легко сочетать с другими ответами, описанными здесь, как
crontab -l | <something> | tee |crontab -
Или, если у вас есть содержимое в файле, это еще проще
cat <file> |crontab -
Просто измените редактор на команду:
EDITOR экспорта ="тройник"
echo "0 * * * * / bin / echo 'Hello World'" | crontab -e
Предполагая, что в вашем crontab уже есть запись, следующая команда должна работать относительно хорошо. Обратите внимание, что $CMD
Переменная есть только для удобства чтения. Сортировка перед фильтрацией дубликатов важна, потому что uniq
работает только на соседних линиях.
CMD='wget -O - -q http://www.example.com/cron.php"'
(crontab -l ; echo "0 * * * * $CMD") | sort | uniq | crontab -
Если у вас в данный момент есть пустой crontab, вы получите следующую ошибку для stderr:
no crontab for user
Если вы хотите избежать этого, вы можете добавить немного сложности добавить что-то вроде этого:
(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//" | sort | uniq | crontab -
Если вы планируете сделать это для однократного сценария, просто чтобы что-то увидеть, взгляните на "на"
Вот еще один способ, позволяющий избежать дублирования
(crontab -l 2>/dev/null | fgrep -v "*/1 * * * * your_command"; echo "*/1 * * * * your_command") | crontab -
И вот способ сделать ответ JohnZ и избежать no crontab for user
сообщение, или если вам нужно работать в set -eu
введите окружение и ничего не может вернуть ошибку (в этом случае 2>/dev/null
часть необязательна):
( (crontab -l 2>/dev/null || echo "") ; echo "0 * * * * your_command") | sort -u - | crontab -
Или, если вы хотите разделить вещи так, чтобы они были более читабельными:
new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
(echo "$preceding_cron_jobs" ; echo "$new_job") | sort - | uniq - | crontab -
Или, при желании, удалите все ссылки на your_command (например: если расписание изменилось, вы хотите, чтобы оно когда-либо использовалось только один раз). В этом случае нам больше не нужно uniq
(добавленный бонус, порядок ввода также сохраняется):
new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
preceding_cron_jobs=$(echo "$preceding_cron_jobs" | grep -v your_command )
(echo "$preceding_cron_jobs" ; echo "$new_job") | crontab -
man crontab также полезен:
CRONTAB (1)
НАЗВАНИЕ
crontab - manipulate per-user crontabs (Dillon's Cron)
СИНТАКСИС
crontab file [-u user] - replace crontab from file
crontab - [-u user] - replace crontab from stdin
crontab -l [user] - list crontab for user
function cronjob_exists($command){
$cronjob_exists=false;
exec('crontab -l', $crontab);
if(isset($crontab)&&is_array($crontab)){
$crontab = array_flip($crontab);
if(isset($crontab[$command])){
$cronjob_exists=true;
}
}
return $cronjob_exists;
}
function append_cronjob($command){
if(is_string($command)&&!empty($command)&&cronjob_exists($command)===FALSE){
//add job to crontab
exec('echo -e "`crontab -l`\n'.$command.'" | crontab -', $output);
}
return $output;
}
append_cronjob('* * * * * curl -s http://localhost/cron/test.php');
В добавление к ответу JohnZ, вот синтаксис для назначения в качестве root, если вы sudoer:
(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -
Это позволит проверить, что ваша команда еще не существует, прежде чем добавить ее.
crontab -l 2>/dev/null | grep -q '/path/to/script' || echo "5 * * * * /path/to/script" | crontab -
Приветствия.
Лучше всего использовать сборник пьес Ansible со следующей задачей:
---
- name: Deploy cron
hosts: all
gather_facts: false
tasks:
- name: Update Cron job
ansible.builtin.cron:
name: Run Drupal Cron Job
user: www-data
minute: "0"
job: "/var/www/html/drupal/vendor/bin/drush core:cron"
В приведенном выше решении используетсяdrush core:cron
, поскольку недавние вызовы cron Drupal требуют ключей (которые нужно было извлечь, а затем жестко запрограммировать).
См.: Настройка заданий cron с помощью команды cron .
Затем используйтеansible-playbook -i hosts deploy.yml
запустить его, гдеhosts
файл:
echo "[all]\n\192.168.0.123 ansible_connection=ssh ansible_user=root" > hosts
где192.168.0.123
ваш хост для развертывания.
Вы можете использовать его как часть сценариев развертывания или поместить в свойJenkinsfile
как часть вашего конвейера развертывания.
Чтобы иметь гибкость при изменении команды в будущем, вы можете сделать это (лучше всего работает со сценарием обновления)
MARK=SOME_UNIQUE_MARK_TEXT
LINE="This is the command # $MARK"
# NOTE: I'm using -e because I might want to avoid weird bash expansions for '*' or '$' and place:
# \x2A instead of *
# \x24 instead of $
( crontab -l | grep -v $MARK ; echo -e "0 * * * *" $LINE ) | crontab -
Таким образом я могу обновить старую команду crontab, которая больше не служит текущей цели.
В основном я получаю текущий crontab, я удаляю строку, содержащую MARK (grep -v
) и замените его новым, добавив в конец файла crontab через
echo -e
. В этом конкретном случае я хочу, чтобы он выполнялся каждый час в минуту 0
0 * * * *
как это видно отсюда.
Ниже то, что я использую в своем скрипте
1.
(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
Я добавляю решения, подобные решениям @JohnZ, которые не добавляют дубликатов, сохраняя при этом существующий порядок crontab. У нас довольно много вакансий, которые сильно комментируются, и нам нужно сохранить эту структуру.
$ { \
crontab -l; \
echo "*/1 * * * * echo job one" &>/dev/null; \
echo "*/30 * * * * echo job two" &>/dev/null; \
} | awk '(/^#/ || !a[$0]++)' | crontab -
Трубопроводный вывод в crontab
я не установил новый crontab для меня на macOS, поэтому вместо этого я нашел это решение, используя tee
редактор в вложенной оболочке:
(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)
Если вы хотите, чтобы задача запускалась от имени пользователя:
crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | crontab -
Если вы хотите, чтобы задача выполнялась с правами:
sudo crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | sudo crontab -
и проверьте задачу (с sudo или без):
crontab -l | sed '/^$/d; /#/d'
Вы также можете редактировать текстовый файл таблицы cron напрямую, но ваше решение кажется вполне приемлемым.