MySQL 主从复制

 

mysql 的主从复制实现的原理就是 binlog 日志,那么我们主节点负责数据库写操作,而从节点负责读操作,这样在从节点上不需要使用事务,能够大大提高数据库的性能。那么这个时候面临的问题就是从节点如何来同步主节点数据的问题,就用到了我们之前说过的 binlog 日志。从节点通过 binlog 日志来与主节点进行数据同步。

 

学习地址:http://www.roncoo.com/course/view/658088f6e77541f5835b61800314083e 

 

 

三台节点,一个 master,两个 slave,规划如下

 

master                                     192.168.153.201

 

slave1                                     192.168.153.152

 

slave2                                     192.168.153.153

 

三台节点都是使用 CentOS6.9 操作系统,数据库使用的是 mysql5.7。

 

配置 master

 

1.创建用户并授权,比如我们的用户叫做 repl,创建用户语法如下:

 

create user ‘repl’

 

 

 

 

 

 

2.授权。用户必须具备 replication slave 权限,除此之外不需要其他的权限

 

grant replication slave on *.* to ‘repl’@’192.168.153.%’ identified by ‘repl’;

 

 

 

 

 

 

3.开启 binlog 日志

 

这里可以参考开启 binlog 日志的文档。

 

至此,主服务器就配置好了。下面来进行配置从服务器

 

slave1

 

1.修改 my.inf 配置文件

 

[mysqld]server-id=2relay-log-index=slave-relay-bin.indexrelay-log=slave-relay-

 

bin

 

2.连接 Master

 

change master to master_host=’192.168.0.104′, //Master 服务器 Ip

 

master_port=3306,

 

master_user=’repl’,

 

master_password=’mysql’,

 

 

master_log_file=’master-bin.000001′,//Master 服务器产生的日志 master_log_pos=0;

 

change master to

 

master_host=’192.168.153.201′,master_port=3306,master_user=’repl’,master_passwo rd=’repl’,master_log_file=’/var/lib/mysql/mysql-bin.000001′,master_log_pos=0;

 

3.查看状态

 

show slaves status\G

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

这里关注两个地方,第一个是 Slave_IO_Running,第二个是 Slave_SQL_Running。这两个必须都为 yes 才可以启动从节点。那么问题出现在哪里呢,后面会有日志提示

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

这里是说两台节点的 uuid 一致,要让这两台机器的 uuid 不一致才行,那么 uuid 在哪呢,在我们数据目录下 auto.cnf 文件中,只要修改这个文件就可以了。

 

 

 

 

 

 

 

 

再来查看状态,然后就为 yes 了。

 

4.启动

 

start slave

 

5.关闭

 

stop slave

 

6.重置

 

reset    slave

 

学习地址:http://www.roncoo.com/course/view/658088f6e77541f5835b61800314083e 

MySQL主从复制

Synergy 一套键鼠同时控制多台电脑的神器!超级方便!(开源免费,支持Win/Mac/Linux)

想必很多人都拥有多台电脑,譬如台式机+笔记本,很多时候我们都会同时打开它们工作。可是你有没发现,如果桌子上摆放着多台电脑多套键盘鼠标,不停来回切换使用是否很累呢?如果说现在可以只用一套键鼠,就能同时控制你全部的电脑,你会否兴奋?

Synergy 正是为此而生的好工具!它可以让你的多台电脑共享一套键鼠,甚至还可以共享剪贴板,而你只需动动鼠标,指针就可以轻松地在各台电脑屏幕之间来回穿梭,就像一台电脑使用多个显示器一样。而且 Synergy 完全免费开源,并跨平台支持 Win/Mac/Linux,相当给力! 使用之后,工作效率提高,腿不酸腰不疼,桌面也干净了,绝对是绝世神器啊!

「注意:Synergy 现已正式改为*收费*软件了!」

Synergy 的使用方法:

我的桌子上有1个台式机 (Windows7) 和1个 MacBook Pro 笔记本 (Mac OSX),偶尔还会用到另外一台笔记本 (Linux/Win双系统) 同时协同工作,这时候桌子上的键鼠们开始打架了,3个鼠标+2个键盘,还要不断移动身体去迁就电脑的位置。这时候就可以,或者说是非常需要 Synergy 来解放这种痛苦了!OK,开始吧……

Synergy

Synergy 有一个使用前提,就是你的应用环境中的多台电脑需要在同一局域网内。譬如说,家里使用一个路由器共享上网的,其下的全部电脑一般就是在同一局域网内。关于局域网的知识就不再在此阐述了,估计大家都知道怎么组网吧。

虽然 Synergy 的配置和使用其实并不难,但目前它只有英文界面,而且界面我个人感觉做得不是很易用,可能新手咋看上去有点晕,我大概说说它是怎么个运作的吧。当然,这事也不能说得太细,不然大家就没得折腾了,这一没折腾,很多人就没人生乐趣了,到时候黑着脸来找我就不好。

设置服务器端:

为了简单起见,我现在只选用已经在同一局域网下的 Macbook Pro 和 PC 两台电脑,而且为了教程更通用,我把MBP也切换到Win7系统 (就是现在两台电脑都是Win7了),在它们中都安装好 Synergy 之后,那么我们先要挑一台使用键鼠的机器设置为服务器端,这里是我的台式机。如图:

Synergy服务器端

按 Configure Server 进入设置界面:

Synergy设置

从右上角拖动一台电脑放到方框中 (删除的话是把电脑图标拖放到左上角的垃圾桶),模拟现实的位置摆放好。例如我的台式机PC是服务器端,MacBook 是在台式机的左边,按图中那样设置,然后把名字改成客户端电脑的计算机名(Win用户可以在“我的电脑”右键属性中看到)。如果多台电脑也是这样依次添加,确定后返回之前的界面,按Start启动服务。

设置客户端:

客户端的设置比服务器端要简单得多。我们来到 Macbook上,启动 Synergy 后,只要选择成客户端模式,并填上服务器的计算机名或者IP地址即可。如下图,设置好后,同样按 Start 即可让其连接服务器。

Synergy客户端

一般来说,如果连接成功的话,你的鼠标已经可以游走在两台电脑之间了。当然,当的鼠标从PC移动到Macbook之后,我们的键盘也会对Macbook生效,而对PC无效了。我可以在 MacBook 上CTRL+C拷贝一些文字,然后再移动回PC上按键盘CTRL+V粘贴,一切都是那么顺畅自然!非常有意思!

写在后面:

Synergy 真的是一款相当相当赞的软件!它能大大提高多电脑用户的工作效率,特别是频繁要在不同平台下工作的朋友。更难能可贵的是,这么优秀的一款软件竟然还是免费开源的~不得不对作者肃然起敬啊。其实对于这种软件,即使是要付款的,我也觉得很值得,因为它能真真切切地方便自己。目前唯一美中不足的是,它只能跨机共享剪贴板中的文本信息,不能跨电脑拷贝文件,也不能方便地在两台电脑之间随意拖动来传输文件,不然就真是碉堡了。至于在MacLinux下的操作、快捷键的设置等更多高级的玩法就等你自己去折腾吧。

另外,我发现这货还能用来捉弄人,让女友/男友给送个小鼠标,然后偷偷帮ta装上 Synergy 之后连接好,在Ta正沉迷着玩某东西的时候,一鼠标飞过去,咩咔咔,咱家的小鼠标还有魔法效果呢!这种吓死爹的效果真不错的。废话我说完了,撤……

相关文件下载地址:

官方网站:访问
软件性质:付费

下载 Synergy (Windows版32位)  |  Win64位  |  Mac版  |  Ubuntu/Debian版  |  Fedora/RedHat版

 http://www.iplaysoft.com/synergy.html

亚马逊 MWS接口 调用错误解决办法 Redefinition of parameter $quotaMax

PHP Compile Error – yii\base\ErrorException

Redefinition of parameter $quotaMax

  • 1. in /home/wwwroot/amz.codecenter.cn/frontend/controllers/MarketplaceWebServiceProducts/Model/ResponseHeaderMetadata.phpat line 31
    const REQUEST_ID = 'x-mws-request-id';
      const RESPONSE_CONTEXT = 'x-mws-response-context';
      const TIMESTAMP = 'x-mws-timestamp';
      const QUOTA_MAX = 'x-mws-quota-max';
      const QUOTA_REMAINING = 'x-mws-quota-remaining';
      const QUOTA_RESETS_AT = 'x-mws-quota-resetsOn';
     
      private $metadata = array();
     
      public function __construct($requestId = null, $responseContext = null, $timestamp = null,$quotaMax = null, $quotaMax = null, $quotaResetsAt = null) {
    //    public function __construct($requestId = null, $responseContext = null, $timestamp = null,$quotaMax = null, $quotaRemaining = null, $quotaResetsAt = null) {
        $this->metadata[self::REQUEST_ID] = $requestId;
        $this->metadata[self::RESPONSE_CONTEXT] = $responseContext;
        $this->metadata[self::TIMESTAMP] = $timestamp;
        $this->metadata[self::QUOTA_MAX] = $quotaMax;
        $this->metadata[self::QUOTA_REMAINING] = $quotaMax;
        $this->metadata[self::QUOTA_RESETS_AT] = $quotaResetsAt;
      }
    
    

