shell crontab

调度任务可用
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

你可能感兴趣的:(crontab)