如何以编程方式创建新的Cron作业?


129

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

我的研究来看,似乎可以转储当前的crontab,然后附加一个新的crontab,然后将其管道传输回crontab:

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

有没有更好的办法?


2
您的解决方案似乎是一个很好的解决方案。
Craig S

在Solaris上,只需删除最后一个crontab的破折号即可。您可以添加grep以避免在此处添加行。
lacroix1547


花括号而不是括号可以做到而不会产生一个进程。确保在括号周围留有空格,{...; }。
杰·温斯顿

Answers:


-25

对我来说一直很好。

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

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

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

  3. 结合以上两个功能来替换crontab行。


78
他问如何,你告诉他什么?
Cerin

1
如果用户还没有crontab怎么办?
Maxim Egorushkin

132

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

如果使用包管理器来打包软件,则只需将文件放在该目录中,它们的解释就好像是crontab一样,但用户名带有一个额外的字段,例如:

文档名称: /etc/cron.d/per_minute

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


5
只要确保所使用的cron版本支持/etc/cron.d/即可。大多数现代Linux发行版都可以。
sleske

8
这是最简单,最优雅的解决方案。当然,必须解析和编辑现有crontab以及其他不相关的条目。
Cerin

13
对此的一个潜在警告是cron接收该文件夹中的新附件的频率(每小时一次)。如果您希望自己的工作马上开始执行,请当心。
JonathanK

6
@JonathanK,您是否知道是否可以要求cron重新扫描/etc/cron.d/*?如果必须等待一个小时才能检查,就很难知道是否有任何事情在起作用!
Halfer 2014年

4
该文件的烫发应如何设置?chmod + x /etc/cron.d/per_minute吗?
吉奥

101

OP的解决方案存在一个错误,它可能允许条目被添加两次,请使用下面的内容进行修复。

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -

5
如果没有描述,这实际上是一个更好的解决方案。它确保命令不会两次添加到crontab。
2013年

2
对于重复条目问题,这几乎不是一个好的解决方案。如果同时在crontab中添加了另一行怎么办?
hmn

6
为确保唯一性,请sortuniq(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
紧接

6
不需要uniq。使用上的-u选项sort
papiro '16

6
我第一次编辑crontab时如何避免用户没有 crontab。
wyx

23

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

希望可以帮助某人


这正是我在寻找的内容,只需添加以下内容即可:grep -v'^#'| 过滤掉评论
Tjunkie 2014年

2
您实际上不需要,2>&1 | grep -v "no crontab"因为在没有crontab的情况下,输出行将crontab: no crontab for...发送到stderr。没有理由捕获该输出,将其发送到stdout,然后使用grep对其进行过滤。如果您的目标是避免crontab: no crontab for...在输出中看到,请使用2> /dev/null | sort....
matty 2016年


6

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

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e

3
当心-这会擦除所有现有条目。
starfry

5

假设您的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 -

5

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

您可以使用管道来优雅地完成此操作。

要完全重写crontab,请执行

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

这应该很容易与此处描述的其他答案结合使用

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

或者,如果您将内容包含在文件中,则它甚至更简单

cat <file> |crontab -

3

这是另一种避免重复的方式

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

2

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

3
说“从stdin替换crontab”的部分实际上是答案的一半:-)
Grodriguez

2

如果您是sudoer,则添加到JohnZ的答案中,这是作为root计划的语法:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -

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');


0

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

(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)

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'


-2

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


1
由于担心并发编辑会导致文件损坏的可能性,因此我对此不以为然。使用命令行crontab命令应避免该问题。
Craig S

克雷格(Craig),如果没有更多的研究,我将不确定命令行版本是否是原子版本,并且种族条件安全。无论如何可能都是“相当安全”的。
tuomassalo 2011年

没有root访问权限,“直接编辑文件”是不可行的(前提是您可以弄清楚用户的crontab文件位于何处,以及如何确保cron守护程序正确接收您的更改),而以编程方式进行“编辑”似乎是问题所在。首先要寻求建议。
2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.