解决办法

修改一下文件

MarketplaceWebServiceProducts/Model/ResponseHeaderMetadata.php

修改前

public function __construct($requestId = null, $responseContext = null, $timestamp = null,$quotaMax = null, $quotaMax = null, $quotaResetsAt = null) {
    $this->metadata[self::REQUEST_ID] = $requestId;
    $this->metadata[self::RESPONSE_CONTEXT] = $responseContext;
    $this->metadata[self::TIMESTAMP] = $timestamp;
    $this->metadata[self::QUOTA_MAX] = $quotaMax;
    $this->metadata[self::QUOTA_REMAINING] = $quotaMax;
    $this->metadata[self::QUOTA_RESETS_AT] = $quotaResetsAt;
  }

修改后

 
 public function __construct($requestId = null, $responseContext = null, $timestamp = null,$quotaMax = null, $quotaRemaining = null, $quotaResetsAt = null) {
    $this->metadata[self::REQUEST_ID] = $requestId;
    $this->metadata[self::RESPONSE_CONTEXT] = $responseContext;
    $this->metadata[self::TIMESTAMP] = $timestamp;
    $this->metadata[self::QUOTA_MAX] = $quotaMax;
    $this->metadata[self::QUOTA_REMAINING] = $quotaRemaining;
    $this->metadata[self::QUOTA_RESETS_AT] = $quotaResetsAt;
  }

crontab从入门到出坑

此篇技术博文主要介绍的是crontab,Linux下的计划任务管理工具。涉及内容包括crontab使用配置、常见坑的分析和编者总结的错误调试方法。非标题党文章,真正地帮您从入门到出坑。

category.png

我的理解,后台任务通常分为两种:常驻和定时。之前的文章《pm2进程管理工具使用总结》主要针对的是常驻任务。今天来谈谈crontab,主要针对的是定时任务。

实验环境:centos7

介绍crontab

crontab的服务进程名为crond,英文意为周期任务。顾名思义,crontab在Linux主要用于周期定时任务管理。通常安装操作系统后,默认已启动crond服务。crontab可理解为cron_table,表示cron的任务列表。类似crontab的工具还有at和anacrontab,但具体使用场景不同,可参见附录《让你学会Linux计划任务》一文了解更多。

关于crontab的用途很多,如

  • 定时系统检测;
  • 定时数据采集;
  • 定时日志备份;
  • 定时更新数据缓存;
  • 定时生成报表;

    等等任务

当然,更多使用场景是要以视具体情况而定了。毕竟是工具通常都是常用规则总结而成的产物。

确认crond服务已经安装与开启之后,下面开始具体说明

简单示例

先来个简单示例体验一下。

  • 目标:每分钟向/tmp/time.txt文件下写入当前时间
  • 新建crontab任务
    $ crontab -e      // 打开crontab任务编辑
    * * * * * date >> /tmp/time.txt
  • 静静等待几分钟
    $ cat /tmp/time.txt
    Do 29. Dez 22:45:01 CST 2016
    Do 29. Dez 22:46:01 CST 2016
    Do 29. Dez 22:47:01 CST 2016
  • 从上面结果看出,每分钟执行了date并写入到/tmp/time.txt。

简单示例演示成功。下面从细节深入说明crontab使用。

使用选项

上面的实验中使用了crontab命令的-e选项。我们来看看crontab命令中有哪些选项?

  • -e 选项 表示打开当前用户的crontab任务列表配置文件。当然也可以直接打开,路径通常是在/var/spool/cron/下,文件以用户名命名,如/var/spool/cron/root。不过,采用-e方式打开,福利是可以帮助我们自动检查任务配置符合规则。
  • -u 选项 指定某用户的任务列表,很好理解。比如我当前是root用户,想操作poloxue用户的任务列表。如下:
    $ crontab -u poloxue -e
  • -l 选项 列出某用户的所有任务列表
  • -r 选项 删除某用户的所有任务列表,这个选项使用小心为上,估计也只是自己实验时玩玩而已,正常不使用。

crontab命令的选项中,主要使用的就是以上几个,理解比较简单。

任务配置

说完了crontab的命令选项,下面开始真正的大戏,任务列表文件如何配置?

首先,看下crontab任务列表配置格式,示例文件如下:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# 更多细节 man 4 crontabs

# 计划任务定义的例子:
# .---------------- 分 (0 - 59)
# |  .------------- 时 (0 - 23)
# |  |  .---------- 日 (1 - 31)
# |  |  |  .------- 月 (1 - 12)
# |  |  |  |  .---- 星期 (0 - 7) (星期日可为0或7)
# |  |  |  |  |
# *  *  *  *  * 执行的命令
* * * * * date >> /time.txt 2>&1

从上面的示例文件可看出,crontab的任务列表主要由两部分组成:环境变量配置与定时任务配置。可能大家在工作中更多是只用到了任务配置部分。

环境变量配置部分

理解环境变量配置这部分可以帮助我们减少去踩一些不必要的坑。简单说明上面涉及的环境变量。

  • SHELL为/bin/bash,表示使用/bin/bash解释执行命令
  • PATH表示到哪些目录路径寻找命令程序,此环境变量的值说明了为什么我们在crontab中执行命令时,尽量要写命令全路径才能执行的原因。
  • MAILTO变量作用是当任务执行有输出时,内容发送到哪个用户的邮箱。禁用可以设置MAILTO=””。

当我们在使用crontab时,发现某些定时任务不能顺利执行,但shell控制台执行成功,环境变量是否正确是我们需要首先关注的点之一。具体详情可以看后面关于环境变量坑的说明。

定时任务配置部分

这部分是crontab配置核心。

  • 基本配置
    如下所示配置共6列,前5列是关于执行时间配置,最后1列是具体执行命令。

    .---------------- 分 (0 - 59)
    |  .------------- 时 (0 - 23)
    |  |  .---------- 日 (1 - 31)
    |  |  |  .------- 月 (1 - 12)
    |  |  |  |  .---- 星期 (0 - 6) (星期日可为0或7)
    |  |  |  |  |
    *  *  *  *  * 执行的命令

    第一列单位为分,表示每时第几分钟,范围为0-59;
    第二列单位为时,表示每天第几小时,范围为0-23;
    第三列单位为日,表示每月第几天,范围为1-31;
    第四列单位为月,表示每年第几月,范围为1-12;
    第五列单位为星期,表示每星期第几天,范围0-7,0与7表示星期日,其他分别为星期1-6;

  • 时间配置段类型
    根据时间列中值的不同设置方式,编者总结出以下五种类型:

    固定某值,指定固定值,如指定1月1日0时0分执行任务

    0 0 1 1 * command

    月日时分都指定了固定数值。

    <font color=red>注:*在crontab中表示任意值都满足条件。</font>

    列表值,时间值是一个列表,如指定一个月内2、12、22日零时执行任务

    0 0 2,12,22 * * command

    上述日指定多个值,2号、12号和22号,以逗号分隔;

    连续范围值,时间为连续范围的值,如指定每个月1至7号零时执行任务

    0 0 1-7 * * command

    上述日期为连续范围的值1-7时

    步长值,根据指定数值跳跃步长确定执行时间,如指定凌晨1时开始每割3个小时0分执行一次任务

    0 1-24/3 * * * command

    上述指定从凌晨1时每3个小时执行任务,如1点0分,4点0分,7点0分等。

    混合值,支持以上类型的组合,如指定每小时0至10分,22、33分以及0-60分钟每隔20分钟执行任务,如下

    0-10,22,33,*/20 * * * * command

    这里的分钟值采取了多种类型组合指定,包括连续范围值(0-7),列表值(22,33),步长值(*/20)。

    <font color=red>声明:这几种时间配置类型是编者自己总结,希望能帮助大家更好理解。有错误帮忙指出。</font>

定时语句解析工具

通常在使用crontab添加任务时,我们会依靠自己已有知识编写定时语句。当需要测试语句是否正确时,总需要一定时间等待证明其正确性。作为一名牛逼的程序员,这种方式就太不酷了。有没有一款工具,只要我们给出语句,其就能告诉具体执行时间呢?下面介绍一款老外开发的crontab在线解析工具。

