Додайте щось до crontab програмно (через ssh)


13

У мене є сценарій розгортання, він повинен щось додавати користувачеві crontab(запускати сценарій, який очищає журнали кожні XXX дні), однак це потрібно робити лише під час першого розгортання або коли його потрібно оновити.

(Я можу бігати xxx.py deploy envабо xxx.py update env)

тому я повинен це зробити:

Check if my cronJob already exist
Put my cronJob if it does not already exist
or
update my cronjob if one of the parameter of the command is different

Я не бачу, як додати / перевірити / видалити щось до crontabбез використання crontab -eта редагування crontabфайлу (завантажити його, переписати, повторно завантажити)

PS: це специфічний для користувача cronjob, "webadmin" збирається це зробити, і він не повинен використовувати sudo для цього.


1
Чи повинен він знаходитись у конкретному користувальницькому кронтабі? Більшість заданих пакетів cron переходять у один із каталогів /etc/cron.*.
CVn

У CentOS є /etc/cron.d? Якщо так, введіть свій скрипт, використовуючи унікальне для вашої програми ім’я
roaima

так, це специфічно для користувача. Я не можу додати його до /etc/cron.d, тому що це кореневий файл, тому всередині роботи роботи корінця (я можу судо, але що мені сказали погану практику)
sliders_alpha

1
як у /etc/crontabфайлів у /etc/cron.d/додатковому полі для імені користувача, відразу після специфікації розкладу. напр * * * * * username /path/to/script. Подивіться man 5 crontabі шукайте SYSTEM CRON.
cas

Відповіді:


15

моя найкраща ідея поки що

спочатку перевірити, чи відповідає вміст тому, що має бути там, і лише оновити, якщо він не виконаний:

if [[ $(crontab -l | egrep -v "^(#|$)" | grep -q 'some_command'; echo $?) == 1 ]]
then
    echo $(crontab -l ; echo '* 1 * * * some_command') | crontab -
fi

але це стає достатньо складним, щоб створити окремий сценарій навколо цієї задачі на Cron.

інші ідеї

ви можете надіслати рядок через stdin до crontab (будьте обережні, це очищає будь-які попередні записи crontab):

echo "* 1 * * * some_command" | crontab -

це навіть повинно працювати прямо через ssh:

echo "* 1 * * * some_command" | ssh user@host "crontab -"

якщо ви хочете додати файл, ви можете скористатися цим:

# on the machine itself
echo "$(echo '* 1 * * * some_command' ; crontab -l)" | crontab -
# via ssh
echo "$(echo '* 1 * * * some_command' ; ssh user@host crontab -l)" | ssh user@host "crontab -"

це залежить: чи потрібно вам, що б там було? :)
Phillip -Zyan K Lee- Stockmann

awww ... не працює як root? ... Я перепишу це ...
Філіп -Зіян К Лі- Стокман

е, мені це подобається: D
sliders_alpha

У мене було дві проблеми з цим рішенням: 1) echo '*...розширено *список до файлів. 2) закінчення рядків у crontab видалено.
Хіт

Мені вдалося виправити ці проблеми: 1) змінити echo "*...та 2) видалити echo $з початку рядка.
Хіт

3

Для запису я буду пропонувати використовувати /etc/cron.d/. Тут можуть писати файли тільки root, але записи можна виконувати як будь-який користувач (без потреби sudo).

echo '0 0 * * 0 webadmin /usr/local/bin/tidy_logfiles' > ~/webadmin.cron
scp -p ~/webadmin.cron root@remote_host:/etc/cron.d/webadmin

Це можна застосувати кілька разів, по webadmin.cronмірі необхідності оновити локальний файл, перш ніж скопіювати його поперек.

Ви навіть можете видалити резервування:

ssh -q root@remote_host rm -f /etc/cron.d/webadmin

Зауважте, що у багатьох випадках ви не можете вказати пароль root для команд scp/ ssh. Натомість вам потрібно встановити сертифікати відкритого / приватного ключа. Крім того, локальний обліковий запис (який би він не був) матиме повний кореневий доступ до віддаленого сервера. Наразі незрозуміло, чи це буде зупинка шоу для вашого конкретного сценарію.


Це мій сервер клієнтів, я не можу ввійти як root, я можу вступити в нього, але якщо я це зробить, вони мене вб'ють. Це робота з webadlmin, тому вона має бути лише в речах webadmin, ось що мені сказав sysadmin.
sliers_alpha

@sliders_alpha робота працює лише як webadmin. Саме резервування вимагає кореневої еквівалентності. Однак я також шукатиму некореневе рішення.
roaima

1
+1. /etc/cron.d/існує саме для цієї мети - так що пакунки / розгортання можуть просто випустити сюди файл crontab.
cas

