如何在没有交互式编辑器的情况下使用Bash自动创建cron作业?


395

crontab是否具有用于在不使用编辑器的情况下创建cron作业的参数(crontab -e)。如果是这样,那么从Bash脚本创建cronjob的代码是什么?



5
可悲的是,这里大多数最重要的答案只是显示了如何修改crontab-尽管以相当安全的方式进行-但我认为这总体上是错误的方法。更好,更安全,更简单的方法是将文件拖放到{{cron.d}}中,并且(目前)有很低的投票答案,说明了进一步查找时的解决方法。
gregmac

Answers:


539

您可以按如下所示将其添加到crontab中:

#write out current crontab
crontab -l > mycron
#echo new cron into cron file
echo "00 09 * * 1-5 echo hello" >> mycron
#install new cron file
crontab mycron
rm mycron

Cron行说明

* * * * * "command to be executed"
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

来源nixCraft


14
您应该使用tempfile或mktemp
PawełPolewicz,2009年

166
(crontab -l; echo“ 00 09 * * 1-5 echo hello”)| crontab-–
Edo

32
(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab --更容易复制Edo的answear
WBAR

8
我建议改变这种状况;&&对抗,如果情况安全守卫crontab -l失败。因此,例如:(crontab -l && echo "0 0 0 0 0 some entry") | crontab -
MacUsers 2016年

12
@MacUsers,crontab -l如果没有crontab则失败,因此使用&&使得脚本无法将第一个条目添加到crontab。
JPhi1618'4

312

您也许可以即时进行

crontab -l | { cat; echo "0 0 0 0 0 some entry"; } | crontab -

crontab -l列出当前的crontab作业,进行cat打印,echo打印新命令,crontab -并将所有打印的内容添加到crontab文件中。您可以通过执行新操作来查看效果crontab -l


3
谢谢,您能解释一下语法,还是指向一个解释它的网址?
网站

9
crontab -l列出当前的crontab作业,进行cat打印,echo打印新命令,crontab -并将所有打印的内容添加到crontab文件中。你可以做一个新的看到效果crontab -l

3
为我工作。如果用户没有现有的crontab,您将看到no crontab for <username>,但仍然可以使用。
2014年

21
在我的Amazon EC2实例上不起作用。相反,(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -可以工作。
斯特凡Bruckert

11
这看起来像是UUcatA的候选人。
ceving 2013年

86

这个较短的文件不需要临时文件,可以避免多次插入,并且可以更改现有条目的时间表。

说您有这些:

croncmd="/home/me/myfunction myargs > /home/me/myfunction.log 2>&1"
cronjob="0 */15 * * * $croncmd"

要将其添加到crontab中,不要重复:

( crontab -l | grep -v -F "$croncmd" ; echo "$cronjob" ) | crontab -

要将其从crontab中删除,无论其当前时间表如何:

( crontab -l | grep -v -F "$croncmd" ) | crontab -

笔记:

  • grep -F从字面上匹配字符串,因为我们不想将其解释为正则表达式
  • 我们也忽略了时间安排,只寻找命令。这条路; 可以更改时间表,而无需在crontab中添加新行

@moeseth:您能详细说明吗?
MoonCactus '16

您应该在计算机上尝试一下
moeseth

2
@moeseth:我显然是在我的计算机(Linux)上尝试过的。我不会建议随机的无效工作:/
MoonCactus

2
顺便说一下,到今天为止,有27个人是不会错的。因此,请说明为什么它不适用于您的设置,以便我们为您提供帮助。
MoonCactus'2

2
可能是OSX问题。
moeseth

40

谢谢大家的帮助。将在这里和其他地方找到的东西拼凑在一起,我想到了:

编码

command="php $INSTALL/indefero/scripts/gitcron.php"
job="0 0 * * 0 $command"
cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -

如果不重复自己,我想不通如何消除对这两个变量的需求。

command显然是我要调度的命令。job获取$command并添加计划数据。在完成工作的代码行中,我分别需要两个变量。

细节

  1. 归功于duckyflip,我使用了这个重定向小东西(<(*command*)crontab -lfgrep命令的输出转换为输入。
  2. fgrep然后过滤掉不匹配$command-v选项),不区分大小写(-i选项)的所有匹配项。
  3. 再次,使用小重定向thingy(<(*command*))将结果转换回cat命令的输入。
  4. cat命令也echo "$job"通过使用重定向事态((<(*command*))来)。
  5. 所以过滤后的输出crontab -lecho "$job",combined一起通过管道('|')传递crontab -到,最后被写入。
  6. 他们从此过着幸福的生活!

简而言之:

这行代码过滤掉与命令匹配的所有cron作业,然后用新的cron作业写出剩余的cron作业,实际上起到了“添加”或“更新”功能的作用。要使用此功能,您要做的就是交换commandjob变量的值。


5
为了使其他读者受益,此方法的优点是您可以多次运行它,而不必担心crontab中的重复条目(与所有其他解决方案不同)。那是因为fgrep -v
aleemb

5
如果您喜欢传统的从左到右的管道crontab -l | fgrep -i -v "$command" | { cat; echo "$job"; } | crontab -l
布置

1
@AntoineLizée,您回答的末尾有多余的“ l”,不应存在。
亨利

26

编辑(固定覆盖):

cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -

这将替换所有crontab内容
TheBonsai

1
@TheBonsai哦,我知道了,我现在修复了它,因此它应该将新命令
附加

3
请记住,Bash的进程替换会吞没错误。如果crontab -l失败但crontab -成功,则您的crontab将是单线的。
ceving 2013年

13

围绕crontab的使用有很多好的答案,但是没有提及更简单的方法,例如使用 cron

使用cron将利用系统文件和位于目录/etc/crontab/etc/cron.daily,weekly,hourly/etc/cron.d/

cat > /etc/cron.d/<job> << EOF
SHELL=/bin/bash 
PATH=/sbin:/bin:/usr/sbin:/usr/bin 
MAILTO=root HOME=/  
01 * * * * <user> <command>
EOF

在上面的示例中,我们在中创建了一个文件/etc/cron.d/,为成功执行该命令提供了环境变量,并user为该命令提供了command本身。该文件不应是可执行文件,并且名称只能包含字母数字和连字符(更多详细信息请参见下文)。

为了给出一个完整的答案,让我们看一下crontabvs 之间的区别cron/crond

crontab -- maintain tables for driving cron for individual users

对于那些想要在系统上的用户上下文中运行作业的人来说,使用crontab可能很有意义。

cron -- daemon to execute scheduled commands

对于那些使用配置管理或想要为其他用户管理作业的人,在这种情况下,我们应该使用 cron

手册页中的简短摘录为您提供了一些有关做什么和不做什么的示例:

/ etc / crontab和/etc/cron.d中的文件必须由root拥有,并且不能是组可写或其他可写的。与假脱机区域相比,/ etc / cron.d下的文件或/etc/cron.hourly、/etc/cron.daily、/etc/cron.weekly和/etc/cron.monthly下的文件也可能是符号链接,前提是符号链接及其指向的文件均由root拥有。/etc/cron.d下的文件不需要可执行,而/etc/cron.hourly、/etc/cron.daily、/etc/cron.weekly和/etc/cron.monthly下的文件都可以执行,就像它们由运行部件运行(有关更多信息,请参见run-parts(8))。

资料来源: http : //manpages.ubuntu.com/manpages/trusty/man8/cron.8.html

从系统角度看,以这种方式管理分支容易且可扩展性强,但这并不总是最好的解决方案。


1
值得一提的是,<job>不应包含文件扩展名。
jww

7

您可能会自动执行此操作,并且不希望将一个作业添加两次。在这种情况下,请使用:

__cron="1 2 3 4 5 /root/bin/backup.sh"
cat <(crontab -l) |grep -v "${__cron}" <(echo "${__cron}")

仅在使用BASH时有效。我不知道正确的DASH(sh)语法。

更新:如果用户还没有crontab,这将不起作用。一种更可靠的方法是:

(crontab -l ; echo "1 2 3 4 5 /root/bin/backup.sh") | sort - | uniq - | crontab - 

另外,如果您的发行版支持它,则还可以使用一个单独的文件:

echo "1 2 3 4 5 /root/bin/backup.sh" |sudo tee /etc/crond.d/backup

另一个SO问题中找到了那些。


也许使用sh代替bash?
kvz 2012年

仍在sh: 1: Syntax error: "(" unexpected使用sh
Batandwa 2015年

仅在使用BASH时有效。我不知道正确的DASH(sh)语法。也更新了答案
kvz

1
首先,如果<和之间有空格,我会使用bash收到此错误(。这意味着< (失败了,但<(行得通,除非您的日程安排中有星号...
doublesharp

我相信这是正确的方法:cat <(crontab -l |grep -v "${CRON}") <(echo "${CRON}") | crontab -
Stanislav

5

为了使用BASH脚本快速,轻松地创建/替换crontab,我使用了以下表示法:

crontab <<EOF
00 09 * * 1-5 echo hello
EOF

5

仅在找不到所需字符串的情况下才编辑crontab的变体:

CMD="/sbin/modprobe fcpci"
JOB="@reboot $CMD"
TMPC="mycron"
grep "$CMD" -q <(crontab -l) || (crontab -l>"$TMPC"; echo "$JOB">>"$TMPC"; crontab "$TMPC")

3

如果您使用的是Vixie Cron,例如在大多数Linux发行版中,您都可以将单个cronjob文件放到/etc/cron.d中。

当然,这仅适用于根。如果您的系统支持此功能,则应该在其中看到几个示例。(请注意该行中包含的用户名,语法与旧的/ etc / crontab相同)

在cron中,令人遗憾的是,无法以普通用户的身份来处理此问题,并且许多cron实现根本无法解决此问题。


2

因此,在Debian,Ubuntu和许多类似的基于Debian的发行版中...

有一个cron任务串联机制,该机制采用一个配置文件,将其捆绑在一起并将其添加到正在运行的cron服务中。

您可以将文件放在/etc/cron.d/somefilename下,其中somefilename是您想要的任何名称。

sudo echo "0,15,30,45 * * * * ntpdate -u time.nist.gov" >> /etc/cron.d/vmclocksync

让我们分解一下:

sudo-因为您需要提升的特权才能更改/ etc目录下的cron配置

echo-在std输出上创建输出的工具。printf,cat ...也可以

“-在字符串开头使用双引号表示您是专业人士

0,15,30,45 * * * *-标准cron运行时间表,此运行时间为每15分钟

ntpdate -u time.nist.gov-我要运行的实际命令

“-因为我的第一个双引号需要一个伙伴来关闭正在输出的行

>>-双重重定向附加而不是覆盖*

/etc/cron.d/vmclocksync-vmclocksync是我选择的文件名,位于/etc/cron.d/


*如果使用>重定向,则可以保证我们只有一个任务条目。但是,我们将有可能破坏现有文件中的任何其他规则。您可以自己决定是否适合使用>进行销毁,或者适合使用>>进行重复。另外,您也可以做一些令人费解的事情,包括检查文件名是否存在,文件名是否存在以及是否要添加任何重复项,但是我有事要做,但我不能这样做你现在。


2

Bash脚本,用于在不使用交互式编辑器的情况下添加cron作业。下面的代码有助于使用Linux文件添加cronjob。

#!/bin/bash

cron_path=/var/spool/cron/crontabs/root

#cron job to run every 10 min.
echo "*/10 * * * * command to be executed" >> $cron_path

#cron job to run every 1 hour.
echo "0 */1 * * * command to be executed" >> $cron_path

1
我知道这是一个漫长的时期,但这仍然是唯一的好答案,因为所有投票最多的人都删除了旧的克朗,而不仅仅是追加了新的克朗。
AFE

1
这个没有安装cron。它只是将其附加到文件中。您将必须以某种方式通知cron进程以安装新条目。
Apoorv Parijat

1

这是一个bash函数,用于crontab不重复地添加命令

function addtocrontab () {
  local frequency=$1
  local command=$2
  local job="$frequency $command"
  cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -
}
addtocrontab "0 0 1 * *" "echo hello"

1
CRON="1 2 3 4 5 /root/bin/backup.sh" 
cat < (crontab -l) |grep -v "${CRON}" < (echo "${CRON}")

将-w参数添加到grep精确命令中,而无需-w参数添加cronjob“ testing”会导致cron作业“ testing123”的删除

脚本函数来添加/删除cronjobs。没有重复条目:

cronjob_editor () {         
# usage: cronjob_editor '<interval>' '<command>' <add|remove>

if [[ -z "$1" ]] ;then printf " no interval specified\n" ;fi
if [[ -z "$2" ]] ;then printf " no command specified\n" ;fi
if [[ -z "$3" ]] ;then printf " no action specified\n" ;fi

if [[ "$3" == add ]] ;then
    # add cronjob, no duplication:
    ( crontab -l | grep -v -F -w "$2" ; echo "$1 $2" ) | crontab -
elif [[ "$3" == remove ]] ;then
    # remove cronjob:
    ( crontab -l | grep -v -F -w "$2" ) | crontab -
fi 
} 
cronjob_editor "$1" "$2" "$3"

经过测试:

$ ./cronjob_editor.sh '*/10 * * * *' 'echo "this is a test" > export_file' add
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file

如果您在crontab中有两次相同的命令(在不同的时间运行),则remove会删除这两行。
Michaelkay

1

我对此的首选解决方案是:

(crontab -l | grep . ; echo -e "0 4 * * * myscript\n") | crontab -

这将确保您正确处理了底部的空白新行。为避免crontab出现问题,通常应在crontab文件末尾添加空白行。并且上面的脚本确保它首先使用“ grep”删除所有空白行。部分,然后在脚本末尾添加一个新的空白行,并在其末尾添加“ \ n”。如果现有的crontab文件以空行结尾,这还将防止在新命令上方出现空行。


1
echo "0 * * * * docker system prune --force >/dev/null 2>&1" | sudo tee /etc/cron.daily/dockerprune

0

否,crontab中没有选项可以修改cron文件。

您必须:获取当前的cron文件(crontab -l> newfile),对其进行更改,然后将新文件放置到位(crontab newfile)。

如果您熟悉perl,则可以使用此模块Config :: Crontab

LLP,安德里亚


0

脚本函数添加cronjobs。检查重复的条目,可用的表达式*>“

cronjob_creator () {         
# usage: cronjob_creator '<interval>' '<command>'

  if [[ -z $1 ]] ;then
    printf " no interval specified\n"
elif [[ -z $2 ]] ;then
    printf " no command specified\n"
else
    CRONIN="/tmp/cti_tmp"
    crontab -l | grep -vw "$1 $2" > "$CRONIN"
    echo "$1 $2" >> $CRONIN
    crontab "$CRONIN"
    rm $CRONIN
fi
}

经过测试:

$ ./cronjob_creator.sh '*/10 * * * *' 'echo "this is a test" > export_file'
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file

资料来源:我的大脑;)


-5

您可能可以将默认编辑器更改为ed,并使用heredoc进行编辑。

EDITOR=ed
export EDITOR

crontab -e << EOF
> a
> * * * * * Myscript
> * * * * * AnotherScript
> * * * * * MoreScript
> .
> w
> q
> EOF

注意前导>,该代码中表示按下回车/输入键以创建新行。

一个手段APPEND所以它不会覆盖任何东西。

表示您已完成编辑。

w ^表示写的变化。

q装置QUIT或退出编辑。

你可以看看

crontab -l

您也可以删除条目。

EDITOR=ed
export EDITOR

crontab -e << EOF
> /Myscript/
> d
> .
> w
> q
> EOF

这将删除其中包含Myscript的crontab条目。

所述d装置删除内的图案 / /

不再检查

crontab -l

这种解决方案在脚本内部的作用少了,当然> :)

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.