我需要通过运行的脚本添加一个cron作业来设置服务器。我目前正在使用Ubuntu。我可以使用crontab -e
,但这将打开一个编辑器来编辑当前的crontab。我想以编程方式执行此操作。
有可能这样做吗?
Cron作业通常存储在/var/spool/cron
下的每用户文件中
最简单的事情可能就是创建一个配置了作业的文本文件,然后将其复制到cron spool文件夹并确保它具有正确的权限。
我在python中编写了一个crontab部署工具:https://github.com/monklof/deploycron
pip install deploycron
安装你的crontab很容易,这会将crontab合并到系统的现有crontab中。
from deploycron import deploycron
deploycron(content="* * * * * echo hello > /tmp/hello")
以下是如何在不直接编辑cron文件的情况下修改cron条目(这是不赞成的)。
crontab -l -u <user> | sed 's/find/replace/g' | crontab -u <user> -
如果要删除cron条目,请使用:
crontab -l -u <user> | sed '/find/d' | crontab -u <user> -
我意识到这不是gaurav所要求的,但为什么不在一个地方拥有所有的解决方案呢?
这是一个不使用/要求新作业在文件中的单行程序:
(crontab -l 2>/dev/null; echo "*/5 * * * * /path/to/job -with args") | crontab -
2>/dev/null
非常重要,因此如果当前没有crontab条目,则不会获得某些* nix所产生的no crontab for username
消息。
对于用户crontabs(包括root),您可以执行以下操作:
crontab -l -u user | cat - filename | crontab -u user -
名为“filename”的文件包含要追加的项目。您也可以使用sed
或其他工具代替cat
进行文本操作。您应该使用crontab
命令而不是直接修改文件。
类似的操作是:
{ crontab -l -u user; echo 'crontab spec'; } | crontab -u user -
如果要修改或创建系统crontabs,则可以像处理普通文本文件一样对其进行操作。它们存储在/etc/cron.d
,/etc/cron.hourly
,/etc/cron.daily
,/etc/cron.weekly
,/etc/cron.monthly
目录以及文件/etc/crontab
和/etc/anacrontab
中。
在Ubuntu和许多其他发行版中,您只需将一个文件放入/etc/cron.d
目录中,该目录包含一行有效的crontab条目。无需在现有文件中添加一行。
如果你只需要每天运行一些东西,只需将文件放入/etc/cron.daily
即可。同样,您也可以将文件放入/etc/cron.hourly
,/etc/cron.monthly
和/etc/cron.weekly
。
Crontab文件只是文本文件,因此可以像任何其他文本文件一样对待。 crontab
命令的目的是使编辑crontab文件更安全。通过此命令编辑时,将检查文件是否存在错误,仅在没有错误时才保存。
crontab [path to file]
可用于指定存储在文件中的crontab。与crontab -e
一样,只有在没有错误的情况下才会安装该文件。
因此,脚本可以直接编写cron选项卡文件,也可以将它们写入临时文件并使用crontab [path to temp file]
命令加载它们。直接写入可以节省写入临时文件的时间,但也避免了安全检查。
更简单的回答你的问题是:
echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/root
您可以在远程服务器上设置cronjobs,如下所示:
#!/bin/bash
servers="srv1 srv2 srv3 srv4 srv5"
for i in $servers
do
echo "0 1 * * * /root/test.sh" | ssh $i " tee -a /var/spool/cron/root"
done
在Linux中,crontab
文件的默认位置是/var/spool/cron/
。在这里您可以找到所有用户的crontab
文件。您只需将cronjob条目附加到相应用户的文件即可。在上面的示例中,root用户的crontab文件将附加一个cronjob,以便每天凌晨1点运行/root/test.sh
。
作为对那些暗示crontab -l | crontab -
的修正:这不适用于每个系统。例如,我必须在运行旧版本SUSE的几十台服务器上向root crontab添加一个作业(不要问为什么)。旧的SUSE将注释行添加到crontab -l
的输出之前,使crontab -l | crontab -
非幂等(Debian在crontab手册页中识别此问题并修补其版本的Vixie Cron以更改crontab -l
的默认行为)。
要在crontab -l
添加注释的系统上以编程方式编辑crontabs,您可以尝试以下操作:
EDITOR=cat crontab -e > old_crontab; cat old_crontab new_job | crontab -
EDITOR=cat
告诉crontab使用cat
作为编辑器(不是通常的默认vi),它不会更改文件,而是将其复制到stdout。如果crontab -
期望以不同于crontab -e
输出的格式输入,那么这可能仍会失败。不要试图用crontab -
替换最终的crontab -e
- 它不会起作用。
(我没有足够的声誉来发表评论,所以我在作为答案添加:随意添加它作为他的答案旁边的评论)
Joe Casadonte's one-liner是完美的,除非你使用set -e
运行,即如果你的脚本设置为出错而失败,并且还没有cronjobs。在这种情况下,单行将不会创建cronjob,但不会停止脚本。沉默的失败可能会产生误导。
原因是crontab -l
返回一个1
返回码,导致后续命令(echo
)不被执行...因此没有创建cronjob。但由于它们作为子进程执行(因为括号),因此它们不会停止脚本。
(有趣的是,如果你再次运行相同的命令,它将工作:一旦你执行了crontab -
一次,crontab -l
仍然没有输出任何东西,但它不再返回错误(你不再得到no crontab for <user>
消息)。所以执行后续的echo
并创建crontab)
在任何情况下,如果你使用set -e
运行,该行必须是:
(crontab -l 2>/dev/null || true; echo "*/5 * * * * /path/to/job -with args") | crontab -
那么/etc/crontab
只是一个ascii文件所以最简单的就是
echo "*/15 * * * * root date" >> /etc/crontab
这将添加一个工作,每15分钟发送一次电子邮件。调整味道,并通过grep
或其他方式测试是否已添加该行以使您的脚本具有幂等性。
在Ubuntu等人,你也可以删除/etc/cron.*
中的文件,这样更容易做和测试---加上你不会搞乱(系统)配置文件,如/etc/crontab
。