调度任务可用
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<<EOF
UPDATE $TABLE SET count=0,exec_time='$nowStamp' WHERE task_name='$2';
exit
EOF`>/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<<EOF
UPDATE $TABLE SET count='$count',pid=$pid,exec_time='$execTime' WHERE task_name='$1';
exit
EOF`>/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<<EOF
UPDATE $TABLE SET exec_time='1420041600',count=0
EOF`
while :
do
script=`basename $0`
day=`date +"%Y%m%d%H"`
LogFile="/taskcron/log/"${day}"_"${script}".log"
if [ ! -d "/taskcron/log/" ]
then
mkdir /taskcron/log/
chmod -R 777 /taskcron/log/
fi
declare -a records
records=`mysql -u$USER -p$PASSWORD $DATABASE<<EOF | tail -n +2
SELECT task_name,bin,script,IFNULL(args,0),cycle,IFNULL(start_day,0),IFNULL(start_time,0),times,intervall,IFNULL(pid,0),IFNULL(count,0),IFNULL(exec_time,0),'||' as split FROM $TABLE;
exit
EOF`>/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