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

Posted

技术标签:

【中文标题】如何以编程方式创建新的 cron 作业?【英文标题】:How can I programmatically create a new cron job? 【发布时间】:2010-10-11 06:48:07 【问题描述】:

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

从my research 看来,我可以转储当前的 crontab,然后附加一个新的,将其通过管道传输回 crontab:

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

有没有更好的办法?

【问题讨论】:

您的解决方案似乎不错。 在 Solaris 上只需删除最后一个 crontab 的破折号。您可以添加 grep 以避免添加已经存在的行。 How to create a cron job using Bash的可能重复 花括号而不是括号将在不产生进程的情况下完成。确保在大括号周围保留空格, ... ; . @davidmytton - 你会考虑将你选择的答案更改为 MarkR 的答案 - 我认为共识是它是对问题的更好答案,并且会为其他人改进这个 *** 条目 【参考方案1】:

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

【讨论】:

我会对此持怀疑态度,因为我担心并发编辑可能会导致文件损坏。使用命令行 crontab 命令应该可以避免这个问题。 克雷格,如果没有更多的研究,我不能确定命令行版本是原子的和竞争条件安全的。无论如何,可能“相当安全”。 “直接编辑文件”在没有 root 访问权限的情况下是不可行的(前提是您可以弄清楚用户的 crontab 文件所在的位置,以及如何确保 cron 守护进程正确接收您的更改),以及“编辑" 以编程方式似乎是问题首先需要建议的内容。【参考方案2】:

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

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

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

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

【讨论】:

只要确保使用的 cron 版本支持 /etc/cron.d/。大多数现代 Linux 发行版都可以。 这是最简单、最优雅的解决方案。当然,不必解析和编辑现有的 crontab 以及其他不相关的条目。 对此的一个潜在警告是 cron 将新添加到此文件夹的频率(每小时一次)。如果您希望您的工作立即开始,请当心。 @JonathanK,你知道是否可以要求cron重新扫描/etc/cron.d/*吗?如果必须等待一个小时来检查,就很难知道某件事是否有效! 应该如何设置这个文件的权限? chmod +x /etc/cron.d/per_minute ?【参考方案3】:

它对我来说总是很有效。

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

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

    删除 crontab 行。也许只有在它不存在时才会发出警告。

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

【讨论】:

他问怎么做,你告诉他什么? 如果用户还没有 crontab 怎么办? 请举例回答问题【参考方案4】:

如果您打算为只运行一次的场景执行此操作,请查看 'at'

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

【讨论】:

说“从标准输入替换 crontab”的部分实际上是一半的答案:-)【参考方案7】:

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

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

【讨论】:

如果没有描述,这实际上是一个更好的解决方案。它确保命令不会两次添加到 crontab。 这不是一个很好的解决重复条目问题的方法。如果同时在 crontab 中添加了另一行怎么办? 为了保证唯一性,在uniq之前只需要sort,例如:(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab - 不需要uniq。在sort 上使用-u 选项。 第一次编辑 crontab 时如何避免 no crontab for user【参考方案8】:

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

【讨论】:

【参考方案9】:

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

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

【讨论】:

当心 - 这会擦除所有现有条目。【参考方案10】:
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');

【讨论】:

【参考方案11】:

向 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 '^#' |过滤掉 cmets 你实际上不应该需要2>&1 | grep -v "no crontab",因为当没有crontab时,输出行crontab: no crontab for...被发送到stderr。没有理由捕获该输出,将其发送到标准输出,然后使用 grep 将其过滤掉。如果您的目标是避免在输出中看到crontab: no crontab for...,请使用2> /dev/null | sort....【参考方案12】:

除了 JohnZ 的回答之外,如果您是 sudoer,以下是作为 root 调度的语法:

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

【讨论】:

【参考方案13】:

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

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

干杯。

【讨论】:

【参考方案14】:

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

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

【讨论】:

【参考方案15】:

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

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

【讨论】:

【参考方案16】:

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

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

要完全重写 crontab,请这样做

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

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

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

或者,如果你有一个文件中的内容,那就更简单了

cat <file> |crontab -

【讨论】:

【参考方案17】:

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

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'

【讨论】:

【参考方案18】:

以下是我在脚本中使用的内容

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 new cron 到 cron 文件中

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

#安装新的 cron 文件

crontab mycron

rm mycron

【讨论】:

【参考方案19】:

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

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) 的行,并通过 echo -e 将其附加到 crontab 文件的末尾,将其替换为新的行。在这种特殊情况下,我希望它每小时在第 0 分钟执行一次 0 * * * *,从 here 可以看出。

【讨论】:

以上是关于如何以编程方式创建新的 cron 作业?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式设置 Cron 作业?

如何以编程方式完成作业后停止cron作业

如何以编程方式创建新的本地 SQL Server 实例?

如何使用 php 脚本创建 cron 作业?

如何使用 Android 4.0 以编程方式创建新的 *** 接口?

如何在 Swift 中以编程方式创建新的 UIViewController