crontab mysqldump 定时任务 备份 及 创建文件 大小 为 0 解决方案+分析

今天现网Mysql数据库要求开始做备份,于是决定把mysqldump命令写到脚本里,然后做到crontab里让它每天定时执行。
系统:RHEL6.5,Mysql5.5

路径:/tmp/tmp
mysqldump写到test.sh,:wq保存后,赋予执行权限:

mysqldump -A -uroot -pyourpassword > /tmp/tmp/mysqlallbak.sql
chmod a+x test.sh

接下来手工执行一下

./test.sh
[root@neoska tmp]# ll
total 648
-rw-r--r-- 1 root root   662849 Nov 29 10:20 mysqlallbak.sql

有sql文件生成,文件大小不为0,一切正常,美滋滋。

接下来删掉那个sql文件,做定时任务,把脚本加入定时执行,设10点22

crontab -e
22 10 * * * /tmp/tmp/test.sh

时间一到,马上到tmp下查看

[root@neoska tmp]# ll
total 0
-rw-r--r-- 1 root root 0 Nov 29 10:22 mysqlallbak.sql

文件确实有,可大小为0,打开看就是个空文件。

检查步骤:

1.打开脚本仔细检查,看是不是语句里忘写mysql登陆密码。
2.脚本检查无误,crontab -e仔细检查定时任务是否有误。
3.crontab检查无误,开始怀疑crontab本身有问题。百度了一下,大多数解决方案是,mysqldump命令写成绝对路径即可。
于是

[root@neoska tmp]# find / -name mysqldump
/usr/local/mysql/bin/mysqldump

打开脚本,把mysqldump换成/usr/local/mysql/bin/mysqldump,重新crontab测试,果然奏效了。
4.用绝对路径写了脚本,测了几次,没问题。但手工执行成功,定时任务挂掉,百思不得其解,遂继续百度之。
原来crontab运行时,使用自己的环境变量,相当于独立的环境。
其自动运行的环境配置写在/etc/crontab。
于是打开看看

[root@neoska tmp]# vim /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed

!有个PATH长的好像系统环境变量PATH!
这个path里,没有步骤3中mysqldump的路径,因此肯定是crontab的环境找不到mysqldump指令,自然也不能执行成功。
原因弄明白了,问题就好解决了。

  • 方案1
    采用软链接方式,将mysqldump软链接到crontab配置文件中PATH后面的任意一个下,如/usr/bin:
 ln -s /usr/local/mysql/bin/mysqldump /usr/bin/mysqldump

回去编辑脚本,把mysqldump的绝对路径删掉,保存重新crontab测试,成功。

  • 方案2
    修改/etc/crontab的内容,在PATH最后面加上:/Your_project_path(注意冒号别掉了)(此处就是mysqldump的存放路径/usr/local/mysql/bin/)保存退出。
    没有软链接的情况下,测试成功。

总结

crontab运行采用独立环境,PATH变量可在/etc/crontab文件中编辑。不只是mysql或mysqldump,所有自定义的命令,都可采用这两种方法,让crontab能够找到该指令,这样就不会出现crontab定时脚本不能执行的现象。
另外,一些需要更改环境变量才能执行的项目,可以在脚本开头写上source /etc/profile或者JAVA_HOME=XXXXX/export XXXXX(使用指定jdk等),来指定该脚本需要的环境变量。

参考资料

Linux中crontab的坑爹环境变量问题
http://blog.csdn.net/dancen/article/details/24355287
corantab 不能自动执行的一些问题-环境变量
http://xiachaofeng.iteye.com/blog/1405184
mysqldump参数之-A -B
http://blog.csdn.net/u010587433/article/details/47417051

附录

完整脚本

#创建一个以当天日期为名的文件夹如171129
mkdir -p /home/neoska/backup/data/`date +%Y%m%d`

#写备份文件,-A为备份所有库。其他常用选项:-B database1 database2 ...为指定的多个库,-d为只导出表结构,-h10.11.12.13为备份IP为10.11.12.13的远程数据库。
mysqldump -A -uroot -ppasswd > /home/neoska/backup/data/`date +%Y%m%d`/mysqldumpall.sql

#删掉3天前的备份数据,可自定义周期,若数据太大则应设小点以免磁盘写满。
rm -rf /home/neoska/backup/data/`date +%Y%m%d -d "-3days"`

Linux系统 Crontab命令 安装配置使用详细说明

Crontab命令常见于Unix和Linux的操作系统之中,用于设置周期性被执行的指令。该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行。通常,crontab储存的指令被守护进程激活。crond 常常在后台运行,每一分钟检查是否有预定的作业需要执行。这类作业一般称为cron jobs。
未分类

一、安装

yum -y install vixie-cron
yum -y install crontabs

说明:
vixie-cron 软件包是 cron 的主程序;
crontabs 软件包是用来安装、卸装、或列举用来驱动 cron 守护进程的表格的程序。

二、配置

cron 是 linux 的内置服务,但它不自动起来,可以用以下的方法启动、关闭这个服务:

service crond start //启动服务
service crond stop //关闭服务
service crond restart //重启服务
service crond reload //重新载入配置
service crond status //查看crontab服务状态

在CentOS系统中加入开机自动启动:

chkconfig –level 345 crond on

列子:

01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly

三、Crontab文件的格式:

minute:分,值为0-59
hour:小时,值为1-23
day:天,值为1-31
month:月,值为1-12
weekday:星期,值为0-6(0代表星期天,1代表星期一,以此类推)
username:要执行程序的用户,一般设置为root
command:要执行的程序路径(设置为绝对路径)例如:/home/cunlz.org/cunlz.sh

root身份登录到命令行

输入crontab -e

按下a键进入到编辑模式

输入 执行代码,例如:

0 3 */7 * * /bin/certbot renew –renew-hook “/etc/init.d/nginx reload”

同时按下ctrl+c退出编辑模式

按下shift+: 输入wq 退出 crontab

附:crontab规则详细实例

1、每天6:00执行

0 6 * * * root /home/cunlz.org/cunlz.sh

2、每周六凌晨4:00执行

0 4 * * 6 root /home/cunlz.org/cunlz.sh

3、每周六凌晨4:25执行

25 4 * * 6 root /home/cunlz.org/cunlz.sh

4、每周一到周五的11:41开始,每隔10分钟执行一次

41,51 11 * * 1-5   root /home/cunlz.org/cunlz.sh
1-59/10 12-23 * * 1-5   root /cunlz.org/cunlz.sh

5、在每天的10:31开始,每隔2小时重复一次

31 10-23/2 * * * root   /cunlz.org/cunlz.sh

6、每天15:00执行

0 15 * * *  root /home/cunlz.org/cunlz.sh

crontab 任务误删恢复

这是一篇简短的记录。

某台服务器某账号的 crontab 任务被清空,原因不明。同时,该服务器上的 crontab 任务备份未开启。故思考如何恢复 crontab 任务。

经查,CentOS 系统的 crontab 任务的日志,打印在 /var/log/cron 之中。考虑过滤日志:

cat /var/log/cron* | grep CMD | awk -F'CMD' '{print $2}' | awk -F'[(|)]' '{print $2}' | sort -u

由此得到系统记录过的 crontab 执行命令,过滤其他账号的命令后即可追回目标账号的 crontab 任务。

此外,考虑备份 crontab;脚本如下:

backup_crontab.sh

#!/usr/bin/env bash

BACKUP_DIRECTORY="${HOME}/crontab_backup"

if [ ! -e "${BACKUP_DIRECTORY}" ]; then
        mkdir -p ${BACKUP_DIRECTORY}
fi

crontab -l > ${BACKUP_DIRECTORY}/$(date '+%Y%m%d').txt

php+crontab+shell方案实现的秒级定时发起异步请求回调方案

方案介绍

该方案出来的场景:一天有一个业务需求,需要把我方的一些信息或订单状态等异步发起请求同步给第三方,这里就会出现定时时间和延迟时间消息的处理,考虑过很多消息队列方案(如:rabbitmq、云消息服务等)。

不过最后公司定了因为该业务流量很小,不用做那么麻烦。所以就直接出了这个方案

该方案在50条消息/s,应该压力不大,量大了就会出现一个消息延迟问题,如果不注重这个业务时间准确性,该方案承载的秒级处理在1000内应该问题也不大

方案架构图

未分类

mysql的任务队列表

CREATE TABLE `open_queue` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `type` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '任务类型,可用于后续读取不同任务失败次数区分',
  `order_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '业务绑定的订单id等,根据自己自行设计业务id',
  `event_identity` varchar(30) NOT NULL DEFAULT '' COMMENT '事件表示分类,可不用,同type',
  `data` text NOT NULL COMMENT '需要处理的数据,json格式化',
  `try` tinyint(4) unsigned NOT NULL DEFAULT '1' COMMENT '特定任务需要当时就处理的次数,而不是发起回调请求的任务',
  `again` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '0不是重试记录 1重试记录,失败后发起任务未1,否者未0',
  `status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '是否被执行 1是 0否',
  `create_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '任务创建的时间戳',
  `at_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '任务时间的时间戳',
  `task_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '执行结果 -1重复消息系统主动取消 0未执行 1执行成功 2执行失败',
  `task_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '执行时间',
  PRIMARY KEY (`id`),
  KEY `IDX_EVENT` (`event_identity`),
  KEY `IDX_AT_TIME` (`at_time`) USING BTREE,
  KEY `IDX_ORDER` (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

方案实现源码

下方代码都是伪代码,大家自行根据思路自己设计业务

redis同步到mysql

该步骤可以省略,因为我方当时redis是单机部署,也没做持久化,

$redisTypeLock; //lock类型
if (!IS_WIN) {
    $file = fopen($path . "/lock/{$redisTypeLock}.lock","w+");
    if (!flock($file, LOCK_EX | LOCK_NB)) {
        flock($file,LOCK_UN);
        fclose($file);
        exit;
    }
}

//成功获得锁 开始业务执行

$count = get_redis_lLen('msgevent:' . $redisType);
if (!$count) {
    //无需要入数据库订单队列,直接返回
    return false;
}

$successCount = 0;
for ($i = 0; $i < $loopLen; $i++) {
    $data = get_redis_lPop('msgevent:' . $redisType);
    //把redis数据格式化存入到数据库持久化
    $result = $this->saveToMysql($data);
    if (!$result) {
        //如果执行失败,重新推入redis队列
        get_redis_lPush('msgevent:' . $redisType, $data);
    }

    $successCount++;
}

if (!IS_WIN) {
    flock($file, LOCK_UN);
    fclose($file);
}

定时执行任务的的入口

这个入口是定时秒级处理脚本和处理小于当前时间的脚本调用的入口

public function task_run()
{
    $timeType = $_GET['tt'] ? : 'now';
    //获取当前秒需要处理的所有消息, 依次路由后执行
    //如果你redis无需存入mysql,你可以redis的list结构实现, 一次全部取出数据集合,并删除list
    //如果接下去业务里发现发起请求失败了,重新把任务分配给redis建立恢复list,list名为t+需要什么时间执行的时间戳
    $lists = $this->getTaskLists($timeType);
    foreach ($lists as $item) {
        $this->task('event:' . $item['event_type']);
        //$this->task('event:demo1');
        //$this->task('event:demo2');
        //$this->task('event:demo3');
    }
}

实际处理业务(发起通知请求)

# 模拟一个发起的请求事件demo
private function pushDemo1Event($info)
{
    $sendInfoData = $this->getSendInfoFromInfo($info);

    //发起请求,这里做的真正的发起给对方的请求,你可以根据$sendInfo拼接各种事件或消息分类给对方
    $isSuccess = $this->sendInfo($sendInfoData);

    $data = array(
        'status'        => 1,
        'task_status'   => $isSuccess ? 1 : 2,
        'task_time'     => NOW_TIME
    );

    $db->save($data);

    //如果执行失败,重新插入一条记录,并把at_time生成下次执行的时间戳,这样定时器根据at_time字段可以取出判断执行到当时的秒级
    if (!$isSuccess) {

        $tryCount = $db->where(...)->count();

        if ($tryCount >= 5) {
            return false;
        }

        $this->newTask($info, $tryCount, 30);
    }
}

private function newTask($info, $tryCount, $timeout = 30)
{
    $newTime = $this->nextTaskTime($info, $timeout);
    $data = array(
        ...
        'at_time' => newTime //执行的时间(时间戳)
    );
    $db->add($data);
}

定时消费方

$timeType = $_GET['time_type'] ? : 'now';
$lists = $this->getMsgAll($timeType);
if (!$lists) {
    return false;
}

foreach ($lists as $item) {
    if ($item['type'] == '1') {
        //根据业务生成我方真实订单
        call_user_func_array(array($this, "add_real_order"), array($item));
    }
    if (in_array($item['type'], array(2,3))) {
        $this->push('push:toengineer', $item);  //指派或取消工程师
    }
    if ($item['type'] == '5') {
        $this->push('push:edit', $item);  //编辑
    }
    if ($item['type'] == '6') {
        $this->push('push:cancel', $item);  //取消
    }
    if ($item['type'] == '7' || $item['type'] == '8' || $item['type'] == '9') {
        $this->push('push:status', $item);  //简单订单状态
    }
}

借助crontab+shell外力实现秒级执行

因为crontab是最小单位是分钟,所以需要借助shell脚本来实现秒级执行

读取redis任务队列到mysql存储

#!/bin/bash
cd /web/project/src
for (( i = 1; i < 60; i = i + 1 ))
do
    #执行php直接返回,不会阻塞 不要忘记最后面的 &
    $(/usr/bin/php index.php redis2mysql > /dev/null 2>&1 &)
    sleep 1
done

exit 0

处理秒级时间sh脚本

#!/bin/bash
cd /web/project/src
for (( i = 1; i < 60; i = i + 1 ))
do
    $(/usr/bin/php index.php task_run > /dev/null 2>&1 &)
    sleep 1
done

exit 0

处理秒级小于当前时间sh脚本

#!/bin/bash
cd /web/project/src
for (( i = 1; i < 60; i = i + 1 ))
do
    $(/usr/bin/php index.php task_run/tt/lt > /dev/null 2>&1 &)
    sleep 1
done

exit 0

linux下的crontab

* * * * * sh /web/project/src/shell/repair_build_order.sh
* * * * * sh /web/project/src/shell/repair_sync_second.sh
* * * * * sh /web/project/src/shell/repair_sync_lt_time.sh

php模拟linux crontab实现定时计划任务的方法

本文分享一下php模拟linux crontab实现定时计划任务的方法。

PHP定时计划任务需要两个文件。

1、crontab.conf.php (配置文件)

<?php
//当为0时,关闭计划任务
return 1;

2、crontab.php (主体文件)

<?php
ignore_user_abort();//关掉浏览器,PHP脚本也可以继续执行.
set_time_limit(0);// 通过set_time_limit(0)可以让程序无限制的执行下去

$interval = 60 * 3;// 每隔3分钟运行
$i = 0;

do {
    $nowTime = date("Y-m-d H:m:s");
    $run = include 'crontab.conf.php';

    if (!$run) {
        file_put_contents("crontab_task.log", "==计划任务已结束 $nowTime==rn", FILE_APPEND);
        die('Job has ended.');
    }

    //此处放要执行的代码
    sleep($interval);// 等待3分钟
    $data = "$i>计划任务正在运行中...(运行状态:$run)  $nowTimern";
    file_put_contents("tasktest.txt", $data, FILE_APPEND);
    $i++;
} while (true);

主要改变 crontab.conf.php 中 return 0 即可实现控制这个计划任务的关闭。

注意:当php服务关掉之后该计划任务脚本也会停掉并且不会自动重启。

解决Linux中crontab不执行ntpdate问题

解决Linux中crontab尚未执行ntpdate问题

未分类

[root@localhost ~]# crontab -l
*/1 * * * * ntpdate time.nist.gov

我是每分钟同步时间,上面看上去是没什么问题,但是你能很容易的发现命令行经常弹出You have new mail in /var/spool/mail/root 类似于这种提示。

当你打开这个文件会有如下提示:/bin/sh: ntpdate: command not found

上面的意思是:在/bin/sh 下找不到ntpdate命令

解决办法:

使用whereis命令查找ntpdate命令

[root@localhost ~]# whereis ntpdate
ntpdate: /usr/sbin/ntpdate /usr/share/man/man8/ntpdate.8.gz

然后重新更改crontab定时任务

[root@localhost ~]# crontab -l
*/1 * * * * /usr/sbin/ntpdate time.nist.gov

保存后即可解决。

crontab定时监控tomcat进程 停止时自动启动

一、创建monitor.sh文件

[root@izjjh7u0ge4d6yz tomcat]# vi monitor.sh

编辑内容为:

#!/bin/sh  
#获取tomcat进程ID  
TomcatID=$(ps -ef | grep tomcat | grep -w 'tomcat'|grep -v 'grep'|awk '{print $2}')  
#Tomcat启动程序(根据自己路径编写)  
StartTomcat=/usr/local/tomcat/bin/startup.sh  
TomcatCache=/usr/local/tomcat/work  
#定义要监控的页面地址(写比较简单页面即可)  
WebUrl=https://hao.360.cn/?wd_xp1  
#日志输出  
TomcatMonitorLog=/tmp/TomcatMonitor.log  
Monitor(){  
   echo "[info]开始监控tomcat...[$(date +'%F %H:%M:%S')]"  
   #判断Tomcat进程是否存在  
   if [[ $TomcatID ]];then  
   echo "[info]当前tomcat进程ID为:$TomcatID,继续检测......"  
   #检测是否启动成功(成功的话页面会返回状态"200")  
   TomcatServiceCode=$(curl -I -m 10 -o /dev/null -s -w %{http_code} $WebUrl)  
   if [ $TomcatServiceCode -eq 200 ];then  
     echo "[info]返回码为$TomcatServiceCode,tomcat启动成功,测试正常......"  
  else  
     echo "[error]tomcat出错,请注意......状态码为$TomcatServiceCode,错误日志已输出到$TomcatMonitorLog[error],开始重启tomcat"  
   #杀掉原tomcat进程  
   kill -9 $TomcatID    
  sleep 3  
   #清理tomcat缓存  
  rm -rf $TomcatCache    
  $StartTomcat  
  fi  
 else  
   echo "[error]tomcat进程不存在!tomcat开始自动重启......[info]$StartTomcat,请稍候......"  
  rm -rf $TomcatCache  
  $StartTomcat  
  fi  
 echo "编写完成"  
 }  
 Monitor>>$TomcatMonitorLog  

二、保存退出后,给脚本执行权限

指令:chmod a+xmonitor.sh

三、启动脚本,使用crontab执行定时任务

[root@izjjh7u0ge4d6yztomcat]# ./monitor.sh

看monitor.sh文件是否已经监控,如下图所示:

未分类

使用crontab需要先启动crontab,然后使用vi添加定时执行任务。

[root@izjjh7u0ge4d6yz tomcat]# /sbin/service crond start
[root@izjjh7u0ge4d6yztomcat]# vi /etc/crontab

添加内容为:

*/1 * * * * /usr/local/tomcat/monitor.sh

保存并退出,可以用crontab -l指令来查看当前的定时任务。

定时执行任务Crontab的20个例子

简介

Linux crontab和Windows task schedules非常的相似。Crontab可以用来在系统中定期的执行任务。比如:写了一个爬虫需要每天早上八点执行,就可以用到Crontab;安装的Tomcat服务器需要每天凌晨重启一次,也可以使用到Crontab。总之,几乎所有的定时任务,我们都可以通过Crontab这个工具来完成。

Crontab在Linux上的结构

未分类

从左到右依次为:

[分钟] [小时] [每月的某一天] [每年的某一月] [每周的某一天] [执行的命令]

注意:请留意每个选项的取值范围。

如何 添加/编辑 Crontab

  • 添加或更新crontab中的命令
crontab -e

默认情况下,系统会编辑当前登录用户的crontab命令集合。需要编辑其他用户的命令集合,需要使用到如下的命令

crontab -u username -e

查看Crontab命令集合

  • 查看当前系统登录用户的Crontab命令集合
crontab -l
  • 查看其他用户的Crontab命令集合
crontab -u username -l

20个超实用的Crontab使用实例

  • 每天 02:00 执行任务
0 2 * * * /bin/sh backup.sh
  • 每天 5:00和17:00执行任务
0 5,17 * * * /scripts/script.sh
  • 每分钟执行一次任务

通常情况下,我们并没有每分钟都需要执行的脚本(默默的想到了12306–)

* * * * *  /scripts/script.sh
  • 每周日 17:00 执行任务
0 17 * * sun  /scripts/script.sh
  • 每 10min 执行一次任务
*/10 * * * * /scripts/monitor.sh
  • 在特定的某几个月执行任务
* * * jan,may,aug * /script/script.sh
  • 在特定的某几天执行任务
0 17 * * sun,fri /script/scripy.sh

在每周五、周日的17点执行任务

  • 在某个月的第一个周日执行任务
0 2 * * sun  [ $(date +%d) -le 07 ] && /script/script.sh
  • 每四个小时执行一个任务
0 */4 * * * /scripts/script.sh
  • 每周一、周日执行任务
0 4,17 * * sun,mon /scripts/script.sh
  • 每个30秒执行一次任务

我们没有办法直接通过上诉类似的例子去执行,因为最小的是1min。但是我们可以通过如下的方法。

* * * * * /scripts/script.sh
* * * * *  sleep 30; /scripts/script.sh
  • 多个任务在一条命令中配置
* * * * * /scripts/script.sh; /scripts/scrit2.sh
  • 每年执行一次任务
@yearly /scripts/script.sh

@yearly 类似于“0 0 1 1 *”。它会在每年的第一分钟内执行,通常我们可以用这个发送新年的问候。

  • 每月执行一次任务
@yearly /scripts/script.sh
  • 每周执行一次任务
@yearly /scripts/script.sh
  • 每天执行一次任务
@yearly /scripts/script.sh
  • 每分钟执行一次任务
@yearly /scripts/script.sh
  • 系统重启时执行
@reboot /scripts/script.sh
  • 将 Cron 结果重定向的特定的账户

默认情况下,cron 只会将结果详情发送给 cron 被制定的用户。如果需要发送给其他用户,可以通过如下的方式:

# crontab -l
MAIL=bob
0 2 * * * /script/backup.sh
  • 将所有的 cron 命令备份到文本文件当中

这是一个当我们丢失了cron命令后方便快速的一个恢复方式。
下面是利用这个方式恢复cron的一个小例子。(看看就行~)
首先:检查当前的cron

# crontab -l
MAIL=rahul
0 2 * * * /script/backup.sh

然后:备份cron到文件中

# crontab -l > cron-backup.txt
# cat cron-backup.txt
MAIL=rahul
0 2 * * * /script/backup.sh

接着:移除当前的cron

# crontab -r
# crontab -l
no crontab for root

恢复:从text file中恢复

# crontab cron-backup.txt
# crontab -l
MAIL=rahul
0 2 * * * /script/backup.sh