工具地址:https://crontab.guru

下面是这个工具的截图

crontab_tool.png

从上面看出,我们输入的语句解析结果为每天的04:05执行任务。下面有这样一行文字“next at 2016-12-31 04:05:00”,告诉了我们最近一次的执行时间。

<font color=red>注明:百度搜索“crontab在线解析”获得的工具有坑,某些语句解析结果错误。为避免大家受骗,这里提供具体地址:http://tool.lu/crontab/</font>

使用有坑

crontab使用中常会遇到各种坑。下面列出编者在使用中曾遇到的一些问题。

时间配置误区

此处介绍两种坑,一种是由于基本功不足导致配置错误,而另一种则是多数人对crontab配置都存在的一个理解误区。

  • 整点时间设置错误
    其实这个错误不用单独说明,但是编者刚开始接触crontab时犯过,单独拿出来说明一下。

    如设定每天3点执行一次某任务
    下面列出错误方式,当我们听到每天3点执行一次某任务时,很多人会把重点放在3点,而忽略了执行一次的需求。

    下面是个错误的例子

    * 3 * * * command

    这里会导致在三点的每分钟都会执行一次任务,也就是执行了60次。
    正确方式如下,每天3点0时执行任务

    0 3 * * * command
  • 日与星期的关系误区
    这真的是个大误区,很多人都不知道的大误区。直接开始说明吧。

    好,首先做两个练习

    设置任务一:每月的1-7每天零时执行某任务,答案如下:

    0 0 1-7 * * date >> /tmp/date.txt

    设置任务二:每星期的星期一零时执行某任务,答案如下:

    0 0 * * 1 date >> /tmp/date.txt

    上面两个任务的设定都是正确的。
    下面提出第三个任务,设置每个月的第一个星期一零时执行某任务
    分解任务要求,首先,第一个星期就是每个月的1-7日,而星期一就是星期一。所以我们理解的crontab任务配置如下

    0 0 1-7 * 1 date >> /tmp/date.txt

    下面直接使用前面介绍的在线解析工具分析此语句,如下

    crontab_time.png

    解析结果显示语句执行时间为每月的1至7日和每星期一。可以看到最近执行时间是“next at 2017-01-01 00:00:00”,这个时间也并非星期一。

    这是crontab的一个特别容易误解之处,下面直接给出结论:

    当日和星期任一列包含时,日与星期两者为并且的关系;
    当日和星期列中不包含
    时,日与星期两者为或者的关系;

<font color=red>请注意,前面提到的那个百度搜索出来的工具分析结果显示的确是每月第一个星期一,这是错误的。如有朋友持怀疑态度,可自行验证,如有错误,随时告知。</font>

环境变量问题

当我们刚使用crontab时,有人会告知所有命令尽量都使用绝对路径,以防错误。为什么?这就和我们下面要谈的环境变量有关了。

  • 首先,获取控制台环境变量看下
    $ env
    XDG_SESSION_ID=10
    HOSTNAME=localhost.localdomain
    SHELL=/bin/bash
    PERL_MB_OPT=--install_base /root/perl5
    USER=root
    MAIL=/var/spool/mail/root
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/php5/bin
    PWD=/var/mail
    SHLVL=1
    HOME=/root
    LOGNAME=root
    XDG_RUNTIME_DIR=/run/user/0
    _=/usr/bin/env

    <font color=red>考虑篇幅,输出有删减。</font>

  • 然后,获取crontab环境变量信息
    * * * * * /usr/bin/env > /tmp/env.txt

    输出结果,如下

    $ cat /tmp/env.txt
    XDG_SESSION_ID=732
    SHELL=/bin/sh
    USER=root
    PATH=/usr/bin:/bin
    PWD=/root
    LANG=de_DE.UTF-8
    SHLVL=1
    HOME=/root
    LOGNAME=root
    XDG_RUNTIME_DIR=/run/user/0
    _=/usr/bin/en
  • 对比分析两者输出
    对比crontab与控制台输出,我们发现两者的环境变量差异很大。如果命令在控制台执行成功,而在crontab执行失败,我们需要考虑是否命令涉及的环境变量在crontab和控制台间存在差异。
  • 明白crontab使用绝对路径执行命令原因了吗?
    我们知道命令默认查找路径是由PATH指定的。

    从上面输出结果可知,控制台的PATH值为

    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/php/bin

    crontab的PATH值为

    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/php/bin

    crontab的PATH值为

    PATH=/usr/bin:/bin

    /usr/local/php/bin/下面存在php命令,在控制台执行成功

    $ php index.php

    因在crontab的PATH变量无/usr/local/php/bin/,其执行php命令则会失败。

  • 解决方式
    已知哪个环境变量导致问题,可以直接在crontab配置中加入变量配置。
    不知哪个环境变量导致问题,终极大招是引入控制台环境变量,如下

    * * * * * source /$HOME/.bash_profile && command

    当然,对于某特定环境变量或有特定的处理方式,如PATH,命令使用绝对路径亦可解决。

特殊符号%

%在crontab是特殊符号,具体含义如下:

  • 第一个%表示标准输入的开始
    * * * * * cat >> /tmp/cat.txt 2>&1 % stdin input

    执行成功之后,查看/tmp/cat.txt

    $ cat /tmp/cat.txt
    stdin input

    我们看到标准输入写入到了/tmp/cat.txt文件。

    <font color=red>理解上面示例,首先需知cat >> /tmp/cat.txt ,作用是将标准输入重定向至/tmp/cat.txt。</font>

  • 其余%表示换行符

    示例如下

    * * * * * cat >> /tmp/cat_line.txt 2>&1 % stdin input 1 % stdin input 2 % stdin input 3

    查看输出

    $ cat /tmp/cat_line.txt
    stdin input 1
    stdin input 2
    stdin input 3

    有三行输出

  • 解决方式

    既然是特殊字符,自然而然就想到了使用\进行转义,如下:

    * * * * * cat >> /tmp/cat_special.txt 2>&1 % per cent is \%. 2>&1

    查看输出

    $ cat /tmp/cat_special.txt
    per cent is %.

    执行成功了。自此,你就顺利爬出了%特殊字符问题的坑。

关于这个问题的具体说明,可以参看附录中的《Crontab and %》。

关于输出重定向

当我们不做输出重定向时,如任务有大量输出,或许有些无法解释的问题。

  • 输出写入邮件
    crontab任务输出默认写入到执行用户的邮件中,如下演示:

    * * * * * date

    命令输出当前日期,下面查看当前用户的邮件

    $ cat /var/spool/mail/$USER
    ...
    
    Sat Dec 31 17:45:01 CST 2016

    由此可见,任务输出的日期信息写入到了用户邮件中。

    如任务有大量输出,会占用磁盘资源。但编者测试显示,如磁盘容量不足,任务也会执行,但输出不会写入邮件;

  • 关闭邮件功能
    如何关闭?设置MAILTO环境变量为空。如下

    MAILTO=""
    * * * * * date

    是不是关闭邮件写入就好了?附录《Linux中的crontab与sendmail》博文表明,关闭mail功能,输出内容将写入到/var/spool/clientmqueue中,可能占满分区的inode资源,导致任务无法执行。inode资源使用情况可通过如下命令获取

    $ df -i
    Filesystem Inodes   IUsed  IFree    IUse% Mounted on
    /dev/sda1  512000   378    511622   1%    /boot
    /dev/sda2  92672000 185351 92486649 1%    /

    抱歉!这种情况编者并未测出!但在公司的生产环境发现过未重定向则任务不执行的情况,加上后解决了问题。百度也搜索到了类似问题,如有朋友了解,欢迎指教,万分感谢。

    当然,为了避免此类问题发生,建议任务都加上输出重定向,如下

    * * * * * date >> /dev/null/ 2>&1

    输出到/dev/null中,标准输入和标准错误都应处理。

    如大家对重定向有疑惑,可参见附录中的《Linux重定向》,对文解释不错。

<font color=red>程序员的感悟:在技术的世界,当我们不按常理做事,事情也不会按常理犯错。</font>

调试大招

最后的福利,编者根据自己的总结而梳理出一套快速定位crontab错误的思路。两个角度:

  • 任务是否执行
  • 命令是否正确
