Как добавить / удалить задания cron с помощью сценария?

Вы можете, просто включите extdebug и верните ненулевой код ( См. описание extdebug option ) из myHandler :

$ function myHandler() {
  if [[ $SKIP = "true" ]]; then return 1; fi;
  echo 'myHandler execute'
}
$ trap 'myHandler' DEBUG
$ shopt -s extdebug
$ echo 1
myHandler execute
1
$ SKIP=true
myHandler execute
$ echo 1

3
06.05.2017, 17:01
4 ответа

Использование cron является правильным способом планирования периодического запуска задач в большинстве систем Unix. Использование личного crontab — наиболее удобный способ для пользователя планировать свои собственные задачи. Системные задачи могут планироваться пользователем root (не используя приведенный ниже сценарий! ) в системном crontab, который обычно имеет немного другой формат (дополнительное поле с именем пользователя).

Вот вам простой скрипт. Любой пользователь может использовать это для управления своим личным crontab.

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

  • Подкоманда remove принимает номер строки и удаляет содержимое этой строки в crontab, независимо от того, что это такое. Номер передается в несанированном виде непосредственно в sed.

  • Запись crontab при ее добавлении должна быть заключена в кавычки. Это влияет на то, как вы должны обрабатывать кавычки внутри самой записи crontab.

Большинство из этих вещей должно быть относительно легко исправить.

#!/bin/sh

usage () {
    cat <<USAGE_END
Usage:
    $0 add "job-spec"
    $0 list
    $0 remove "job-spec-lineno"
USAGE_END
}

if [ -z "$1" ]; then
    usage >&2
    exit 1
fi

case "$1" in
    add)
        if [ -z "$2" ]; then
            usage >&2
            exit 1
        fi

        tmpfile=$(mktemp)

        crontab -l >"$tmpfile"
        printf '%s\n' "$2" >>"$tmpfile"
        crontab "$tmpfile" && rm -f "$tmpfile"
        ;;
    list)
        crontab -l | cat -n
        ;;
    remove)
        if [ -z "$2" ]; then
            usage >&2
            exit 1
        fi

        tmpfile=$(mktemp)

        crontab -l | sed -e "$2d" >"$tmpfile"
        crontab "$tmpfile" && rm -f "$tmpfile"
        ;;
    *)
        usage >&2
        exit 1
esac

Пример использования:

$ ./script
Usage:
    ./script add "job-spec"
    ./script list
    ./script remove "job-spec-lineno"

$ ./script list
     1  */15 * * * * /bin/date >>"$HOME"/.fetchmail.log
     2  @hourly /usr/bin/newsyslog -r -f "$HOME/.newsyslog.conf"
     3  @reboot /usr/local/bin/fetchmail

$ ./script add "0 15 * * * echo 'hello world!'"

$ ./script list
     1  */15 * * * * /bin/date >>"$HOME"/.fetchmail.log
     2  @hourly /usr/bin/newsyslog -r -f "$HOME/.newsyslog.conf"
     3  @reboot /usr/local/bin/fetchmail
     4  0 15 * * * echo 'hello world!'

$ ./script remove 4

$ ./script list
     1  */15 * * * * /bin/date >>"$HOME"/.fetchmail.log
     2  @hourly /usr/bin/newsyslog -r -f "$HOME/.newsyslog.conf"
     3  @reboot /usr/local/bin/fetchmail
8
27.01.2020, 21:10

Если вам нужна запись cron:

0 * * * * my_script

, то я рекомендую вам придумать отдельное имя для вашей функции управления cron, например, "cron_mgmt", первым аргументом которой является SWITCH в операторе CASE:

cron_mgmt () {

    case $1 in
    add ) ... ;;
    list ) ...;;
    remove ) ...
    help ) ...
    * )  echo "You need help. Here it is"
         cron_mgmt help
         ;;
    esac
}   
0
27.01.2020, 21:10

Вместо того, чтобы создавать собственный интерфейс, сделайте его простым. Чтобы установить задание cron с определенным расписанием, поместите его в определенный каталог. Чтобы удалить его, удалите его из каталога. Вам не нужно предоставлять пользователям какие-либо инструменты для этого, просто сообщите им, в какой каталог поместить их задание.

Именно так большинство дистрибутивов Linux управляют системными заданиями cron, которые могут быть установлены отдельными пакетами. Debian, Fedora, Arch Linux и другие содержат инструмент под названием run-parts, задачей которого является запуск сценариев в определенном каталоге один за другим. Различные реализации run-parts имеют разные правила относительно того, какие именно имена файлов приемлемы для сценариев. Если вы не хотите зависеть от этого, вы можете создать свой собственный:

for x in /path/to/daily-jobs/*; do
  if [ -x "$x" ]; then
    case "${x##*/}" in
      *[!-0-9A-Z_a-z]*) :;; # skip file names containing "weird" characters
      *) "$x";;
    esac
  fi
done

Если вы хотите разрешить пользователям указывать свое собственное расписание, этот подход не будет работать. Вам необходимо перестраивать файл crontab каждый раз при отправке нового задания. Это можно сделать, но сложно надежно настроить. Однако, если пользователи могут указывать свое собственное расписание, то нет особых причин добавлять еще один интерфейс поверх crontab -e или графический интерфейс, который вызывает crontab -e.

0
27.01.2020, 21:10

Ваша текущая реализация cron, вероятно, поддерживает /etc/cron.d, где задания имеют дополнительный пользователь «запуск от имени», указанный после обычных полей времени и перед командой. Итак, просто настройте свой интерфейс для создания файлов в этом каталоге, таких как обычные записи cron, с именем пользователя (возможно, извлеченным из логина), добавленным после пятого поля. Затем вы можете выполнять одно задание для каждого файла.:)

Посмотрите на man 5 crontab https://linux.die.net/man/5/crontab

Обратите внимание, что основная проблема заключается в том, что пользователь, который может редактировать файлы в этот каталог может создать файл, который запускается от имени пользователя root. Итак, вы, вероятно, хотите, чтобы скрипт-оболочка запускался через sudo, который будет проверять ввод и заставлять вычисленное имя пользователя в сгенерированный файл. А затем нужно убедиться, что вы делаете что-то безопасно в сценарии, например, не доверяете $PATH и т. д.

PS, в сценарии оболочки: getent passwd $(

Честно говоря, если вы знакомите пользователей с форматом времени cron, несколько дополнительных секунд, чтобы научить их использовать crontab -e (и установить $EDITOR, если vi пугает ) не очень сложно.

1
27.01.2020, 21:10

Теги

Похожие вопросы