3

Я настійно рекомендую використовувати Ansible * для цього, а не прокручувати свій власний. Або ляльковий або шеф-кухар - але Ansible добре підходить для сценаріїв розгортання з нульовою інфраструктурою, як це.

Це тому, що вже є модулі, призначені для вирішення подібних проблем, а інструменти управління конфігурацією мають ідентифікацію як основну мету проектування - це властивість змінюватися лише тоді, коли це потрібно, навіть якщо ви випадково (або навмисно) запускаєте її знову.

Зокрема, cron-модуль Ansible може змінювати крони користувачів. Як бонус, якщо ви хочете пізніше налаштувати на використання системних копійок, це буде дуже легким настроєм, а не переписанням.


* відмова від відповідальності: я працюю в Red Hat, а Ansible - проект, який фінансується Red Hat.


Так, я не знав про ansible 2 місяці тому, і тепер у нас є масивний сценарій розгортання python (але він ВІДМОВНИЙ, читабельний, керується,;)) Наступного разу я використаю ansible, але зараз переходжу назад неможливо (грошові гроші гроші)
слайдери_алфа

1

Якщо ви хочете додати завдання cron через цільовий обліковий запис, запустіть crontab -e. Ця команда передає crontab через редактор. Скажіть йому, щоб скористатися командою редактора, яка змінює crontab за вашим бажанням. Команда редактора виконується як фрагмент оболонки із доданим ім'ям тимчасового файлу.

unset VISUAL
EDITOR='update_crontab () {
  set -e
  new=$(mktemp)
  if <"$1" grep -v "^#" | grep -w do_stuff; then
    # Remove existing entries containing do_stuff
    grep -v -w do_stuff "$1" >"$new"
  else
    cp "$1" "$new"
  fi
  # Add the new entry
  echo "1 2 3 4 5 do_stuff --new-options" >>"$new"
  mv "$new" "$1"
}
update_crontab' crontab -e

Цей підхід є більш надійним, ніж нативний, crontab -l | … | crontab -тому що цей вразливий до перегонів, якщо crontab редагується одночасно: зміни, внесені між викликом до crontab -lта закликом до crontab -, будуть скасовані.


1

Це адаптація того, що запропонував @ phillip-zyan-k-lee-stockmann , спираючись на його код "Найкраща ідея поки що".

Мої зміни від його (відмінний і корисний фрагмент) в основному:

  • Regex - це не лише ім'я команди, але й весь запис, включаючи часові рядки. Таким чином, він може підтримувати додавання команди, навіть якщо в інших записах є команди з одноіменними або перекриваються іменами. (Він все одно не буде додавати одну і ту ж команду в той же графік двічі.)
  • Трохи рубок
  • З різних причин я перейшов (і назвав) шахту на погодинну; легко відрегулювати його назад за синтаксисом crontab

І ось ось мій код того, що я зателефонував crontab-add-hourly.sh:

#!/bin/bash

# PURPOSE:
# To allow simple, programmatic addition of commands/entries into the crontab (if not already present)

cmd=$1
entry="0 * * * * $cmd"
printf "we want to add this entry:\n$entry\n\n" 
escapedEntry=$(printf '%s\n' "$entry" | sed 's:[][\/.^$*]:\\&:g') #from: https://unix.stackexchange.com/a/129063/320236
printf "but first we'll see if it's already in there using this regex pattern:\n$escapedEntry\n\n"

if [[ $(crontab -l | egrep -v '^(#|$)' | grep -q "$escapedEntry"; echo $?) == 1 ]] # from: https://unix.stackexchange.com/a/297377/320236
then
    printf "all clear; pattern was not already present; adding command to crontab hourly:\n$cmd\n\n"
    (crontab -l ; printf "$entry\n\n") | crontab -
else
    printf "pattern already present; no action taken\n\n"
fi

Приклад використання та виведення:

$ ./crontab-add-hourly.sh my-script.bash

we want to add this entry:
0 * * * * my-script.bash

but first we'll see if it's already in there using this regex pattern:
0 \* \* \* \* my-script\.bash

all clear; pattern was not already present; adding command to crontab hourly:
my-script.bash

0

TL; DR: Це фактично працює, перевірено на Bash 4.4.

if [[ $(crontab -l | egrep -v "^(#|$)" | grep -q 'some_command'; echo $?) == 1 ]]
then
    set -f
    printf "$(crontab -l ; echo '* * * * * some_command')\n" | crontab -
    set +f
fi

Як зазначається у коментарях @Phillip -Zyan K Lee- Stockmann, це рішення поширюється *на всі файли в поточному каталозі. Не вдалося запропонувати коментарі працювати. set -f відключає розширення підстановки, див. https://stackoverflow.com/a/11456496/915441 .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.