任务是否执行?
  • 调试思路

    首先,通过日志确认任务是否执行
    然后,如未执行则分析定时语句,
    最后,定时没有问题,检查crond服务是否开启

    下面说明具体分析步骤。

  • 日志确认
    调试错误,日志通常是个利器,crontab也有日志。
    编者的服务器中crontab日志文件位置为/var/log/cron

    查看日志
    日志中包含任务执行记录,配置错误提示,任务配置编辑重载记录,服务开启等记录。

    下面是日志的部分内容,

    $ vim /var/log/cron
    ...
    Dec 31 19:17:01 localhost crond[1455]: (CRON) bad day-of-week (/var/spool/cron/root)
    Dec 31 19:17:01 localhost CROND[4409]: (root) CMD (date)
    ...

    这里截取了对调试比较重要的两条记录,如下介绍

    执行记录

    Dec 31 19:17:01 localhost CROND[4409]: (root) CMD (date)

    显示12月21 19时17分1秒执行了date命令

    配置错误

    Dec 31 19:17:01 localhost crond[1455]: (CRON) bad day-of-week (/var/spool/cron/root)

    上面显示/var/spool/cron/root的任务配置有错,也就是root任务配置有错。错误原因:bad day-of-week,星期配置有错。

    语句是这样的

    * * * * date >> /dev/null 2>&1

    明显缺少了星期时间段。

  • 确认定时语句

    通过上面的日志分析,如任务没有执行,使用定时语句在线分析工具分析定时是否正确,非常简单。

  • 确认服务开启
    如果定时语句也正确,检查服务是否开启。检测命令如下

    Systemd方式(centos7及以上)

    $ systemctl status crond.service

    SysVinit方式(centos7以下)

    $ service crond status

    查看命令输出,如未开启,执行如下命令开启

    Systemd方式(centos7及以上)

    $ systemctl start crond.service

    SysVinit方式(centos7以下)

    $ service crond start

确认任务成功后,如问题仍未解决,继续往下看。

命令是否正确

确认命令成功与否,这里总结步骤大致如下

  • 获取命令执行输出
    crontab中的命令执行出错,多数人都不知道如何调试。我们知道在控制台执行命令时,可通过输出获取错误信息调试问题。这种方式在crontab同样适用,方法就是利用重新向获取输出,进行分析。示例如下

    * * * * * php /root/index.php >> /tmp/debug.log 2>&1

    这条任务总是执行失败,我们把输出重定向到/tmp/debug.log。
    查看debug.log,如下

    $ cat /tmp/debug.log
    /bin/sh: php: command not found
    /bin/sh: php: command not found

    显示php命令没有找到,很明显的就可以确定是环境变量的问题。这种方式定位问题非常有效。

  • 具体问题具体分析
    有了命令执行的输出,下面就是具体问题具体分析了。或许是前面提到的各种坑,也或许是命令本身所独有的问题。

调试的方法到这里就说完了。但还是实践为王,需持续总结,同时也希望大家不要在同样的坑中重复犯错。


作者:波罗学
链接:http://www.jianshu.com/p/8bf8f6529108
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

计划任务crontab 命令

Linux 系统提供了使用者控制计划任务的命令 :crontab 命令。

一、crond简介

crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进程。

crond进程每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。
Linux下的任务调度分为两类,系统任务调度和用户任务调度。

系统任务调度

系统周期性所要执行的工作,比如写缓存数据到硬盘、日志清理等。在/etc目录下有一个crontab文件,这个就是系统任务调度的配置文件。
/etc/crontab文件包括下面几行:

[root@localhost ~]# cat /etc/crontab 
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=""
HOME=/
# run-parts
51 * * * * root run-parts /etc/cron.hourly
24 7 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly

前四行是用来配置crond任务运行的环境变量:第一行SHELL变量指定了系统要使用哪个shell,这里是bash,第二行PATH变量指定了系统执行命令的路径,第三行MAILTO变量指定了crond的任务执行信息将通过电子邮件发送给root用户,如果MAILTO变量的值为空,则表示不发送任务执行信息给用户,第四行的HOME变量指定了在执行命令或者脚本时使用的主目录。第六至九行表示的含义将在下个小节详细讲述。这里不在多说。

用户任务调度

用户定期要执行的工作,比如用户数据备份、定时邮件提醒等。用户可以使用 crontab 工具来定制自己的计划任务。所有用户定义的crontab 文件都被保存在/var/spool/cron目录中。其文件名与用户名一致。
使用者权限文件:

文件 说明
/etc/cron.deny 该文件中所列用户不允许使用crontab命令
/etc/cron.allow 该文件中所列用户允许使用crontab命令
/var/spool/cron/ 所有用户crontab文件存放的目录,以用户名命名

crontab文件的含义

用户所建立的crontab文件中,每一行都代表一项任务,每行的每个字段代表一项设置,它的格式共分为六个字段,前五段是时间设定段,第六段是要执行的命令段,格式如下:

minute hour day month week command
minute: 表示分钟,可以是从0到59之间的任何整数。
hour:表示小时,可以是从0到23之间的任何整数。
day:表示日期,可以是从1到31之间的任何整数。
month:表示月份,可以是从1到12之间的任何整数。
week:表示星期几,可以是从0到7之间的任何整数,这里的0或7代表星期日。
command:要执行的命令,可以是系统命令,也可以是自己编写的脚本文件。

命令格式.png

在以上各个字段中,还可以使用以下特殊字符:

  • 星号(*):代表所有可能的值,例如month字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。
  • 逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”
  • 中杠(-):可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”
  • 正斜线(/):可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。同时正斜线可以和星号一起使用,例如*/10,如果用在minute字段,表示每十分钟执行一次。

二、crond服务

安装crontab: yum install crontabs
服务操作说明:

/sbin/service crond start //启动服务
/sbin/service crond stop //关闭服务
/sbin/service crond restart //重启服务
/sbin/service crond reload //重新载入配置

查看crontab服务状态:service crond status
手动启动crontab服务:service crond start
查看crontab服务是否已设置为开机启动,执行命令:ntsysv
加入开机自动启动:chkconfig –level 35 crond on

三、crontab命令详解

1. 命令格式:

crontab [-u user] file
crontab [-u user] [ -e | -l | -r ]

2. 命令功能:

通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell script脚本。时间间隔的单位可以是分钟、小时、日、月、周及以上的任意组合。这个命令非常设合周期性的日志分析或数据备份等工作。

3. 命令参数:

-u user:用来设定某个用户的crontab服务,例如,“-u ixdba”表示设定ixdba用户的crontab服务,此参数一般有root用户来运行。
file:file是命令文件的名字,表示将file做为crontab的任务列表文件并载入crontab。如果在命令行中没有指定这个文件,crontab命令将接受标准输入(键盘)上键入的命令,并将它们载入crontab。
-e:编辑某个用户的crontab文件内容。如果不指定用户,则表示编辑当前用户的crontab文件。
-l:显示某个用户的crontab文件内容,如果不指定用户,则表示显示当前用户的crontab文件内容。
-r:从/var/spool/cron目录中删除某个用户的crontab文件,如果不指定用户,则默认删除当前用户的crontab文件。
-i:在删除用户的crontab文件时给确认提示。

4. 常用方法:

1). 创建一个新的crontab文件
在考虑向cron进程提交一个crontab文件之前,首先要做的一件事情就是设置环境变量EDITOR。cron进程根据它来确定使用哪个编辑器编辑crontab文件。99%的UNIX和LINUX用户都使用vi,如果你也是这样,那么你就编辑$HOME目录下的. profile文件,在其中加入这样一行:
EDITOR=vi; export EDITOR
然后保存并退出。不妨创建一个名为<user> cron的文件,其中<user>是用户名,例如, davecron。在该文件中加入如下的内容。

    # (put your own initials here)echo the date to the console every
    # 15minutes between 6pm and 6am
    0,15,30,45 18-06 * * * /bin/echo 'date' > /dev/console

保存并退出。确信前面5个域用空格分隔。
在上面的例子中,系统将每隔15分钟向控制台输出一次当前时间。如果系统崩溃或挂起,从最后所显示的时间就可以一眼看出系统是什么时间停止工作的。在有些系统中,用tty1来表示控制台,可以根据实际情况对上面的例子进行相应的修改。为了提交你刚刚创建的crontab文件,可以把这个新创建的文件作为cron命令的参数:$ crontab davecron
现在该文件已经提交给cron进程,它将每隔1 5分钟运行一次。
同时,新创建文件的一个副本已经被放在/var/spool/cron目录中,文件名就是用户名(即dave)。
2). 列出crontab文件
为了列出crontab文件,可以用:

    $ crontab -l
    0,15,30,45,18-06 * * * /bin/echo `date` > dev/tty1

