我需要通过我运行的脚本添加一个cron作业来设置服务器。我目前正在使用Ubuntu。我可以使用crontab -e,但这将打开一个编辑器来编辑当前的crontab。我想通过编程来实现。
crontab -e
可以这样做吗?
/etc/crontab只是一个ascii文件,所以最简单的就是
/etc/crontab
echo "*/15 * * * * root date" >> /etc/crontab
这会增加一份每15分钟给你发邮件的工作。调整口味,并通过grep或其他方法测试是否已经添加了行,使你的脚本是幂等的。
grep
在Ubuntu等上,你也可以在/etc/cron.*中放置文件,这更容易做和测试——另外,你不会混淆(系统)配置文件,如/etc/crontab。
/etc/cron.*
在Ubuntu和许多其他发行版中,你可以将一个文件放入/etc/cron.d目录中,其中只包含一行有效的定时任务条目。不需要向现有文件添加行。
/etc/cron.d
如果你只是需要每天运行一些东西,只需将一个文件放入/etc/cron.daily。同样,你也可以将文件放到/etc/cron.hourly、/etc/cron.monthly和/etc/cron.weekly中。
/etc/cron.daily
/etc/cron.hourly
/etc/cron.monthly
/etc/cron.weekly
Cron作业通常存储在/var/spool/cron下的每个用户文件中
/var/spool/cron
您要做的最简单的事情可能就是创建一个配置了作业的文本文件,然后将其复制到cron spool文件夹,并确保它具有正确的权限(600)。
Crontab文件是简单的文本文件,因此可以像对待任何其他文本文件一样对待。crontab命令的目的是使编辑crontab文件更安全。当通过这个命令进行编辑时,将检查文件是否有错误,只有在没有错误时才保存。
crontab
crontab [path to file]可用于指定存储在文件中的crontab。像crontab -e一样,这只会在没有错误的情况下安装文件。
crontab [path to file]
因此,脚本既可以直接写入cron选项卡文件,也可以将它们写入临时文件,并使用crontab [path to temp file]命令加载它们。直接写入避免了必须写入临时文件,但也避免了安全检查。
crontab [path to temp file]
对于crontabs用户(包括root),您可以执行如下操作:
crontab -l -u user | cat - filename | crontab -u user -
其中名为“filename”的文件包含要追加的项。你也可以使用sed或其他工具来代替cat进行文本操作。你应该使用crontab命令,而不是直接修改文件。
sed
cat
类似的操作是:
{ crontab -l -u user; echo 'crontab spec'; } | crontab -u user -
如果您正在修改或创建系统crontab,那么可以像操作普通文本文件一样对它们进行操作。它们存储在/etc/cron.d, /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthly目录和文件/etc/crontab和/etc/anacrontab中。
/etc/anacrontab
下面是一个单行程序,它不使用/要求新作业在文件中:
(crontab -l 2>/dev/null; echo "*/5 * * * * /path/to/job -with args") | crontab -
2>/dev/null很重要,这样你就不会得到一些*nix在当前没有crontab项时产生的no crontab for username消息。
2>/dev/null
no crontab for username
作为对那些建议crontab -l | crontab -的纠正:这并不适用于每个系统。例如,我必须在运行旧版本SUSE的数十台服务器上向根crontab添加一个作业(不要问为什么)。旧的su在crontab -l的输出前加上注释行,使得crontab -l | crontab -非幂等(Debian在crontab的manpage中发现了这个问题,并修复了Vixie Cron的版本,以改变crontab -l的默认行为)。
crontab -l | crontab -
crontab -l
要在crontab -l添加注释的系统上以编程方式编辑crontab,可以尝试以下方法:
EDITOR=cat crontab -e > old_crontab; cat old_crontab new_job | crontab -
EDITOR=cat告诉crontab使用cat作为编辑器(不是通常的默认vi),这不会改变文件,而是将其复制到标准输出。如果crontab -期望输入的格式与crontab -e输出的格式不同,则仍然可能失败。不要尝试用crontab -e替换最终的crontab - -这将不起作用。
EDITOR=cat
crontab -
对你的问题更简单的回答是:
echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/root
您可以在远程服务器上设置cronjob,如下所示:
#!/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条目附加到相应的用户文件中。在上面的例子中,根用户的crontab文件被附加了一个cronjob,以便在每天凌晨1点运行/root/test.sh。
/var/spool/cron/
/root/test.sh
我已经用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> -
我知道这不是高拉夫想要的,但为什么不把所有的解都集中在一起呢?
(我没有足够的声誉来评论,所以我添加了at作为答案:请随意添加它作为评论在他的答案旁边)
乔·卡萨多特的俏皮话是完美的,除非你用set -e运行,也就是说,如果你的脚本设置为错误失败,并且还没有cronjob。在这种情况下,一行程序不会创建cronjob,但不会停止脚本。无声的失败很容易误导人。
set -e
原因是crontab -l返回一个1返回码,导致后续命令(echo)不被执行…因此cronjob不会被创建。但是由于它们是作为子进程执行的(因为括号),它们不会停止脚本。
1
echo
(有趣的是,如果你再次运行相同的命令,它将工作:一旦你执行了crontab -一次,crontab -l仍然没有输出任何东西,但它不再返回错误(你不再得到no crontab for <user>消息)。因此,随后的echo被执行,crontab被创建)
no crontab for <user>
在任何情况下,如果使用set -e运行,该行必须为:
(crontab -l 2>/dev/null || true; echo "*/5 * * * * /path/to/job -with args") | crontab -
它是一种增量添加cron作业的方法:
ssh USER_NAME@$PRODUCT_IP nohup "echo '*/2 * * * * ping -c2 PRODUCT_NAME.com >> /var/www/html/test.html' | crontab -u USER_NAME -"
另一个一次性向crontab添加多个脚本的解决方案:
cat <<EOF | crontab - * * * * * /bin/foo.sh * * * * * /bin/gaga.sh EOF
ssh $HOST "echo \"* * * * * echo hello >> /var/spool/cron/crontabs/root\"; sleep 2; crontab /var/spool/cron/crontabs/root"