简体   繁体   English

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

[英]How can I programmatically create a new cron job?

I want to be able to programatically add a new cron job, what is the best way to do this?我希望能够以编程方式添加新的 cron 作业,最好的方法是什么?

From my research , it seems I could dump the current crontab and then append a new one, piping that back into crontab:我的研究来看,我似乎可以转储当前的 crontab,然后附加一个新的,将其管道返回到 crontab:

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

Is there a better way?有没有更好的办法?

The best way if you're running as root, is to drop a file into /etc/cron.d如果您以 root 身份运行,最好的方法是将文件放入 /etc/cron.d

if you use a package manager to package your software, you can simply lay down files in that directory and they are interpreted as if they were crontabs, but with an extra field for the username, eg:如果您使用 package 管理器到 package 您的软件,您可以简单地将文件放在该目录中,它们被解释为好像它们是 crontabs,但用户名有一个额外的字段,例如:

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

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

OP's solution has a bug, it might allow entries to be added twice, use below to fix. OP 的解决方案有一个错误,它可能允许添加两次条目,使用下面来修复。

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

To Add something to cron向 cron 添加内容

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | sort | uniq | crontab -

To remove this from cron从 cron 中删除它

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | grep -v hupChannel.sh |  sort | uniq | crontab -

hope would help someone希望能帮助某人

Most of the solutions here are for adding lines to the crontab.这里的大多数解决方案都是为 crontab 添加行。 If you need more control, you'll want to be able to control the entire contents of the crontab.如果您需要更多控制,您将希望能够控制 crontab 的全部内容。

You can use piping to do this pretty elegantly.您可以使用管道非常优雅地做到这一点。

To completely rewrite the crontab, do要完全重写 crontab,请执行

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

This should be easy to combine with other answers described here like这应该很容易与此处描述的其他答案相结合,例如

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

Or, if you have the contents in a file, it is even simpler或者,如果您在文件中有内容,那就更简单了

cat <file> |crontab -

Simply change the editor to tee command:只需将编辑器更改为 tee 命令:

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

If you're planning on doing it for a run-once scenario for just wget'ing something, take a look at 'at'如果您打算在运行一次的情况下只做一些事情,请查看“at”

Assuming that there is already an entry in your crontab, the following command should work relatively well.假设您的 crontab 中已经有一个条目,那么下面的命令应该工作得比较好。 Note that the $CMD variable is only there for readability.请注意, $CMD变量只是为了便于阅读。 Sorting before filtering duplicates is important, because uniq only works on adjacent lines.在过滤重复之前进行排序很重要,因为uniq仅适用于相邻行。

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

If you currently have an empty crontab, you will receive the following error to stderr:如果您当前有一个空的 crontab,您将收到以下错误到 stderr:

no crontab for user

If you want to avoid this, you can add a little bit of complexity add do something like this:如果你想避免这种情况,你可以增加一点复杂性添加做这样的事情:

