145

我希望能够以编程方式添加新的 cron 作业,最好的方法是什么?

根据我的研究,似乎我可以转储当前的 crontab,然后附加一个新的,将其管道返回到 crontab:

(crontab -l ; echo "0 * * * * wget -O - -q http://www.example.com/cron.php") | crontab -

有没有更好的办法?

4

19 回答 19

153

如果您以 root 身份运行,最好的方法是将文件放入 /etc/cron.d

如果您使用包管理器来打包您的软件,您可以简单地将文件放在该目录中,并且它们被解释为好像它们是 crontabs,但带有一个额外的用户名字段,例如:

文件名:/etc/cron.d/per_minute

内容: * * * * * root /bin/sh /home/root/script.sh

于 2009-03-04T14:38:40.920 回答
110

OP 的解决方案有一个错误,它可能允许添加两次条目,使用下面来修复。

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
于 2012-11-13T04:49:18.073 回答
26

向 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 -

希望能帮助某人

于 2014-07-22T16:14:28.930 回答
9

这里的大多数解决方案都是为 crontab 添加行。如果您需要更多控制,您将希望能够控制 crontab 的全部内容。

您可以使用管道非常优雅地做到这一点。

要完全重写 crontab,请执行

echo "2 2 2 2 2 /bin/echo foobar" |crontab -

这应该很容易与此处描述的其他答案相结合,例如

crontab -l | <something> | tee |crontab -

或者,如果您在文件中有内容,那就更简单了

cat <file> |crontab -
于 2018-06-13T13:49:25.447 回答
6

如果您打算在运行一次的情况下只做一些事情,请查看“at”

于 2009-03-04T14:44:20.033 回答
6

只需将编辑器更改为 tee 命令:

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e
于 2014-06-17T14:15:01.767 回答
5

假设您的 crontab 中已经有一个条目,那么下面的命令应该工作得比较好。请注意,该$CMD变量仅用于可读性。在过滤重复之前排序很重要,因为uniq仅适用于相邻行。

CMD='wget -O - -q http://www.example.com/cron.php"'
(crontab -l ; echo "0 * * * * $CMD") | sort | uniq | crontab -

如果您当前有一个空的 crontab,您将收到以下错误到 st​​derr:

no crontab for user

如果你想避免这种情况,你可以增加一点复杂性添加做这样的事情:

(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//"  | sort | uniq | crontab -
于 2013-07-31T11:32:14.773 回答
4

这是另一种单行方式,可避免重复

(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 的任何引用(例如:如果时间表已更改,您只希望它曾经 cron'ed 一次)。在这种情况下,我们不再需要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 -
于 2018-04-17T19:28:50.523 回答
3

man 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
于 2009-03-06T10:41:51.067 回答
2

添加到 JohnZ 的答案中,如果您是 sudoer,以下是作为 root 进行调度的语法:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -
于 2015-07-24T16:00:23.250 回答
1
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');
于 2014-07-14T00:32:11.593 回答
1

这将检查以确保您的命令在添加之前不存在。

crontab -l 2>/dev/null | grep -q '/path/to/script' || echo "5 * * * * /path/to/script" | crontab -

干杯。

于 2016-11-11T11:43:22.423 回答
0

您也可以将任务添加到 /etc/cron.*/

于 2009-03-06T10:39:28.623 回答
0

将stdout 插入crontab并没有在 macOS 上为我安装新的 crontab,所以我找到了这个解决方案,tee在子 shell 中使用编辑器:

(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)
于 2017-08-19T10:33:27.583 回答
0

如果您希望任务以用户身份运行:

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'
于 2019-10-21T14:29:57.087 回答
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

#echo 新的 cron 到 cron 文件中

echo "0 3 * * * /usr/local/bin/certbot-auto renew" >> mycron

#安装新的cron文件

crontab mycron

rm mycron
于 2020-09-23T09:42:29.613 回答
0

为了在将来更改命令时具有灵活性,您可以这样做(最适合使用更新脚本)

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 * * * *可以看出。

于 2020-12-05T21:08:39.790 回答
-2

您也可以直接编辑 cron 表文本文件,但您的解决方案似乎完全可以接受。

于 2009-03-04T14:36:41.580 回答
-28

它对我来说总是很有效。

您应该考虑一个稍微复杂一点的脚本,它可以做三件事。

  1. 附加一个 crontab 行;确保它不存在。在它已经存在时添加是不好的。

  2. 删除 crontab 行。如果它不存在,也许只有警告。

  3. 结合以上两个特性来替换 crontab 行。

于 2009-03-04T14:38:42.357 回答