你将会看到和上面类似的内容。可以使用这种方法在$HOME目录中对crontab文件做一备份:
$ crontab -l > $HOME/mycron
这样,一旦不小心误删了crontab文件,可以用上一节所讲述的方法迅速恢复。
3). 编辑crontab文件
如果希望添加、删除或编辑crontab文件中的条目,而EDITOR环境变量又设置为vi,那么就可以用vi来编辑crontab文件,相应的命令为:$ crontab -e
可以像使用v i编辑其他任何文件那样修改crontab文件并退出。如果修改了某些条目或添加了新的条目,那么在保存该文件时,cron会对其进行必要的完整性检查。如果其中的某个域出现了超出允许范围的值,它会提示你。
我们在编辑crontab文件时,没准会加入新的条目。例如,加入下面的一条:

       # DT:delete core files,at 3.30am on 1,7,14,21,26,26 days of each month
    30 3 1,7,14,21,26 * * /bin/find -name "core' -exec rm {} \;

现在保存并退出。最好在crontab文件的每一个条目之上加入一条注释,这样就可以知道它的功能、运行时间,更为重要的是,知道这是哪位用户的作业。
现在让我们使用前面讲过的crontab -l命令列出它的全部信息:

       $ crontab -l 
       # (crondave installed on Tue May 4 13:07:43 1999)
       # DT:ech the date to the console every 30 minites
      0,15,30,45 18-06 * * * /bin/echo `date` > /dev/tty1
       # DT:delete core files,at 3.30am on 1,7,14,21,26,26 days of each month
       30 3 1,7,14,21,26 * * /bin/find -name "core' -exec rm {} \;

4). 删除crontab文件
要删除crontab文件,可以用:$ crontab -r
5). 恢复丢失的crontab文件
如果不小心误删了crontab文件,假设你在自己的$HOME目录下还有一个备份,那么可以将其拷贝到/var/spool/cron/<username>,其中<username>是用户名。如果由于权限问题无法完成拷贝,可以用:
$ crontab <filename>
其中,<filename>是你在$HOME目录中副本的文件名。
我建议你在自己的$HOME目录中保存一个该文件的副本。我就有过类似的经历,有数次误删了crontab文件(因为r键紧挨在e键的右边)。这就是为什么有些系统文档建议不要直接编辑crontab文件,而是编辑该文件的一个副本,然后重新提交新的文件。
有些crontab的变体有些怪异,所以在使用crontab命令时要格外小心。如果遗漏了任何选项,crontab可能会打开一个空文件,或者看起来像是个空文件。这时敲delete键退出,不要按<Ctrl-D>,否则你将丢失crontab文件。

5. 使用实例

  • 实例1:每1分钟执行一次command
    命令:* * * * * command
  • 实例2:每小时的第3和第15分钟执行
    命令:3,15 * * * * command
  • 实例3:在上午8点到11点的第3和第15分钟执行
    命令: 3,15 8-11 * * * command
  • 实例4:每隔两天的上午8点到11点的第3和第15分钟执行
    命令: 3,15 8-11 */2 * * command
  • 实例5:每个星期一的上午8点到11点的第3和第15分钟执行
    命令: 3,15 8-11 * * 1 command
  • 实例6:每晚的21:30重启smb
    命令: 30 21 * * * /etc/init.d/smb restart
  • 实例7:每月1、10、22日的4 : 45重启smb
    命令: 45 4 1,10,22 * * /etc/init.d/smb restart
  • 实例8:每周六、周日的1 : 10重启smb
    命令: 10 1 * * 6,0 /etc/init.d/smb restart
  • 实例9:每天18 : 00至23 : 00之间每隔30分钟重启smb
    命令: 0,30 18-23 * * * /etc/init.d/smb restart
  • 实例10:每星期六的晚上11 : 00 pm重启smb
    命令: 0 23 * * 6 /etc/init.d/smb restart
  • 实例11:每一小时重启smb
    命令: * */1 * * * /etc/init.d/smb restart
  • 实例12:晚上11点到早上7点之间,每隔一小时重启smb
    命令: * 23-7/1 * * * /etc/init.d/smb restart
  • 实例13:每月的4号与每周一到周三的11点重启smb
    命令: 0 11 4 * mon-wed /etc/init.d/smb restart
  • 实例14:一月一号的4点重启smb
    命令:0 4 1 jan * /etc/init.d/smb restart
  • 实例15:每小时执行/etc/cron.hourly目录内的脚本
    命令:01 * * * * root run-parts /etc/cron.hourly
    说明:run-parts这个参数了,如果去掉这个参数的话,后面就可以写要运行的某个脚本名,而不是目录名了

四、使用注意事项

1. 注意环境变量问题

有时我们创建了一个crontab,但是这个任务却无法自动执行,而手动执行这个任务却没有问题,这种情况一般是由于在crontab文件中没有配置环境变量引起的。
在crontab文件中定义多个调度任务时,需要特别注意的一个问题就是环境变量的设置,因为我们手动执行某个任务时,是在当前shell环境下进行的,程序当然能找到环境变量,而系统自动执行任务调度时,是不会加载任何环境变量的,因此,就需要在crontab文件中指定任务运行所需的所有环境变量,这样,系统执行任务调度时就没有问题了。
不要假定cron知道所需要的特殊环境,它其实并不知道。所以你要保证在shelll脚本中提供所有必要的路径和环境变量,除了一些自动设置的全局变量。所以注意如下3点:

  • 1)脚本中涉及文件路径时写全局路径;
  • 2)脚本执行要用到java或其他环境变量时,通过source命令引入环境变量,如:
      cat start_cbp.sh
      #!/bin/sh
      source /etc/profile
      export RUN_CONF=/home/d139/conf/platform/cbp/cbp_jboss.conf
      /usr/local/jboss-4.0.5/bin/run.sh -c mev &
  • 3)当手动执行脚本OK,但是crontab死活不执行时。这时必须大胆怀疑是环境变量惹的祸,并可以尝试在crontab中直接引入环境变量解决问题。如:
       0 * * * * . /etc/profile;/bin/sh /var/www/java/audit_no_count/bin/restart_audit.sh

2. 注意清理系统用户的邮件日志

每条任务调度执行完毕,系统都会将任务输出信息通过电子邮件的形式发送给当前系统用户,这样日积月累,日志信息会非常大,可能会影响系统的正常运行,因此,将每条任务进行重定向处理非常重要。
例如,可以在crontab文件中设置如下形式,忽略日志输出:

    0 */3 * * * /usr/local/apache2/apachectl restart >/dev/null 2>&1

/dev/null 2>&1表示先将标准输出重定向到/dev/null,然后将标准错误重定向到标准输出,由于标准输出已经重定向到了/dev/null,因此标准错误也会重定向到/dev/null,这样日志输出问题就解决了。

3. 系统级任务调度与用户级任务调度

系统级任务调度主要完成系统的一些维护操作,用户级任务调度主要完成用户自定义的一些任务,可以将用户级任务调度放到系统级任务调度来完成(不建议这么做),但是反过来却不行,root用户的任务调度操作可以通过crontab –uroot –e来设置,也可以将调度任务直接写入/etc/crontab文件,需要注意的是,如果要定义一个定时重启系统的任务,就必须将任务放到/etc/crontab文件,即使在root用户下创建一个定时重启系统的任务也是无效的。

4. 其他注意事项

新创建的cron job,不会马上执行,至少要过2分钟才执行。如果重启cron则马上执行。
当crontab突然失效时,可以尝试/etc/init.d/crond restart解决问题。或者查看日志看某个job有没有执行/报错tail -f /var/log/cron
千万别乱运行crontab -r。它从Crontab目录(/var/spool/cron)中删除用户的Crontab文件。删除了该用户的所有crontab都没了。
在crontab中%是有特殊含义的,表示换行的意思。如果要用的话必须进行转义\%,如经常用的date ''+%Y%m%d'在crontab里是不会执行的,应该换成date '+\%Y\%m\%d'

注意:本文转载整理自http://www.cnblogs.com/peida/archive/2013/01/08/2850483.html

注意:本文转载整理自http://www.cnblogs.com/peida/archive/2013/01/08/2850483.html

linux 脚本定时任务 计划任务crontab 命令


[root@VM_99_203_centos etc]# cat crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# 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

 

计划任务crontab 命令

crontab从入门到出坑

 

 

 

yii2 安装使用redis 通过composer 安装Predis及使用教程

yii 安装Predis扩展程序

参考地址

https://packagist.org/packages/predis/predis

composer 执行以下命令

composer require predis/predis

php 代码如下

<?php
namespace frontend\controllers;

use Yii;
use yii\web\Controller;
/*redis 需要使用的命名空间*/
use Predis\Autoloader;
use Predis\Client;

class RedisController extends Controller
{

    public function actionIndex()
    {
//        Autoloader::register();
        $client =new Client([
            'scheme' => 'tcp',
            'host'   => '127.0.0.1',
            'port'   => 6379,
        ]);
        $client->set('foo', 'bar5');
        echo $value = $client->get('foo');
    }
    
}

https://github.com/nrk/predis

 


//使用autoload加载相关库,这边重点就是为了require $file;
spl_autoload_register ( function ( $class ) {
$file = __DIR__ . '/lib/Predis/' . $class . '.php' ;
if ( file_exists ( $file ) ) {
require $file ;
return true ;
}
} ) ;

&nbsp;

//配置连接的IP、端口、以及相应的数据库
$server = array (
'host' => '127.0.0.1' ,
'port' => 6379 ,
'database' => 15
) ;
$redis = new Client ( $server ) ;

&nbsp;

//普通set/get操作
$redis -> set ( 'library' , 'predis' ) ;
$retval = $redis -> get ( 'library' ) ;
echo $retval ; //显示 'predis'

//setex set一个存储时效
$redis -> setex ( 'str' , 10 , 'bar' ) ; //表示存储有效期为10秒

//setnx/msetnx相当于add操作,不会覆盖已有值
$redis -> setnx ( 'foo' , 12 ) ; //true
$redis -> setnx ( 'foo' , 34 ) ; //false

//getset操作,set的变种,结果返回替换前的值
$redis -> getset ( 'foo' , 56 ) ; //返回34

// incrby/incr/decrby/decr 对值的递增和递减
$redis -> incr ( 'foo' ) ; //foo为57
$redis -> incrby ( 'foo' , 2 ) ; //foo为59

//exists检测是否存在某值
$redis -> exists ( 'foo' ) ; //true

//del 删除
$redis -> del ( 'foo' ) ; //true

//type 类型检测,字符串返回string,列表返回 list,set表返回set/zset,hash表返回hash
$redis -> type ( 'foo' ) ; //不存在,返回none
$redis -> set ( 'str' , 'test' ) ;
$redis -> type ( 'str' ) ; //字符串,返回string

//append 连接到已存在字符串
$redis -> append ( 'str' , '_123' ) ; //返回累加后的字符串长度8,此进str为 'test_123'

//setrange 部分替换操作
$redis -> setrange ( 'str' , 0 , 'abc' ) ; //返回3,参数2为0时等同于set操作
$redis -> setrange ( 'str' , 2 , 'cd' ) ; //返回4,表示从第2个字符后替换,这时'str'为'abcd'

//substr 部分获取操作
$redis -> substr ( 'str' , 0 , 2 ) ; //表示从第0个起,取到第2个字符,共3个,返回'abc'

//strlen 获取字符串长度
$redis -> strlen ( 'str' ) ; //返回4

//setbit/getbit 位存储和获取
$redis -> setbit ( 'binary' , 31 , 1 ) ; //表示在第31位存入1,这边可能会有大小端问题?不过没关系,getbit 应该不会有问题
$redis -> getbit ( 'binary' , 31 ) ; //返回1

//keys 模糊查找功能,支持*号以及?号(匹配一个字符)
$redis -> set ( 'foo1' , 123 ) ;
$redis -> set ( 'foo2' , 456 ) ;
$redis -> keys ( 'foo*' ) ; //返回foo1和foo2的array
$redis -> keys ( 'f?o?' ) ; //同上

//randomkey 随机返回一个key
$redis -> randomkey ( ) ; //可能是返回 'foo1'或者是'foo2'及其它任何一存在redis的key

//rename/renamenx 对key进行改名,所不同的是renamenx不允许改成已存在的key
$redis -> rename ( 'str' , 'str2' ) ; //把原先命名为'str'的key改成了'str2'

//expire 设置key-value的时效性,ttl 获取剩余有效期,persist 重新设置为永久存储
$redis -> expire ( 'foo' , 1 ) ; //设置有效期为1秒
$redis -> ttl ( 'foo' ) ; //返回有效期值1s
$redis -> expire ( 'foo' ) ; //取消expire行为

//dbsize 返回redis当前数据库的记录总数
$redis -> dbsize ( ) ;

/*
队列操作
*/

//rpush/rpushx 有序列表操作,从队列后插入元素
//lpush/lpushx 和rpush/rpushx的区别是插入到队列的头部,同上,'x'含义是只对已存在的key进行操作
$redis -> rpush ( 'fooList' , 'bar1' ) ; //返回一个列表的长度1
$redis -> lpush ( 'fooList' , 'bar0' ) ; //返回一个列表的长度2
$redis -> rpushx ( 'fooList' , 'bar2' ) ; //返回3,rpushx只对已存在的队列做添加,否则返回0
//llen返回当前列表长度
$redis -> llen ( 'fooList' ) ; //3

//lrange 返回队列中一个区间的元素
$redis -> lrange ( 'fooList' , 0 , 1 ) ; //返回数组包含第0个至第1个共2个元素
$redis -> lrange ( 'fooList' , 0 ,- 1 ) ; //返回第0个至倒数第一个,相当于返回所有元素,注意redis中很多时候会用到负数,下同

//lindex 返回指定顺序位置的list元素
$redis -> lindex ( 'fooList' , 1 ) ; //返回'bar1'

//lset 修改队列中指定位置的value
$redis -> lset ( 'fooList' , 1 , '123' ) ; //修改位置1的元素,返回true

//lrem 删除队列中左起指定数量的字符
$redis -> lrem ( 'fooList' , 1 , '_' ) ; //删除队列中左起(右起使用-1)1个字符'_'(若有)

//lpop/rpop 类似栈结构地弹出(并删除)最左或最右的一个元素
$redis -> lpop ( 'fooList' ) ; //'bar0'
$redis -> rpop ( 'fooList' ) ; //'bar2'

//ltrim 队列修改,保留左边起若干元素,其余删除
$redis -> ltrim ( 'fooList' , 0 , 1 ) ; //保留左边起第0个至第1个元素

//rpoplpush 从一个队列中pop出元素并push到另一个队列
$redis -> rpush ( 'list1' , 'ab0' ) ;
$redis -> rpush ( 'list1' , 'ab1' ) ;
$redis -> rpush ( 'list2' , 'ab2' ) ;
$redis -> rpush ( 'list2' , 'ab3' ) ;
$redis -> rpoplpush ( 'list1' , 'list2' ) ; //结果list1 =>array('ab0'),list2 =>array('ab1','ab2','ab3')
$redis -> rpoplpush ( 'list2' , 'list2' ) ; //也适用于同一个队列,把最后一个元素移到头部list2 =>array('ab3','ab1','ab2')

//linsert 在队列的中间指定元素前或后插入元素
$redis -> linsert ( 'list2' , 'before' , 'ab1' , '123' ) ; //表示在元素'ab1'之前插入'123'
$redis -> linsert ( 'list2' , 'after' , 'ab1' , '456' ) ; //表示在元素'ab1'之后插入'456'

&nbsp;

//blpop/brpop 阻塞并等待一个列队不为空时,再pop出最左或最右的一个元素(这个功能在php以外可以说非常好用)
//brpoplpush 同样是阻塞并等待操作,结果同rpoplpush一样
$redis -> blpop ( 'list3' , 10 ) ; //如果list3为空则一直等待,直到不为空时将第一元素弹出,10秒后超时

&nbsp;

/**
set表操作
*/

//sadd 增加元素,返回true,重复返回false
$redis -> sadd ( 'set1' , 'ab' ) ;
$redis -> sadd ( 'set1' , 'cd' ) ;
$redis -> sadd ( 'set1' , 'ef' ) ;

//srem 移除指定元素
$redis -> srem ( 'set1' , 'cd' ) ; //删除'cd'元素

//spop 弹出首元素
$redis -> spop ( 'set1' ) ;

//smove 移动当前set表的指定元素到另一个set表
$redis -> sadd ( 'set2' , '123' ) ;
$redis -> smove ( 'set1' , 'set2' , 'ab' ) ; //移动'set1'中的'ab'到'set2',返回true or false

//scard 返回当前set表元素个数
$redis -> scard ( 'set2' ) ; //2

//sismember 判断元素是否属于当前表
$redis -> sismember ( 'set2' , '123' ) ; //true or false

//smembers 返回当前表的所有元素
$redis -> smembers ( 'set2' ) ; //array('123','ab');

//sinter/sunion/sdiff 返回两个表中元素的交集/并集/补集
$redis -> sadd ( 'set1' , 'ab' ) ;
$redis -> sinter ( 'set2' , 'set1' ) ; //返回array('ab')