(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//"  | sort | uniq | crontab -

Here's another one-liner way, that avoids duplicates这是另一种单行方式,可避免重复

(crontab -l 2>/dev/null | fgrep -v "*/1 *  *  *  * your_command"; echo "*/1 *  *  *  * your_command") | crontab -

And here's a way to do JohnZ's answer and avoid no crontab for user message, or if you need to operate in a set -eu type environment and can't have anything return a failure (in which case the 2>/dev/null part is optional):这是一种回答 JohnZ 并避免no crontab for user消息的方法,或者如果您需要在set -eu类型环境中操作并且不能让任何东西返回失败(在这种情况下, 2>/dev/null部分是可选的):

( (crontab -l 2>/dev/null || echo "")  ; echo "0 * * * * your_command") | sort -u - | crontab -

Or if you want to split things up so that they're more readable:或者,如果您想拆分内容以使其更具可读性:

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
(echo "$preceding_cron_jobs" ; echo "$new_job") | sort - | uniq - | crontab -

Or optionally remove any references to your_command (ex: if the schedule has changed, you only want it ever cron'ed once).或者可以选择删除对 your_command 的任何引用(例如:如果时间表已更改,您只希望它曾经 cron'ed 一次)。 In this case we no longer need uniq (added bonus, insertion order is also preserved):在这种情况下,我们不再需要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 -

Adding to JohnZ's answer, here's the syntax to schedule as root if you are a sudoer:添加到 JohnZ 的答案中,如果您是 sudoer,以下是作为 root 进行调度的语法:

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

man crontab is also useful: man crontab 也很有用:

CRONTAB(1)克朗塔布(1)

NAME姓名

   crontab - manipulate per-user crontabs (Dillon's Cron)

SYNOPSIS概要

   crontab file [-u user] - replace crontab from file

   crontab - [-u user] - replace crontab from stdin

   crontab -l [user] - list crontab for user
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');

This would check to ensure that your command doesn't already exist before adding it.这将检查以确保您的命令在添加之前不存在。

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

Cheers.干杯。

Piping stdout into crontab didn't install the new crontab for me on macOS, so I found this solution instead, using the tee editor in a sub shell:将 stdout 导入crontab并没有在 macOS 上为我安装新的 crontab,所以我找到了这个解决方案,使用子 shell 中的tee编辑器:

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

If you want the task to run as a user:如果您希望任务以用户身份运行:

crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | crontab -

If you want the task to run with privileges:如果您希望任务以特权运行:

sudo crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | sudo crontab -

and check task (with or without 'sudo'):并检查任务(有或没有'sudo'):

crontab -l | sed '/^$/d; /#/d'

also you can add your tasks to /etc/cron.*/您也可以将任务添加到 /etc/cron.*/

Below is what I use in my script以下是我在脚本中使用的内容

1. 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 -

#write out current crontab #写出当前的crontab

crontab -l > mycron 2>/dev/null

#echo new cron into cron file #echo 新的 cron 到 cron 文件中

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

#install new cron file #安装新的cron文件

crontab mycron

rm mycron

To have flexibility when changing the command in the future you can do this (works best with an update script)为了在将来更改命令时具有灵活性,您可以这样做(最适合使用更新脚本)

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 -

In this way I can update an old crontab command which no longer serves current purpose.通过这种方式,我可以更新不再用于当前目的的旧 crontab 命令。

Basically I get the current crontab, I eliminate the line containing the MARK ( grep -v ) and replace it with the new one by appending it at the end of the crontab file via echo -e .基本上我得到了当前的 crontab,我删除了包含 MARK ( grep -v )的行,并通过echo -e将其附加到 crontab 文件的末尾,将其替换为新的。 In this particular case I want it executed every hour at minute 0 0 * * * * as it can be seen from here .在这种特殊情况下,我希望它每小时在 0 0 * * * *分钟执行一次,从这里可以看出。

I'm adding a solutions similar to @JohnZ's that does not add duplicates while still preserving the existing order of crontab.我正在添加一个类似于@JohnZ 的解决方案,它不会添加重复项,同时仍保留现有的 crontab 顺序。 We have quite a few jobs that are heavily commented and we need to preserve that structure.我们有很多工作受到大量评论,我们需要保留这种结构。

$ { \
    crontab -l; \
    echo "*/1  * * * *   echo job one"  &>/dev/null; \
    echo "*/30 * * * *   echo job two"  &>/dev/null; \
  } | awk '(/^#/ || !a[$0]++)' | crontab -

You could also edit the cron table text file directly, but your solution seems perfectly acceptable.您也可以直接编辑 cron 表文本文件,但您的解决方案似乎完全可以接受。

It's always worked well for me.它对我来说总是很有效。

You should consider a slightly more sophisticated script that can do three things.您应该考虑一个稍微复杂的脚本,它可以做三件事。

  1. Append a crontab line; Append 一条 crontab 行; assuring that it didn't exist.确保它不存在。 Adding when it already exists is bad.在它已经存在时添加是不好的。

  2. Remove the crontab line.删除 crontab 行。 Perhaps only warning if it didn't exist.如果它不存在,也许只有警告。

  3. A combination of the above two features to replace the crontab line.结合以上两个特性来替换 crontab 行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM