如何通过脚本添加/删除 cron 作业?

que*_*ued 3 cron shell-script

我将制作一个在启动时执行并定期运行的 bash 脚本。

我希望它是用户可配置的,以便用户可以0 * * * * my_script通过运行添加 cron 作业my_script add 0 * * * *,列出作业my_script list,并删除my_script remove job_number作业编号在my_script list命令输出中列出的位置。

如果我可以单独管理 crontab 文件,这将很容易实现。但是,似乎 crontab 每个用户只有一个文件(如果不是,请告诉我)。当然,直接处理那个 crontab 文件是一个糟糕的解决方案。

那么处理cron作业的正确方法是什么?或者,有没有更好的方法来处理定期运行的脚本?

状况:

  1. 任何用户都应该能够运行它,无论是否有特权。
  2. 没有依赖性。

补充问题:

由于我找不到任何适当的方法来管理定期运行的脚本,我想我可能做错了什么。在软件设计的意义上,实现接口来管理软件的定时任务是不是不切实际?我应该将所有日程管理留给用户吗?

Kus*_*nda 8

使用 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
Run Code Online (Sandbox Code Playgroud)

使用示例:

$ ./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
Run Code Online (Sandbox Code Playgroud)