//sinterstore/sunionstore/sdiffstore 将两个表交集/并集/补集元素copy到第三个表中
$redis -> set ( 'foo' , 0 ) ;
$redis -> sinterstore ( 'foo' , 'set1' ) ; //这边等同于将'set1'的内容copy到'foo'中,并将'foo'转为set表
$redis -> sinterstore ( 'foo' , array ( 'set1' , 'set2' ) ) ; //将'set1'和'set2'中相同的元素copy到'foo'表中,覆盖'foo'原有内容

//srandmember 返回表中一个随机元素
$redis -> srandmember ( 'set1' ) ;

&nbsp;

/**
有序set表操作
*/

//sadd 增加元素,并设置序号,返回true,重复返回false
$redis -> zadd ( 'zset1' , 1 , 'ab' ) ;
$redis -> zadd ( 'zset1' , 2 , 'cd' ) ;
$redis -> zadd ( 'zset1' , 3 , 'ef' ) ;

//zincrby 对指定元素索引值的增减,改变元素排列次序
$redis -> zincrby ( 'zset1' , 10 , 'ab' ) ; //返回11

//zrem 移除指定元素
$redis -> zrem ( 'zset1' , 'ef' ) ; //true or false

//zrange 按位置次序返回表中指定区间的元素
$redis -> zrange ( 'zset1' , 0 , 1 ) ; //返回位置0和1之间(两个)的元素
$redis -> zrange ( 'zset1' , 0 ,- 1 ) ; //返回位置0和倒数第一个元素之间的元素(相当于所有元素)

//zrevrange 同上,返回表中指定区间的元素,按次序倒排
$redis -> zrevrange ( 'zset1' , 0 ,- 1 ) ; //元素顺序和zrange相反

//zrangebyscore/zrevrangebyscore 按顺序/降序返回表中指定索引区间的元素
$redis -> zadd ( 'zset1' , 3 , 'ef' ) ;
$redis -> zadd ( 'zset1' , 5 , 'gh' ) ;
$redis -> zrangebyscore ( 'zset1' , 2 , 9 ) ; //返回索引值2-9之间的元素 array('ef','gh')
//参数形式
$redis -> zrangebyscore ( 'zset1' , 2 , 9 , 'withscores' ) ; //返回索引值2-9之间的元素并包含索引值 array(array('ef',3),array('gh',5))
$redis -> zrangebyscore ( 'zset1' , 2 , 9 , array ( 'withscores' => true , 'limit' => array ( 1 , 2 ) ) ) ; //返回索引值2-9之间的元素,'withscores' =>true表示包含索引值; 'limit'=>array(1, 2),表示最多返回2条,结果为array(array('ef',3),array('gh',5))

//zunionstore/zinterstore 将多个表的并集/交集存入另一个表中
$redis -> zunionstore ( 'zset3' , array ( 'zset1' , 'zset2' , 'zset0' ) ) ; //将'zset1','zset2','zset0'的并集存入'zset3'
//其它参数
$redis -> zunionstore ( 'zset3' , array ( 'zset1' , 'zset2' ) , array ( 'weights' => array ( 5 , 0 ) ) ) ; //weights参数表示权重,其中表示并集后值大于5的元素排在前,大于0的排在后
$redis -> zunionstore ( 'zset3' , array ( 'zset1' , 'zset2' ) , array ( 'aggregate' => 'max' ) ) ; //'aggregate' => 'max'或'min'表示并集后相同的元素是取大值或是取小值

//zcount 统计一个索引区间的元素个数
$redis -> zcount ( 'zset1' , 3 , 5 ) ; //2
$redis -> zcount ( 'zset1' , '(3' , 5 ) ) ; //'(3'表示索引值在3-5之间但不含3,同理也可以使用'(5'表示上限为5但不含5

//zcard 统计元素个数
$redis -> zcard ( 'zset1' ) ; //4

//zscore 查询元素的索引
$redis -> zscore ( 'zset1' , 'ef' ) ; //3

//zremrangebyscore 删除一个索引区间的元素
$redis -> zremrangebyscore ( 'zset1' , 0 , 2 ) ; //删除索引在0-2之间的元素('ab','cd'),返回删除元素个数2

//zrank/zrevrank 返回元素所在表顺序/降序的位置(不是索引)
$redis -> zrank ( 'zset1' , 'ef' ) ; //返回0,因为它是第一个元素;zrevrank则返回1(最后一个)

//zremrangebyrank 删除表中指定位置区间的元素
$redis -> zremrangebyrank ( 'zset1' , 0 , 10 ) ; //删除位置为0-10的元素,返回删除的元素个数2

&nbsp;

/**
hash表操作
*/

//hset/hget 存取hash表的数据
$redis -> hset ( 'hash1' , 'key1' , 'v1' ) ; //将key为'key1' value为'v1'的元素存入hash1表
$redis -> hset ( 'hash1' , 'key2' , 'v2' ) ;
$redis -> hget ( 'hash1' , 'key1' ) ; //取出表'hash1'中的key 'key1'的值,返回'v1'

//hexists 返回hash表中的指定key是否存在
$redis -> hexists ( 'hash1' , 'key1' ) ; //true or false

//hdel 删除hash表中指定key的元素
$redis -> hdel ( 'hash1' , 'key2' ) ; //true or false

//hlen 返回hash表元素个数
$redis -> hlen ( 'hash1' ) ; //1

//hsetnx 增加一个元素,但不能重复
$redis -> hsetnx ( 'hash1' , 'key1' , 'v2' ) ; //false
$redis -> hsetnx ( 'hash1' , 'key2' , 'v2' ) ; //true

//hmset/hmget 存取多个元素到hash表
$redis -> hmset ( 'hash1' , array ( 'key3' => 'v3' , 'key4' => 'v4' ) ) ;
$redis -> hmget ( 'hash1' , array ( 'key3' , 'key4' ) ) ; //返回相应的值 array('v3','v4')

//hincrby 对指定key进行累加
$redis -> hincrby ( 'hash1' , 'key5' , 3 ) ; //返回3
$redis -> hincrby ( 'hash1' , 'key5' , 10 ) ; //返回13

//hkeys 返回hash表中的所有key
$redis -> hkeys ( 'hash1' ) ; //返回array('key1','key2','key3','key4','key5')

//hvals 返回hash表中的所有value
$redis -> hvals ( 'hash1' ) ; //返回array('v1','v2','v3','v4',13)

//hgetall 返回整个hash表元素
$redis -> hgetall ( 'hash1' ) ; //返回array('key1'=>'v1','key2'=>'v2','key3'=>'v3','key4'=>'v4','key5'=>13)

&nbsp;

/**
排序操作
*/

//sort 排序
$redis -> rpush ( 'tab' , 3 ) ;
$redis -> rpush ( 'tab' , 2 ) ;
$redis -> rpush ( 'tab' , 17 ) ;
$redis -> sort ( 'tab' ) ; //返回array(2,3,17)
//使用参数,可组合使用 array('sort' => 'desc','limit' => array(1, 2))
$redis -> sort ( 'tab' , array ( 'sort' => 'desc' ) ) ; //降序排列,返回array(17,3,2)
$redis -> sort ( 'tab' , array ( 'limit' => array ( 1 , 2 ) ) ) ; //返回顺序位置中1的元素2个(这里的2是指个数,而不是位置),返回array(3,17)
$redis -> sort ( 'tab' , array ( 'limit' => array ( 'alpha' => true ) ) ) ; //按首字符排序返回array(17,2,3),因为17的首字符是'1'所以排首位置
$redis -> sort ( 'tab' , array ( 'limit' => array ( 'store' => 'ordered' ) ) ) ; //表示永久性排序,返回元素个数
$redis -> sort ( 'tab' , array ( 'limit' => array ( 'get' => 'pre_*' ) ) ) ; //使用了通配符'*'过滤元素,表示只返回以'pre_'开头的元素

&nbsp;

/**
redis管理操作
*/

//select 指定要操作的数据库
$redis -> select ( 'mydb' ) ; //指定为mydb,不存在则创建

//flushdb 清空当前库
$redis -> flushdb ( ) ;

//move 移动当库的元素到其它库
$redis -> set ( 'foo' , 'bar' ) ;
$redis -> move ( 'foo' , 'mydb2' ) ; //若'mydb2'库存在

//info 显示服务当状态信息
$redis -> info ( ) ;

//slaveof 配置从服务器
$redis -> slaveof ( '127.0.0.1' , 80 ) ; //配置127.0.0.1端口80的服务器为从服务器
$redis -> slaveof ( ) ; //清除从服务器

//同步保存服务器数据到磁盘
$redis -> save ( ) ;
//异步保存服务器数据到磁盘
$redis -> bgsave ( ) ;
//??
$redis -> bgrewriteaof ( ) ;
//返回最后更新磁盘的时间
$redis -> lastsave ( ) ;

&nbsp;

//set/get多个key-value
$mkv = array (
'usr:0001' => 'First user' ,
'usr:0002' => 'Second user' ,
'usr:0003' => 'Third user'
) ;
$redis -> mset ( $mkv ) ; //存储多个key对应的value
$retval = $redis -> mget ( array_keys ( $mkv ) ) ; //获取多个key对应的value
print_r ( $retval ) ;

&nbsp;

//批量操作
$replies = $redis -> pipeline ( function ( $pipe ) {
$pipe -> ping ( ) ;
$pipe -> flushdb ( ) ;
$pipe -> incrby ( 'counter' , 10 ) ; //增量操作
$pipe -> incrby ( 'counter' , 30 ) ;
$pipe -> exists ( 'counter' ) ;
$pipe -> get ( 'counter' ) ;
$pipe -> mget ( 'does_not_exist' , 'counter' ) ;
} ) ;
print_r ( $replies ) ;

&nbsp;

&nbsp;

//CAS,事务性操作

function zpop ( $client , $zsetKey ) {
$element = null ;
$options = array (
'cas' => true , // Initialize with support for CAS operations
'watch' => $zsetKey , // Key that needs to be WATCHed to detect changes
'retry' => 3 , // Number of retries on aborted transactions, after
// which the client bails out with an exception.
) ;

$txReply = $client -> multiExec ( $options , function ( $tx )
use ( $zsetKey , & $element ) {
@ list ( $element ) = $tx -> zrange ( $zsetKey , 0 , 0 ) ;
if ( isset ( $element ) ) {
$tx -> multi ( ) ; // With CAS, MULTI *must* be explicitly invoked.
$tx -> zrem ( $zsetKey , $element ) ;
}
} ) ;
return $element ;
}
$zpopped = zpop ( $redis , 'zset' ) ;
echo isset ( $zpopped ) ? "ZPOPed $zpopped" : "Nothing to ZPOP!" , "\n" ;

&nbsp;

//对存取的key加前缀,如: 'nrk:'
$redis -> getProfile ( ) -> setPreprocessor ( new KeyPrefixPreprocessor ( 'nrk:' ) ) ;

&nbsp;

&nbsp;

&nbsp;

//分布式存储的一些方法
$multiple_servers = array (
array (
'host' => '127.0.0.1' ,
'port' => 6379 ,
'database' => 15 ,
'alias' => 'first' ,
) ,
array (
'host' => '127.0.0.1' ,
'port' => 6380 ,
'database' => 15 ,
'alias' => 'second' ,
) ,
) ;

&nbsp;

use Predis\Distribution\IDistributionStrategy ;

class NaiveDistributionStrategy implements IDistributionStrategy {
private $_nodes , $_nodesCount ;

public function __constructor ( ) {
$this ->_nodes = array ( ) ;
$this ->_nodesCount = 0 ;
}

public function add ( $node , $weight = null ) {
$this ->_nodes [ ] = $node ;
$this ->_nodesCount ++;
}

public function remove ( $node ) {
$this ->_nodes = array_filter ( $this ->_nodes , function ( $n ) use ( $node ) {
return $n !== $node ;
} ) ;
$this ->_nodesCount = count ( $this ->_nodes ) ;
}

public function get ( $key ) {
$count = $this ->_nodesCount ;
if ( $count === 0 ) {
throw new RuntimeException ( 'No connections' ) ;
}
return $this ->_nodes [ $count > 1 ? abs ( crc32 ( $key ) % $count ) : 0 ] ;
}

public function generateKey ( $value ) {
return crc32 ( $value ) ;
}
}

//配置键分布策略
$options = array (
'key_distribution' => new NaiveDistributionStrategy ( ) ,
) ;

$redis = new Predis\Client ( $multiple_servers , $options ) ;

for ( $i = 0 ; $i set ( "key:$i" , str_pad ( $i , 4 , '0' , 0 ) ) ;
$redis -> get ( "key:$i" ) ;
}

$server1 = $redis -> getClientFor ( 'first' ) -> info ( ) ;
$server2 = $redis -> getClientFor ( 'second' ) -> info ( ) ;

printf ( "Server '%s' has %d keys while server '%s' has %d keys.\n" ,
'first' , $server1 [ 'db15' ] [ 'keys' ] , 'second' , $server2 [ 'db15' ] [ 'keys' ]
) ;

git add , git commit 添加错文件 撤销

1. git add 添加 多余文件
这样的错误是由于, 有的时候 可能

git add . (空格+ 点) 表示当前目录所有文件,不小心就会提交其他文件

git add 如果添加了错误的文件的话

撤销操作

git status 先看一下add 中的文件
git reset HEAD 如果后面什么都不跟的话 就是上一次add 里面的全部撤销了
git reset HEAD XXX/XXX/XXX.java 就是对某个文件进行撤销了

2. git commit 错误

如果不小心 弄错了 git add后 , 又 git commit 了。
先使用
git log 查看节点
commit xxxxxxxxxxxxxxxxxxxxxxxxxx
Merge:
Author:
Date:

然后
git reset commit_id

over

PS:还没有 push 也就是 repo upload 的时候

git reset commit_id (回退到上一个 提交的节点 代码还是原来你修改的)
git reset –hard commit_id (回退到上一个commit节点, 代码也发生了改变,变成上一次的)

3.如果要是 提交了以后,可以使用 git revert

还原已经提交的修改
此次操作之前和之后的commit和history都会保留,并且把这次撤销作为一次最新的提交
git revert HEAD 撤销前一次 commit
git revert HEAD^ 撤销前前一次 commit
git revert commit-id (撤销指定的版本,撤销也会作为一次提交进行保存)
git revert是提交一个新的版本,将需要revert的版本的内容再反向修改回去,版本会递增,不影响之前提交的内容。

http://blog.csdn.net/kongbaidepao/article/details/52253774

CentOS7使用firewalld打开关闭防火墙与端口

1、firewalld的基本使用
启动: systemctl start firewalld
查看状态: systemctl status firewalld
停止: systemctl disable firewalld
禁用: systemctl stop firewalld
2.systemctl是CentOS7的服务管理工具中主要的工具,它融合之前service和chkconfig的功能于一体。

启动一个服务:systemctl start firewalld.service
关闭一个服务:systemctl stop firewalld.service
重启一个服务:systemctl restart firewalld.service
显示一个服务的状态:systemctl status firewalld.service
在开机时启用一个服务:systemctl enable firewalld.service
在开机时禁用一个服务:systemctl disable firewalld.service
查看服务是否开机启动:systemctl is-enabled firewalld.service
查看已启动的服务列表:systemctl list-unit-files|grep enabled
查看启动失败的服务列表:systemctl –failed

3.配置firewalld-cmd

查看版本: firewall-cmd –version
查看帮助: firewall-cmd –help
显示状态: firewall-cmd –state
查看所有打开的端口: firewall-cmd –zone=public –list-ports
更新防火墙规则: firewall-cmd –reload
查看区域信息:  firewall-cmd –get-active-zones
查看指定接口所属区域: firewall-cmd –get-zone-of-interface=eth0
拒绝所有包:firewall-cmd –panic-on
取消拒绝状态: firewall-cmd –panic-off
查看是否拒绝: firewall-cmd –query-panic
那怎么开启一个端口呢
添加
firewall-cmd –zone=public –add-port=80/tcp –permanent    (–permanent永久生效,没有此参数重启后失效)
重新载入
firewall-cmd –reload
查看
firewall-cmd –zone= public –query-port=80/tcp
删除
firewall-cmd –zone= public –remove-port=80/tcp –permanent

直接命令:service firewalld stop

 

1. Disable Firewalld Service.

[root@rhel-centos7-tejas-barot-linux ~]# systemctl mask firewalld

2. Stop Firewalld Service.

[root@rhel-centos7-tejas-barot-linux ~]# systemctl stop firewalld

3. Install iptables service related packages.

[root@rhel-centos7-tejas-barot-linux ~]# yum -y install iptables-services

4. Make sure service starts at boot:

[root@rhel-centos7-tejas-barot-linux ~]# systemctl enable iptables

# If you do not want ip6tables, You can skip following command.

[root@rhel-centos7-tejas-barot-linux ~]# systemctl enable ip6tables

5. Now, Finally Let’s start the iptables services.

[root@rhel-centos7-tejas-barot-linux ~]# systemctl start iptables

# If you do not want ip6tables, You can skip following command.

[root@rhel-centos7-tejas-barot-linux ~]# systemctl start ip6tables

Firewalld Service is now disabled and stop, You can use iptables.