crontab 可以用 vixie-cron-4.1.tar.bz2 http://download.chinaunix.net/download.php?id=22023&ResourceID=11114 来修改
java quartz web 来做
shell 版本的
#/bin/bash # # @function shell crontab # @author liuniuyou # @version 0.1 # @date 2014-12-30 # #CREATE TABLE `task` ( #`task_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务名称' , #`description` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '任务描述' , #`bin` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '执行程序' , #`script` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '执行脚本' , #`args` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '脚本参数 多个参数加:间隔' , #`cycle` enum('6','5','4','3','2','1') CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '执行周期 1周 2分 3小时 4 天 5 月 6年 ' , #`start_day` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '数据库 默认值为0 表示 日期为空不设置' , #`start_time` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '开始执行时间 因为开始 时间 有些为天 有些 为时 不统一用字符' , #`times` int(11) NOT NULL COMMENT '次数' , #`intervall` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '间隔时间' , #`pid` int(11) NULL DEFAULT NULL COMMENT '执行程序的pid 如果多个加:间隔' , #`count` int(11) NULL DEFAULT 0 COMMENT '本cycle 执行周期内 已经运行的次数。运行完清零' , #`exec_time` int(11) NULL DEFAULT 0 , #PRIMARY KEY (`task_name`) #) #ENGINE=MyISAM #DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci #CHECKSUM=0 #ROW_FORMAT=DYNAMIC #DELAY_KEY_WRITE=0 #; . /taskcron/common/common exportEnv TABLE="yt_task" RUNBYYEAR=6 RUNBYMONTH=5 RUNBYDAY=4 RUNBYHOUR=3 RUNBYMINUT=2 RUNBYWEEK=1 MUSTRUN=1 GIVEUPRUN=0 EXISTPID=1 NOEXISTPID=0 scriptPid=$$ #$1 cycle #$2 starttime getLastCycleDetail() { starttime=$2 cycleTime=$1 nowTimestamp=`date +%s` dayTimestamp=$[$nowTimestamp-$cycleTime] lastCycleTime=`echo $dayTimestamp|awk '{print strftime("%Y:%m:%d:%T",$0)}'` lDayY=`echo $lastCycleTime|awk -F":" '{print $1}'` lDayM=`echo $lastCycleTime|awk -F":" '{print $2}'` lDayD=`echo $lastCycleTime|awk -F":" '{print $3}'` lDayH=`echo $lastCycleTime|awk -F":" '{print $4}'` lDayF=`echo $lastCycleTime|awk -F":" '{print $5}'` lDayS=`echo $lastCycleTime|awk -F":" '{print $6}'` case $cycle in "$RUNBYYEAR") lastStartTimestamp=`date -d "${lDayY}-$starttime" +%s` ;; "$RUNBYMONTH") lastStartTimestamp=`date -d "${lDayY}-${lDayM}-$starttime" +%s` ;; "$RUNBYDAY") startTime=`echo $2|awk -F" " '{print $2}'` lastStartTimestamp=`date -d "${lDayY}-${lDayM}-${lDayD} $startTime" +%s` ;; "$RUNBYHOUR") lastStartTimestamp=`date -d "${lDayY}-${lDayM}-${lDayD} ${lDayH}:$starttime" +%s` ;; "$RUNBYMINUT") lastStartTimestamp=`date -d "${lDayY}-${lDayM}-${lDayD} ${lDayH}:${lDayF}:$starttime" +%s` ;; "$RUNBYWEEK") weekDay=`echo $starttime|awk -F" " '{print $1}'` startTime=`echo $starttime|awk -F" " '{print $2}'` lastStartTimestamp=`date -d "${lDayY}-${lDayM}-${lDayD} $startTime" +%s` ;; *) ;; esac } getNowDetail() { now=`date +"%Y:%m:%d:%H:%M:%S"` nowTimestamp=`date +%s` nowY=`echo $now|awk -F":" '{print $1}'` nowM=`echo $now|awk -F":" '{print $2}'` nowD=`echo $now|awk -F":" '{print $3}'` nowH=`echo $now|awk -F":" '{print $4}'` nowF=`echo $now|awk -F":" '{print $5}'` nowS=`echo $now|awk -F":" '{print $6}'` nowW=`date +%w` } # $1 cycle # $2 Startime # $3 intervall 间隔时间 # $4 times 要运行的次数 # $5 count 已经运行的次数 # $6 lastExecStamp isToExeTime() { getNowDetail case $1 in "$RUNBYYEAR") startTimestamp=`date -d "${nowY}-$2" +%s` #isExecByYear "$2" "$3" "$4" "$5" ;; "$RUNBYMONTH") startTimestamp=`date -d "${nowY}-${nowM}-$2" +%s` ;; "$RUNBYDAY") startTime=`echo $2|awk -F" " '{print $2}'` startTimestamp=`date -d "${nowY}-${nowM}-${nowD} $startTime" +%s` ;; "$RUNBYHOUR") startTimestamp=`date -d "${nowY}-${nowM}-${nowD} ${nowH}:$2" +%s` ;; "$RUNBYMINUT") startTimestamp=`date -d "${nowY}-${nowM}-${nowD} ${nowH}:${nowF}:$2" +%s` ;; "$RUNBYWEEK") weekDay=`echo $2|awk -F" " '{print $1}'` startTime=`echo $2|awk -F" " '{print $2}'` # 按周的不等于就放弃 如周二运行 必须周二运行 if [ ${weekDay} -ne ${nowW} ];then return $GIVEUPRUN fi startTimestamp=`date -d "${nowY}-${nowM}-${nowD} $startTime" +%s` ;; *) ;; esac # 此处不存在 times 与 count 相等的处理,此逻辑在updateTaskCount函数中处理。 $lastExecStamp都为 前次处理的时间戳了 所以只要加一次间隔时间就可以了。 # ${count}为0 次运行 不需要加间隔时间。只需要判断startTimestamp 时间 count=$5 lastExecStamp=$6 runTimestamp=$[$lastExecStamp+$3] writeLog "count ${count} nowTimestamp ${nowTimestamp} runTimestamp ${runTimestamp} startTimestamp ${startTimestamp} " if [ ${nowTimestamp} -lt ${startTimestamp} ];then return $GIVEUPRUN else if [ $count -eq 0 ];then if [ $lastExecStamp -lt $startTimestamp ];then return $MUSTRUN else return $GIVEUPRUN fi fi fi if [ ${nowTimestamp} -lt ${runTimestamp} ];then return $GIVEUPRUN else return $MUSTRUN fi } # $1 cycle # $2 taskName # $3 starttime # $4 allIntervall updateTaskCount(){ nowStamp=`date +%s` cycle=$1 starttime=$3 taskIntvall=$4 cycleDiff=0 case $cycle in "$RUNBYYEAR") cycleDiff=$[365*24*3600] ;; "$RUNBYMONTH") cycleDiff=$[31*24*3600] ;; "$RUNBYDAY") cycleDiff=$[24*3600] ;; "$RUNBYHOUR") cycleDiff=3600 ;; "$RUNBYMINUT") cycleDiff=60 ;; "$RUNBYWEEK") cycleDiff=$[7*24*3600] ;; *) ;; esac getLastCycleDetail "$cycleDiff" "$starttime" diff=$[$nowStamp-$lastStartTimestamp] writeLog "updateCount:lastStartTimestamp $lastStartTimestamp starttime $3 allIntervall $4 nowStamp ${nowStamp} diff-${diff} cycleDiff ${cycleDiff} " if [ ${diff} -gt ${cycleDiff} ];then writeLog "任务 $2 开始新的周期,更新计数器" updateCount=`mysql -u$USER -p$PASSWORD $DATABASE</dev/null else writeLog "任务 $2 本周期内所有任务已经完成,还未到新周期的开始,等待中..... " fi } #$1 数字 # 是数字 返回 1 checkInt(){ if echo $1 | egrep -q '^[0-9]+$'; then echo 1 else echo 0 fi } #$1 taskname #$2 CMD 运行的命令脚本 #$3 count 已经运行的次数 #$4 times 计划运行次数 #$5 Pid execCmd() { writeLog " 任务 $1 的 pid: $5 count $3 times $4 taskName $1 CMD $2 " pidIsNUll=`checkInt "$5"` writeLog "pidIsNUll $pidIsNUll" if [ $pidIsNUll -gt 0 ];then isRun=`exsitPid $5` else isRun=$NOEXISTPID fi writeLog "ps -a | grep "$5" | wc -l " writeLog "isRun :$isRun " if [ "$isRun" = "$EXISTPID" ];then writeLog "任务 $1 已经有进程在运行 " else writeLog "CMD: $2" CMD="$2" eval "$CMD" >> /dev/null & pid=$! execTime=`date +%s` #`date +"%Y-%m-%d:%H:%M:%S"` writeLog "execCmd count:$count" #更行pid 和 count count=$3 if [ ${times} -gt ${count} ];then count=$[${count}+1] fi writeLog "execCmd2 count:$count" writeLog "CMD $2 UPDATE $TABLE SET count='${count}',pid=$pid,exec_time='$execTime' WHERE task_name='$1'; " updateCount=`mysql -u$USER -p$PASSWORD $DATABASE< /dev/null writeLog "update pid exec_time: $updateCount" writeLog "任务 $1 命令 $2 本周期已经运行 $3, 现在开始运行第$count次 ..... " fi } exsitPid() { echo `ps -a | grep "$1" | wc -l` } writeLog "taskcron 主进程pid ${selfPid}" ##初始化时间点 2015-01-01 00:00:00 即时间戳1420041600 `mysql -u$USER -p$PASSWORD $DATABASE< /dev/null i=1 taskLines=${records} for field in ${taskLines[@]} do if [ "$field" = "||" ];then #如果本周期的运行次数已经完成 退出循环 if [ ${times} -eq ${count} ];then #当前时间为周期时间的结尾 则更新计数器 allInteravall=$[${times}*${intervall}] updateTaskCount "$cycle" "$taskName" "$startTime" "$allInteravall" i=1 CMD="" writeLog "*****************任务 单次 $taskName end*********************" continue writeLog "continue ...." fi if [ "${startDay}" != "0" ];then startTime=$startDay" "$startTime fi isToExeTime "$cycle" "$startTime" "$intervall" "$times" "$count" "$lastExecTime" runFlag=$? if [ ${runFlag} -eq ${MUSTRUN} ];then execCmd "$taskName" "$CMD" "$count" "$times" "$pid" else writeLog "间隔时间为 $intervall, 本次运行时间还没有到!等待中..... " fi i=1 CMD="" writeLog "*****************任务单次 $taskName end*********************" else case $i in "1") taskName="$field" writeLog "*****************任务单次 $taskName start*********************" ;; "2") CMD="$field" ;; "3") CMD="$CMD $field" ;; "4") args=`echo "$field"|sed -r "s/:/ /g"` CMD="$CMD $args" ;; "5") cycle=$field ;; "6") startDay="$field" ;; "7") startTime="$field" ;; "8") times="$field" ;; "9") intervall="$field" ;; "10") pid="$field" ;; "11") count="$field" ;; "12") lastExecTime="$field" ;; *) ;; esac let "i=$i+1" fi done sleep 1s done