记一下 openwrt 可能忘记的常用命令

将 /dev/sda1 分区挂载为 swap 交换区:

1
2
mkswap /dev/sda1
swapon /dev/sda1

挂载 vfat:

1
2
3
4
opkg install kmod-fs-vfat // fat,fat32
opkg install kmod-nls-utf8 kmod-nls-cp437 kmod-nls-iso8859-1 // 文件系统的语言支持
mkdir sda1
mount -t vfat /dev/sda1 sda1

挂载 ntfs:

1
2
3
opkg install kmod-fuse ntfs-3g
mkdir sda1
ntfs-3g /dev/sda1 sda1

格式化分区:

1
2
opkg install e2fsprogs
mkfs.ext4 /dev/sda1

支持 extroot:

1
2
opkg install block-mount
reboot

复制flash根分区文件到外部存储

1
2
3
4
5
6
mkdir /mnt/sda1
mount /dev/sda1 /mnt/sda1
mkdir -p /tmp/cproot
mount --bind / /tmp/cproot/
tar -C /tmp/cproot/ -cvf - . | tar -C /mnt/sda1 -xf -
umount /dev/sda1

使用 HTML5 WebSocket 构建实时 Web 应用

作为下一代的 Web 标准,HTML5 拥有许多引人注目的新特性,如 Canvas、本地存储、多媒体编程接口、WebSocket 等等。这其中有“Web 的 TCP ”之称的 WebSocket 格外吸引开发人员的注意。WebSocket 的出现使得浏览器提供对 Socket 的支持成为可能,从而在浏览器和服务器之间提供了一个基于 TCP 连接的双向通道。Web 开发人员可以非常方便地使用 WebSocket 构建实时 web 应用,开发人员的手中从此又多了一柄神兵利器。本文首先介绍 HTML5 WebSocket 的基本概念以及这个规范试图解决的问题,然后介绍 WebSocket 的基本原理和编程接口。接下来会通过一个简单案例来示范怎样实现一个 WebSocket 应用,并且展示 WebSocket 如何在功能强大和编程简单易用上达到的完美统一。最后介绍了目前主流浏览器对 WebSocket 支持的状况、局限性以及未来的展望。

实时 Web 应用的窘境

Web 应用的信息交互过程通常是客户端通过浏览器发出一个请求,服务器端接收和审核完请求后进行处理并返回结果给客户端,然后客户端浏览器将信息呈现出来,这种机制对于信息变化不是特别频繁的应用尚能相安无事,但是对于那些实时要求比较高的应用来说,比如说在线游戏、在线证券、设备监控、新闻在线播报、RSS 订阅推送等等,当客户端浏览器准备呈现这些信息的时候,这些信息在服务器端可能已经过时了。所以保持客户端和服务器端的信息同步是实时 Web 应用的关键要素,对 Web 开发人员来说也是一个难题。在 WebSocket 规范出来之前,开发人员想实现这些实时的 Web 应用,不得不采用一些折衷的方案,其中最常用的就是轮询 (Polling) 和 Comet 技术,而 Comet 技术实际上是轮询技术的改进,又可细分为两种实现方式,一种是长轮询机制,一种称为流技术。下面我们简单介绍一下这几种技术:
轮询:
这是最早的一种实现实时 Web 应用的方案。客户端以一定的时间间隔向服务端发出请求,以频繁请求的方式来保持客户端和服务器端的同步。这种同步方案的最大问题是,当客户端以固定频率向服务器发起请求的时候,服务器端的数据可能并没有更新,这样会带来很多无谓的网络传输,所以这是一种非常低效的实时方案。
长轮询:
长轮询是对定时轮询的改进和提高,目地是为了降低无效的网络传输。当服务器端没有数据更新的时候,连接会保持一段时间周期直到数据或状态改变或者时间过期,通过这种机制来减少无效的客户端和服务器间的交互。当然,如果服务端的数据变更非常频繁的话,这种机制和定时轮询比较起来没有本质上的性能的提高。
流:
流技术方案通常就是在客户端的页面使用一个隐藏的窗口向服务端发出一个长连接的请求。服务器端接到这个请求后作出回应并不断更新连接状态以保证客户端和服务器端的连接不过期。通过这种机制可以将服务器端的信息源源不断地推向客户端。这种机制在用户体验上有一点问题,需要针对不同的浏览器设计不同的方案来改进用户体验,同时这种机制在并发比较大的情况下,对服务器端的资源是一个极大的考验。
综合这几种方案,您会发现这些目前我们所使用的所谓的实时技术并不是真正的实时技术,它们只是在用 Ajax 方式来模拟实时的效果,在每次客户端和服务器端交互的时候都是一次 HTTP 的请求和应答的过程,而每一次的 HTTP 请求和应答都带有完整的 HTTP 头信息,这就增加了每次传输的数据量,而且这些方案中客户端和服务器端的编程实现都比较复杂,在实际的应用中,为了模拟比较真实的实时效果,开发人员往往需要构造两个 HTTP 连接来模拟客户端和服务器之间的双向通讯,一个连接用来处理客户端到服务器端的数据传输,一个连接用来处理服务器端到客户端的数据传输,这不可避免地增加了编程实现的复杂度,也增加了服务器端的负载,制约了应用系统的扩展性。


WebSocket 的拯救

HTML5 WebSocket 设计出来的目的就是要取代轮询和 Comet 技术,使客户端浏览器具备像 C/S 架构下桌面系统的实时通讯能力。 浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。因为 WebSocket 连接本质上就是一个 TCP 连接,所以在数据传输的稳定性和数据传输量的大小方面,和轮询以及 Comet 技术比较,具有很大的性能优势。Websocket.org 网站对传统的轮询方式和 WebSocket 调用方式作了一个详细的测试和比较,将一个简单的 Web 应用分别用轮询方式和 WebSocket 方式来实现,在这里引用一下他们的测试结果图:

图 1. 轮询和 WebSocket 实现方式的网络负载对比图

图 1. 轮询和 WebSocket 实现方式的网络负载对比图
通过这张图可以清楚的看出,在流量和负载增大的情况下,WebSocket 方案相比传统的 Ajax 轮询方案有极大的性能优势。这也是为什么我们认为 WebSocket 是未来实时 Web 应用的首选方案的原因。


WebSocket 规范

WebSocket 协议本质上是一个基于 TCP 的协议。为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息”Upgrade: WebSocket”表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
下面我们来详细介绍一下 WebSocket 规范,由于这个规范目前还是处于草案阶段,版本的变化比较快,我们选择 draft-hixie-thewebsocketprotocol-76版本来描述 WebSocket 协议。因为这个版本目前在一些主流的浏览器上比如 Chrome,、FireFox、Opera 上都得到比较好的支持,您如果参照的是新一些的版本话,内容可能会略有差别。
一个典型的 WebSocket 发起请求和得到响应的例子看起来如下:

清单 1. WebSocket 握手协议

客户端到服务端:

1
2
3
4
5
6
7
8
GET /demo HTTP/1.1 
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Upgrade: WebSocket
Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5
Origin: http://example.com
[8-byte security key]

服务端到客户端:

1
2
3
4
5
6
HTTP/1.1 101 WebSocket Protocol Handshake 
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://example.com
WebSocket-Location: ws://example.com/demo
[16-byte hash response]

这些请求和通常的 HTTP 请求很相似,但是其中有些内容是和 WebSocket 协议密切相关的。我们需要简单介绍一下这些请求和应答信息,”Upgrade:WebSocket”表示这是一个特殊的 HTTP 请求,请求的目的就是要将客户端和服务器端的通讯协议从 HTTP 协议升级到 WebSocket 协议。从客户端到服务器端请求的信息里包含有”Sec-WebSocket-Key1”、“Sec-WebSocket-Key2”和”[8-byte securitykey]”这样的头信息。这是客户端浏览器需要向服务器端提供的握手信息,服务器端解析这些头信息,并在握手的过程中依据这些信息生成一个 16 位的安全密钥并返回给客户端,以表明服务器端获取了客户端的请求,同意创建 WebSocket 连接。一旦连接建立,客户端和服务器端就可以通过这个通道双向传输数据了。
在实际的开发过程中,为了使用 WebSocket 接口构建 Web 应用,我们首先需要构建一个实现了 WebSocket 规范的服务器,服务器端的实现不受平台和开发语言的限制,只需要遵从 WebSocket 规范即可,目前已经出现了一些比较成熟的 WebSocket 服务器端实现,比如:

  • Kaazing WebSocket Gateway — 一个 Java 实现的 WebSocket Server
  • mod_pywebsocket — 一个 Python 实现的 WebSocket Server
  • Netty —一个 Java 实现的网络框架其中包括了对 WebSocket 的支持
  • node.js —一个 Server 端的 JavaScript 框架提供了对 WebSocket 的支持
    如果以上的 WebSocket 服务端实现还不能满足您的业务需求的话,开发人员完全可以根据 WebSocket 规范自己实现一个服务器。在“WebSocket 实战”这一节,我们将使用 Microsoft .NET 平台上的 C# 语言来打造一个简单的 WebSocket 服务器,继而构建一个简单的实时聊天系统。

WebSocket JavaScript 接口

上一节介绍了 WebSocket 规范,其中主要介绍了 WebSocket 的握手协议。握手协议通常是我们在构建 WebSocket 服务器端的实现和提供浏览器的 WebSocket 支持时需要考虑的问题,而针对 Web 开发人员的 WebSocket JavaScript 客户端接口是非常简单的,以下是 WebSocket JavaScript 接口的定义:

清单 2. WebSocket JavaScript 定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Constructor(in DOMString url, in optional DOMString protocol)] 
interface WebSocket {
readonly attribute DOMString URL;
// ready state
const unsigned short CONNECTING = 0;
const unsigned short OPEN = 1;
const unsigned short CLOSED = 2;
readonly attribute unsigned short readyState;
readonly attribute unsigned long bufferedAmount;
//networking
attribute Function onopen;
attribute Function onmessage;
attribute Function onclose;
boolean send(in DOMString data);
void close();
};
WebSocket implements EventTarget;

其中 URL 属性代表 WebSocket 服务器的网络地址,协议通常是”ws”,send 方法就是发送数据到服务器端,close 方法就是关闭连接。除了这些方法,还有一些很重要的事件:onopen,onmessage,onerror 以及 onclose。我们借用 Nettuts 网站上的一张图来形象的展示一下 WebSocket 接口:

图 2. WebSocket JavaScript 接口

图 2. WebSocket JavaScript 接口
下面是一段简单的 JavaScript 代码展示了怎样建立 WebSocket 连接和获取数据:

清单 3. 建立 WebSocket 连接的实例 JavaScript 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var  wsServer = 'ws://localhost:8888/Demo'; 
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) { onOpen(evt) };
websocket.onclose = function (evt) { onClose(evt) };
websocket.onmessage = function (evt) { onMessage(evt) };
websocket.onerror = function (evt) { onError(evt) };
function onOpen(evt) {
console.log("Connected to WebSocket server.");
}
function onClose(evt) {
console.log("Disconnected");
}
function onMessage(evt) {
console.log('Retrieved data from server: ' + evt.data);
}
function onError(evt) {
console.log('Error occured: ' + evt.data);
}

浏览器支持

下面是主流浏览器对 HTML5 WebSocket 的支持情况:

浏览器支持情况









Chrome
Supported in version 4+
Firefox
Supported in version 4+
Internet Explorer
Supported in version 10+
Opera
Supported in version 10+
Safari
Supported in version 5+

WebSocket 实战

这一节里我们用一个案例来演示怎么使用 WebSocket 构建一个实时的 Web 应用。这是一个简单的实时多人聊天系统,包括客户端和服务端的实现。客户端通过浏览器向聊天服务器发起请求,服务器端解析客户端发出的握手请求并产生应答信息返回给客户端,从而在客户端和服务器之间建立连接通道。服务器支持广播功能,每个聊天用户发送的信息会实时的发送给所有的用户,当用户退出聊天室时,服务器端需要清理相应用户的连接信息,避免资源的泄漏。以下我们分别从服务器端和客户端来演示这个 Web 聊天系统的实现,在实现方式上我们采用了 C# 语言来实现 WebSocket 服务器,而客户端是一个运行在浏览器里的 HTML 文件。

WebSocket 服务器端实现

这个聊天服务器的实现和基于套接字的网络应用程序非常类似,首先是服务器端要启动一个套接字监听来自客户端的连接请求,关键的区别在于 WebSocket 服务器需要解析客户端的 WebSocket 握手信息,并根据 WebSocket 规范的要求产生相应的应答信息。一旦 WebSocket 连接通道建立以后,客户端和服务器端的交互就和普通的套接字网络应用程序是一样的了。所以在下面的关于 WebSocket 服务器端实现的描述中,我们主要阐述 WebSocket 服务器怎样处理 WebSocket 握手信息,至于 WebSocket 监听端口的建立,套接字信息流的读取和写入,都是一些常用的套接字编程的方式,我们就不多做解释了,您可以自行参阅本文的附件源代码文件。
在描述 WebSocket 规范时提到,一个典型的 WebSocket Upgrade 信息如下所示:

1
2
3
4
5
6
7
8
GET /demo HTTP/1.1 
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Upgrade: WebSocket
Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5
Origin: http://example.com
[8-byte security key]

其中 Sec-WebSocket-Key1,Sec-WebSocket-Key2 和 [8-byte security key] 这几个头信息是 WebSocket 服务器用来生成应答信息的来源,依据 draft-hixie-thewebsocketprotocol-76 草案的定义,WebSocket 服务器基于以下的算法来产生正确的应答信息:

  1. 逐个字符读取 Sec-WebSocket-Key1 头信息中的值,将数值型字符连接到一起放到一个临时字符串里,同时统计所有空格的数量;
  2. 将在第 1 步里生成的数字字符串转换成一个整型数字,然后除以第 1 步里统计出来的空格数量,将得到的浮点数转换成整数型;
  3. 将第 2 步里生成的整型值转换为符合网络传输的网络字节数组;
  4. 对 Sec-WebSocket-Key2 头信息同样进行第 1 到第 3 步的操作,得到另外一个网络字节数组;
  5. 将 [8-byte security key] 和在第 3,第 4 步里生成的网络字节数组合并成一个 16 字节的数组;
  6. 对第 5 步生成的字节数组使用 MD5 算法生成一个哈希值,这个哈希值就作为安全密钥返回给客户端,以表明服务器端获取了客户端的请求,同意创建 WebSocket 连接
    至此,客户端和服务器的 WebSocket 握手就完成了,WebSocket 通道也建立起来了。下面首先介绍一下服务器端实现是如何根据用户传递的握手信息来生成网络字节数组的。.NET 平台提供了很方便的对字符串,数值以及数组操作的函数,所以生成字节数组的方法还是非常简单明了的,代码如下:
清单 4. 生成网络字节数组的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   private byte[]   BuildServerPartialKey(string clientKey) 
{
string partialServerKey = "";
byte[] currentKey;
int spacesNum = 0;
char[] keyChars = clientKey.ToCharArray();
foreach (char currentChar in keyChars)
{
if (char.IsDigit(currentChar)) partialServerKey += currentChar;
if (char.IsWhiteSpace(currentChar)) spacesNum++;
}
try
{
currentKey = BitConverter.GetBytes((int)(Int64.Parse(partialServerKey)
/ spacesNum));
if (BitConverter.IsLittleEndian) Array.Reverse(currentKey);
}
catch
{
if (currentKey!= null) Array.Clear(currentKey, 0, currentKey.Length);
}
return currentKey;
}

得到网络字节数组以后,服务器端生成 16 位安全密钥的方法如下所示:

清单 5. 生成 16 位安全密钥的代码
1
2
3
4
5
6
7
8
9
10
11
private byte[] BuildCompleteServerKey(byte[] serverKey1, byte[] serverKey2, 
byte[] last8Bytes)
{
byte[] concatenatedKeys = new byte[16];
Array.Copy(serverKey1, 0, concatenatedKeys, 0, 4);
Array.Copy(serverKey2, 0, concatenatedKeys, 4, 4);
Array.Copy(last8Bytes, 0, concatenatedKeys, 8, 8);
System.Security.Cryptography.MD5 MD5Service =
System.Security.Cryptography.MD5.Create();
return MD5Service.ComputeHash(concatenatedKeys);
}

整个实现是非常简单明了的,就是将生成的网络字节数组和客户端提交的头信息里的 [8-byte security key] 合并成一个 16 位字节数组并用 MD5 算法加密,然后将生成的安全密钥作为应答信息返回给客户端,双方的 WebSocekt 连接通道就建立起来了。实现了 WebSocket 握手信息的处理逻辑,一个具有基本功能的 WebSocket 服务器就完成了。整个 WebSocket 服务器由两个核心类构成,一个是 WebSocketServer,另外一个是 SocketConnection,出于篇幅的考虑,我们不介绍每个类的属性和方法了,文章的附件会给出详细的源代码,有兴趣的读者可以参考。
服务器刚启动时的画面如下:

图 3. WebSocket 服务器刚启动的画面

图 3. WebSocket 服务器刚启动的画面
客户端可以依据这个信息填写聊天服务器的连接地址,当有客户端连接到聊天服务器上时,服务器会打印出客户端和服务器的握手信息,每个客户的聊天信息也会显示在服务器的界面上,运行中的聊天服务器的界面如下:

图 4. 有客户端连接到 WebSocket 服务器的

图 4. 有客户端连接到 WebSocket 服务器的
以上我们简单描述了实现一个 WebSocket 服务器的最基本的要素,下一节我们会描述客户端的实现。

客户端实现

客户端的实现相对于服务器端的实现来说要简单得多了,我们只需要发挥想象去设计 HTML 用户界面,然后呼叫 WebSocket JavaScript 接口来和 WebSocket 服务器端来交互就可以了。当然别忘了使用一个支持 HTML5 和 WebSocket 的浏览器,在笔者写这篇文章的时候使用的浏览器是 Firefox。客户端的页面结构是非常简洁的,初始运行界面如下:

图 5. 聊天室客户端初始页面

图 5. 聊天室客户端初始页面
当页面初次加载的时候,首先会检测当前的浏览器是否支持 WebSocket 并给出相应的提示信息。用户按下连接按钮时,页面会初始化一个到聊天服务器的 WebSocekt 连接,初始化成功以后,页面会加载对应的 WebSocket 事件处理函数,客户端 JavaScript 代码如下所示:

清单 6. 初始化客户端 WebSocket 对象的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function ToggleConnectionClicked() {
if (SocketCreated && (ws.readyState == 0 || ws.readyState == 1)) {
ws.close();
} else {
Log("准备连接到聊天服务器 ...");
try {
ws =
new WebSocket("ws://" + document.getElementById("Connection").value);
SocketCreated = true;
} catch (ex) {
Log(ex, "ERROR");
return;
}
document.getElementById("ToggleConnection").innerHTML = "断开";
ws.onopen = WSonOpen;
ws.onmessage = WSonMessage;
ws.onclose = WSonClose;
ws.onerror = WSonError;
}
};

function WSonOpen() {
Log("连接已经建立。", "OK");
$("#SendDataContainer").show("slow");
};

function WSonMessage(event) {
Log(event.data);
};

function WSonClose() {
Log("连接关闭。", "ERROR");
document.getElementById("ToggleConnection").innerHTML = "连接";
$("#SendDataContainer").hide("slow");
};


function WSonError() {
Log("WebSocket错误。", "ERROR");
};

当用户按下发送按钮,客户端会调用WebSocket对象向服务器发送信息,并且这个消息会广播给所有的用户,实现代码如下所示:

1
2
3
4
5
6
7
8
function SendDataClicked()
{
if (document.getElementById("DataToSend").value != "") {
ws.send(document.getElementById("txtName").value + "说 :\"" +
document.getElementById("DataToSend").value + "\"");
document.getElementById("DataToSend").value = "";
}
};

如果有多个用户登录到聊天服务器,客户端页面的运行效果如下所示:

图 6. 聊天客户端运行页面

图 6. 聊天客户端运行页面
至此我们已经完成了一个完整的 WebSocket 客户端实现,用户可以体验一下这个聊天室的简单和快捷,完全不用考虑页面的刷新和繁琐的 Ajax 调用,享受桌面程序的用户体验。WebSocket 的强大和易用可见一斑,您完全可以在这个基础上加入更多的功能,设计更加漂亮的用户界面,切身体验 WebSocket 的震撼力。完整的客户端代码请参阅附件提供的源代码。


WebSocket 的局限性

WebSocket 的优点已经列举得很多了,但是作为一个正在演变中的 Web 规范,我们也要看到目前用 Websocket 构建应用程序的一些风险。首先,WebSocket 规范目前还处于草案阶段,也就是它的规范和 API 还是有变动的可能,另外的一个风险就是微软的 IE 作为占市场份额最大的浏览器,和其他的主流浏览器相比,对 HTML5 的支持是比较差的,这是我们在构建企业级的 Web 应用的时候必须要考虑的一个问题。


总结

本文介绍了 HTML5 WebSocket 的横空出世以及它尝试解决的的问题,然后介绍了 WebSocket 规范和 WebSocket 接口,以及和传统的实时技术相比在性能上的优势,并且演示了怎样使用 WebSocket 构建一个实时的 Web 应用,最后我们介绍了当前的主流浏览器对 HTML5 的支持情况和 WebSocket 的局限性。不过,我们应该看到,尽管 HTML5 WebSocket 目前还有一些局限性,但是已经是大势所趋,微软也明确表达了未来对 HTML5 的支持,而且这些支持我们可以在 Windows 8 和 IE10 里看到,我们也在各种移动设备,平板电脑上看到了 HTML5 和 WebSocket 的身影。WebSocket 将会成为未来开发实时 Web 应用的生力军应该是毫无悬念的了,作为 Web 开发人员,关注 HTML5,关注 WebSocket 也应该提上日程了,否则我们在新一轮的软件革新的浪潮中只能做壁上观了。

下载示例代码:new-source

转载自 http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/

另祝各位元旦快乐!

iptables 开启80端口

经常使用CentOS的朋友,可能会遇到和我一样的问题。最近在Linux CentOS防火墙下安装配置 ORACLE
数据库的时候,总显示因为网络端口而导致的EM安装失败,遂打算先关闭一下CentOS防火墙。偶然看到CentOS防火墙的配置操作说明,感觉不错。执行”setup”命令启动文字模式配置实用程序,在”选择一种工具”中选择”防火墙配置”,然后选择”运行工具”按钮,出现CentOS防火墙配置界面,
将”安全级别”设为”禁用”,然后选择”确定”即可.

这样重启计算机后,CentOS防火墙默认已经开放了80和22端口

简介:CentOS是Linux家族的一个分支。

CentOS防火墙在虚拟机的CENTOS装好APACHE不能用,郁闷,解决方法如下

1
2
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT 
/sbin/iptables -I INPUT -p tcp --dport 22 -j ACCEPT

然后保存:

1
/etc/rc.d/init.d/iptables save

centos 5.3,5.4以上的版本需要用

1
service iptables save

来实现保存到配置文件。
这样重启计算机后,CentOS防火墙默认已经开放了80和22端口。

这里应该也可以不重启计算机:

1
/etc/init.d/iptables restart

CentOS防火墙的关闭,关闭其服务即可:
查看CentOS防火墙信息:/etc/init.d/iptables status

关闭CentOS防火墙服务:/etc/init.d/iptables stop

永久关闭?不知道怎么个永久法:chkconfig –level 35 iptables off

上面的内容是针对老版本的centos,下面的内容是基于新版本。

1
iptables -P INPUT DROP

这样就拒绝所有访问 CentOS 5.3 本系统数据,除了 Chain RH-Firewall-1-INPUT (2 references) 的规则外 , 呵呵。

用命令配置了 iptables 一定还要 service iptables save 才能保存到配置文件。
cat /etc/sysconfig/iptables 可以查看 防火墙 iptables 配置文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Generated by iptables-save v1.3.5 on Sat Apr 14 07:51:07 2001 
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1513:149055]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p esp -j ACCEPT
-A RH-Firewall-1-INPUT -p ah -j ACCEPT
-A RH-Firewall-1-INPUT -d 224.0.0.251 -p udp -m udp --dport 5353 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT
# Completed on Sat Apr 14 07:51:07 2001

另外补充:
CentOS 防火墙配置 80端口
看了好几个页面内容都有错,下面是正确方法:

1
2
#/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT 
#/sbin/iptables -I INPUT -p tcp --dport 22 -j ACCEPT

然后保存:

1
#/etc/rc.d/init.d/iptables save

再查看是否已经有了:

1
2
3
4
5
6
7
8
9
10
11
[root@vcentos ~]# /etc/init.d/iptables status 
Table: filter
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:80
2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
3 RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0

Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0

  • 设置iptables为自动启动
    1
    chkconfig --level 2345 iptables on

可能因为大家使用的版本不一,所有使用方法也略有不同。

如果需要远程管理mysql,则使用以下指令临时打开,用完后关闭

  • 打开指令

    1
    iptables -A INPUT -p tcp -s xxx.xxx.xxx.xxx --dport 3306 -j ACCEPT
  • 关闭指令

    1
    iptables -D INPUT -p tcp -s xxx.xxx.xxx.xxx --dport 3306 -j ACCEPT

转载自 http://www.blogjava.net/Alpha/archive/2012/09/17/387950.html

PHP 快速读取大文件

最近想分析一下iis的日志,由于日志文件800M等大文件,所以怎样使用PHP快速读取成了问题!首先排除了file,因为加载太慢,内存溢出!
后来考虑用指针fgets,但是读取还是有点慢,如果只读取1000条以内的数据还是可以接受的
最后试用了PHP的stream_get_line函数 ,读取快速,读取50万条数据大文件,大概需要20秒左右的时间!例子代码如下

1
2
3
4
5
6
7
8
$fp = fopen('./iis.log', 'r'); //文件
while (!feof($fp)) {
//for($j=1;$j<=1000;$j++) { //读取下面的1000行并存储到数组中
$logarray[] = stream_get_line($fp, 65535, "\n");
// break;
// }

}

转载自 http://www.wenlingnet.com/index.php/172/

P.S. 说实话这个是挺快的,就是没法指定起始位置
QQ图片20141216215656

脚上的泡都是自己走的

早上爸爸送妹妹去上课,我正好去超市买东西,大家一起走,回家的路上,碰上以前同学在等公交,爸爸说要捎上她,我拒绝了。爸爸有点不高兴的说“都认识人,捎一段给她送家去,她自己从公交站走到家得走挺老远的呢!”我就跟爸爸说了我们小时候的一件事,我们一起上学的时候,有一次连着下雨好多天,我几双鞋都湿了,怎么都晾不干,我妈找出一双旧鞋让我穿。这位同学看到之后说“这鞋是你捡的吧?我前天刚扔垃圾桶的!”我说“这鞋我的。”她坚持“我前天扔垃圾桶的,就是这双!”无论我怎么解释,她就说这是她扔的,还找来跟她不错的同学作证!说我这鞋是捡她的,连着好多天,不停的说我从垃圾桶捡了她的鞋。把我烦的不行,回家我让我妈把我的鞋烤干了,把那双旧鞋给了她。我以为这事完了,没想到她就自以为她说的是对的,到处跟人说我捡她旧鞋。一连说了好几年。从那儿以后只要看见她,我就想起这事,我爸一说要捎着她,我果断就拒绝了。

无独有偶,我高中同学里有个类似的事,同学A没事就欺负同学B,比如冬天半夜趁着同学B上厕所,把宿舍门锁上,同学B在门口敲门不让其他人开,同学B只好去找宿管老师,可还是冻两小时发烧了。再比如大家一起去洗澡,他把同学B的衣服带走,让同学B找不到衣服。再比如挑拨别的同学打同学B,等等损人不利己的事。大家毕业以后,各奔东西,巧的是,同学B开了公司,当了老板,同学A去他公司面试,同学B找借口没有收同学A。同学A在我们的同学群里谴责同学B,不讲同学情谊,一点也没有人情味。

最近陪爸妈看电视,有个大叔家里拆迁,他回家要分家产,父母和兄弟姐妹都不同意,大叔很可怜,家里只有个两居室,儿子要结婚了,可是没房子,老两口的退休金根本不够给孩子买房子,想趁着这次拆迁要点钱,给儿子买房子,可是家里都不给。本来挺可怜这大叔的,可是等大叔父母和兄弟姐妹诉说之后,有了戏剧性的转折。大叔父母拿出了一个协议,大叔二十多年前结婚的时候跟父母商定,父母给一万块钱,他离家结婚,对父母生的时候不养,死了不用葬。大叔拿了钱,真的履行了协议,除了春节带着孩子回家看看父母以外,父母生病、盖房、搬家等等从来没管过。律师看了协议之后说协议无效,大叔很高兴,说是不是可以分家里拆迁的钱和房子。律师说家里财产是父母的,爱给谁给谁。协议无效,子女对父母有赡养义务,你必须赡养父母。

很多遇到困难的人总说自己很可怜,总说别人不对,遇到不顺的事就抱怨。我就是这样,每次我跟我妈抱怨,我妈就告诉我“脚上的泡都是自己走的”。我很喜欢《生命的寻路人》里的一句话“每件事都不止是表面呈现的样貌。看得见的世界只是知觉的一种层次。”一方面是说我们不要对别人的故事妄下结论,事情可能不像我们看到的一样。另外一方面是指我们面对困难的时候,要多想自己是不是有什么不对。人生路上,有些绊脚的石头,是我们自己放的。

mssql 时间格式化

1 取值后格式化
{0:d}小型:如2005-5-6
{0:D}大型:如2005年5月6日
{0:f}完整型
2 当前时间获取
DateTime.Now.ToShortDateString
3 取值中格式化
SQL Server里面可能经常会用到的日期格式转换方法:
sql server使用convert来取得datetime日期数据,以下实例包含各种日期格式的转换
语句及查询结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AM
Select CONVERT(varchar(100), GETDATE(), 1): 05/16/06
Select CONVERT(varchar(100), GETDATE(), 2): 06.05.16
Select CONVERT(varchar(100), GETDATE(), 3): 16/05/06
Select CONVERT(varchar(100), GETDATE(), 4): 16.05.06
Select CONVERT(varchar(100), GETDATE(), 5): 16-05-06
Select CONVERT(varchar(100), GETDATE(), 6): 16 05 06
Select CONVERT(varchar(100), GETDATE(), 7): 05 16, 06
Select CONVERT(varchar(100), GETDATE(), 8): 10:57:46
Select CONVERT(varchar(100), GETDATE(), 9): 05 16 2006 10:57:46:827AM
Select CONVERT(varchar(100), GETDATE(), 10): 05-16-06
Select CONVERT(varchar(100), GETDATE(), 11): 06/05/16
Select CONVERT(varchar(100), GETDATE(), 12): 060516
Select CONVERT(varchar(100), GETDATE(), 13): 16 05 2006 10:57:46:937
Select CONVERT(varchar(100), GETDATE(), 14): 10:57:46:967
Select CONVERT(varchar(100), GETDATE(), 20): 2006-05-16 10:57:47
Select CONVERT(varchar(100), GETDATE(), 21): 2006-05-16 10:57:47.157
Select CONVERT(varchar(100), GETDATE(), 22): 05/16/06 10:57:47 AM
Select CONVERT(varchar(100), GETDATE(), 23): 2006-05-16
Select CONVERT(varchar(100), GETDATE(), 24): 10:57:47
Select CONVERT(varchar(100), GETDATE(), 25): 2006-05-16 10:57:47.250
Select CONVERT(varchar(100), GETDATE(), 100): 05 16 2006 10:57AM
Select CONVERT(varchar(100), GETDATE(), 101): 05/16/2006
Select CONVERT(varchar(100), GETDATE(), 102): 2006.05.16
Select CONVERT(varchar(100), GETDATE(), 103): 16/05/2006
Select CONVERT(varchar(100), GETDATE(), 104): 16.05.2006
Select CONVERT(varchar(100), GETDATE(), 105): 16-05-2006
Select CONVERT(varchar(100), GETDATE(), 106): 16 05 2006
Select CONVERT(varchar(100), GETDATE(), 107): 05 16, 2006
Select CONVERT(varchar(100), GETDATE(), 108): 10:57:49
Select CONVERT(varchar(100), GETDATE(), 109): 05 16 2006 10:57:49:437AM
Select CONVERT(varchar(100), GETDATE(), 110): 05-16-2006
Select CONVERT(varchar(100), GETDATE(), 111): 2006/05/16
Select CONVERT(varchar(100), GETDATE(), 112): 20060516
Select CONVERT(varchar(100), GETDATE(), 113): 16 05 2006 10:57:49:513
Select CONVERT(varchar(100), GETDATE(), 114): 10:57:49:547
Select CONVERT(varchar(100), GETDATE(), 120): 2006-05-16 10:57:49
Select CONVERT(varchar(100), GETDATE(), 121): 2006-05-16 10:57:49.700
Select CONVERT(varchar(100), GETDATE(), 126): 2006-05-16T10:57:49.827
Select CONVERT(varchar(100), GETDATE(), 130): 18 ???? ?????? 1427 10:57:49:907AM
Select CONVERT(varchar(100), GETDATE(), 131): 18/04/1427 10:57:49:920AM

转载自 http://blog.csdn.net/dlyhs/archive/2009/05/12/4170986.aspx

linux下SSH传输文件

通过ssh传输文件
SSH进入对方机器:

1
ssh remoteIP

1
scp -rp /path/filename username@remoteIP:/path #将本地文件拷贝到服务器上
1
scp -rp username@remoteIP:/path/filename /path #将远程文件从服务器下载到本地
1
tar cvzf - /path/ | ssh username@remoteip "cd /some/path/; cat -> path.tar.gz" #压缩传输
1
tar cvzf - /path/ | ssh username@remoteip "cd /some/path/; tar xvzf -" #压缩传输一个目录并解压

转载自 http://blog.chinaunix.net/uid-20545423-id-1930177.html

纯靠点小聪明搞定学校 WiFi 该死的 web 登陆

去年学校还是用的 WPA2 PSK 加密的说,但因为我破了密码以后好心把密码传了出去就。。。唉自作自受。。。于是,学校今年升级了设备,改用 web 验证方法验证用户:
Screenshot_2014-10-27-17-19-56
真是丧心病狂。当然,学校也发现了学生使用学校网络的需求,遂给学生也提供了个 WiFi,但是!
Screenshot_2014-09-25-20-57-28
Screenshot_2014-09-25-20-58-18
哎呦我勒个去,然后试 ssh,无效,没招了,想用 remote rdp,尼玛也屏蔽。学校你这是作死的节奏啊。然后,从开学开始的一个月里,我试图直接获取管理权限,但是,试了各种弱口令后,无果。于是放弃获取管理权限,放低要求,只要能用就行。
既然技术不够,那看来只能走点歪门邪道试试咯。前几周,闲得无聊发现某任课老师上网本反应极慢,就向其提出重装系统的建议,老师答应了。之后我发现,老师的办公室里有有线网络,但是需要老师自己设定 IP 地址及网关等各种信息。没错,老师给我了:
Screenshot_2014-11-01-00-44-28
顺手记录了 mac 地址备用。用手机连上学校 WiFi 以后,发现被 DHCP 分配的 IP 地址与办公室有线网络并不在同一网段中,顿觉希望渺茫,手动指定了 IP 地址以后,无效。也懒得改手机的 mac 地址,没继续试下去。
换个思路,向老师索取了学校 WiFi 的账号及初始密码。想着总有老师是不用学校 WiFi 的吧,随手改了账号的后三位数字一试,居然真的登上了:
Screenshot_2014-10-27-17-18-57
真是机智的小淘气。

还没完,表示俺是住宿生,寝室门口有一台学校的路由器,但是,并没有开无线:
20141026_150554
百度了一下,发现这种路由器需要连接 console 口来管理,但尼玛我没有设备能连接有线网络啊:
20141026_151359
而且我不知道这台路由的 IP 地址,怎么办好呢。。。各位要不猜一下我干了什么869530255AD4DE7DE8AB2F80CF218AB8A7598D8B5

顺便提一下,学校网速还是不错的:
Screenshot_2014-10-24-11-09-22

有时候宽恕别人是变相的爱自己

几乎所有人在生活中都不会一帆风顺,总会遇到一些坎坷,一些弯路甚至是一些阴险小人。阴险小人会做什么坏事,你在明,他在暗,想防范是不太可能的。他们会找各种理由,断章取义,推理分析出各种事攻击你,中伤你,伤害你。这些攻击点可能在你的私生活、婚姻、家庭、爱好等等。而大多数人,都有以偏概全的惯性思维,有个成语叫一叶障目,有可能因为某个优点,认为这个人什么都好。也可能因为某个缺点,认为这个人什么都坏。

之前怀孕的时候有件事,我和李亦树在QQ群里聊天,说起一个事,我说了句“注册500个马甲关注自己。”马上有人截图发到网上揭露我有这么多粉丝的原因。很多人参加了这个争论,也有很多人问我是不是真有500个马甲。后来我问李亦树,我该怎么回答,他建议的回复是“谁说我有500个马甲?我的关注里,除了你都是我马甲。”有什么比生命更重要?当然没有!那就别为了这些事浪费宝贵的生命了。

自我调侃能节约无限的时间,但自我调侃不是逃避的借口。自我调侃是因为有自信,有自信的人,豁达的自我调侃。有次我们去海边,一位大哥带着金链子,一位大妈对他说“你这金链子假的吧?!真的不会这么粗!”大哥淡定的说“可不是!多亏您提醒,我一会儿找个绳儿拴一下,下海别飘走了。”有次去内蒙,看一个蒙族的汉子带儿子去摔跤,小男孩要面对自己大一倍的对手,他苦笑着对父亲说“他一屁股就把我坐死了。”父亲没有被他的“幽默”说服,反而告诉他,不打赢了就不能回家。每次男孩被摔下场,父亲就拉他走到一边,指点着他,男孩几次下来被摔的鼻青脸肿,终于赢得了比赛。对手失败后走过来挑衅说“看我下次怎么收拾你这个豆芽菜!”男孩看看父亲,跟对手说“你刚才是没看到我这个豆芽才绊倒的吧?!”周围人哄笑着。男孩用自我调侃的方式,漂亮的摆脱了对手的纠缠。

对于互联网时代的各种新闻,乐嘉(别跟我讨论他的人品,生活什么的,这话就是在他那儿看的,我只能写他的名字。)写过一句话,我觉得很有道理“在微博的世界中,感性的人们可以遇事多点理性和思考,少点冲动和口号。在避免永远做围观的看客,让这个社会越来越冷漠的同时,也要避免我们自己怀善人心做恶人事。与此同时,对于那些内心有着强烈愿望和使命感,希望通过网络发声从而影响社会变革的朋友而言,学会说话,说的有效有理有利有节是重要的功课。任何变革难免要有牺牲,但盲目的牺牲绝对不是变革。如果我们暂时无法改变社会,至少我们每个人可从改变自己开始。”我们在所谓的“站队”中理性一点,不要被所谓的“真相”所误导,谨慎评论。记得看电影《搜索》时,我们讨论那些“人肉”、“网络暴力”女主角的人,在女主角自杀以后,会不会忏悔,会不会内疚。而恶意放大事件的某个点,追求点击量的媒体及个人,是不是杀人凶手,应不应该负责。每次谁让我评论某个人、某件事的时候,我都会想到这个电影,都会谨慎,再谨慎。

在这个充满信息的环境中,能够回避耗费大量精力的骂战,是一种能力。相对于权力可以被剥夺,财富可以流失,名声更是一张艳照就可以没有了。能力,是一种稳定的,能创造价值又可以增长的好资源。拥有了这种能力,你能够有更多的时间,去做你想做的事,能创造价值的事。早上看书《浮石绘 • 话》里有两句“宽恕别人其实是在变相的爱自己。聪明人总是会给别人台阶下,因为你的谦让其实是在让他替你挪地方,将会使你的道路变得宽广。”“在人生中,我们常常要因为一点小事而耗费大量的精力,有一种人天生只能跟善良的好人打交道,如果能离开难缠的小人,任何代价都是可以付出的。”

MySQL事件调度器详解

自MySQL5.1.6起,增加了一个非常有特色的功能–事件调度器(Event Scheduler),可以用做定时执行某些特定任务(例如:删除记录、对数据进行汇总等等),来取代原先只能由操作系统的计划任务来执行的工作。更值得一提的是MYSQL的事件调度器可以精确到每秒钟执行一个任务,而操作系统的计划任务(如:Linux下的CRON或Windows下的任务计划)只能精确到每分钟执行一次。对于一些对数据实时性要求比较高的应用(例如:股票、赔率、比分等)就非常适合。
事件调度器有时也可称为临时触发器(temporal triggers),因为事件调度器是基于特定时间周期触发来执行某些任务,而触发器(Triggers)是基于某个表所产生的事件触发的,区别也就在这里。
在使用这个功能之前必须确保event_scheduler已开启,可执行

1
SET GLOBAL event_scheduler = 1;

或我们可以在配置my.ini文件 中加上event_scheduler = 1或

1
SET GLOBAL event_scheduler = ON;

来开启,也可以直接在启动命令加上“–event_scheduler=1”,例如:
mysqld … –event_scheduler=1
要查看当前是否已开启事件调度器,可执行如下SQL:

1
SHOW VARIABLES LIKE 'event_scheduler';


1
SELECT @@event_scheduler;


拥有SUPER 权限的账户执行SHOW PROCESSLIST 就可以看到这个线程了

定时服务配置
先来看一下它的语法:

1
2
3
4
5
6
7
8
9
CREATE EVENT [IF NOT EXISTS] event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE]
[COMMENT 'comment']
DO sql_statement;
schedule:
AT TIMESTAMP [+ INTERVAL INTERVAL]
| EVERY INTERVAL [STARTS TIMESTAMP] [ENDS TIMESTAMP]

INTERVAL:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}

1. 每秒插入一条记录到数据表

1
2
3
4
5
USE test;
CREATE TABLE aaa (timeline TIMESTAMP);
CREATE EVENT e_test_insert
ON SCHEDULE EVERY 1 SECOND
DO INSERT INTO test.aaa VALUES (CURRENT_TIMESTAMP);

等待3秒钟后,再执行查询看看:
mysql> SELECT * FROM aaa;
+———————+
| timeline |
+———————+
| 2007-07-18 20:44:26 |
| 2007-07-18 20:44:27 |
| 2007-07-18 20:44:28 |
+———————+

2. 5秒(天)后清空test表

1
2
3
4
5
6
CREATE EVENT e_test
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 5 SECOND
DO TRUNCATE TABLE test.aaa;
CREATE EVENT e_test
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 5 DAY
DO TRUNCATE TABLE test.aaa;

3. 2008年5月23日9点39分20秒整清空test表

1
2
3
CREATE EVENT e_test
ON SCHEDULE AT TIMESTAMP '2008-05-23 9:39:20'
DO TRUNCATE TABLE test.aaa;

这个测试有问题。还不太明白原因。

4. 每天定时清空test表

1
2
3
CREATE EVENT e_test
ON SCHEDULE EVERY 1 DAY
DO TRUNCATE TABLE test.aaa;

5. 5天后开启每天定时清空test表

1
2
3
4
CREATE EVENT e_test
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_TIMESTAMP + INTERVAL 5 DAY
DO TRUNCATE TABLE test.aaa;

这里5天也可以为0天,当时就开启清空表

6. 每天定时清空test表,5天后停止执行

1
2
3
4
CREATE EVENT e_test
ON SCHEDULE EVERY 1 DAY
ENDS CURRENT_TIMESTAMP + INTERVAL 5 DAY
DO TRUNCATE TABLE test.aaa;

该设置要求天数大于1,否则报错。而且创建不成功

7. 5天后开启每天定时清空test表,一个月后停止执行

1
2
3
4
5
CREATE EVENT e_test
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_TIMESTAMP + INTERVAL 5 DAY
ENDS CURRENT_TIMESTAMP + INTERVAL 1 MONTH
DO TRUNCATE TABLE test.aaa;[ON COMPLETION [NOT] PRESERVE]

可以设置这个事件是执行一次还是持久执行,默认为NOT PRESERVE。
该事件会停止每隔一秒插入数据的事件,感觉这点上mysql做的还是有问题。

8. 每天定时清空test表(只执行一次,任务完成后就终止该事件)

1
2
3
4
CREATE EVENT e_test
ON SCHEDULE EVERY 1 DAY
ON COMPLETION NOT PRESERVE
DO TRUNCATE TABLE test.aaa;

[ENABLE | DISABLE]可是设置该事件创建后状态是否开启或关闭,默认为ENABLE。
[COMMENT ‘comment’]可以给该事件加上注释。

定时服务日常维护测试
修改事件(ALTER EVENT)

1
2
3
4
5
6
7
ALTER EVENT event_name
[ON SCHEDULE schedule]
[RENAME TO new_event_name]
[ON COMPLETION [NOT] PRESERVE]
[COMMENT 'comment']
[ENABLE | DISABLE]
[DO sql_statement]

a、临时关闭事件

1
ALTER EVENT e_test DISABLE;

b、开启事件

1
ALTER EVENT e_test ENABLE;

c、将每天清空test表改为5天清空一次:

1
2
ALTER EVENT e_test
ON SCHEDULE EVERY 5 DAY;

d、重命名事件并加上注释

1
alter event test.new_e_test rename to e_test comment 'e_test_cm';

删除事件(DROP EVENT)
语法很简单,如下所示:

1
DROP EVENT [IF EXISTS] event_name

例如删除前面创建的e_test事件

1
DROP EVENT e_test;

当然前提是这个事件存在,否则会产生ERROR 1513 (HY000): Unknown event错误,因此最好加上IF EXISTS

1
DROP EVENT IF EXISTS e_test;

查看事件
a、查看一个event的详细信息可以用下面的视图:

1
SELECT * FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'test_insert'   AND EVENT_SCHEMA = 'test'\G;

b、简要列出所有的event:show events
语法:

1
2
SHOW EVENTS [FROM schema_name]
[LIKE 'pattern' | WHERE expr]

格式化显示所有event

1
SHOW EVENTS\G

格式化显示test用户的event

1
show events FROM test;

c、查看event的创建信息

1
2
SHOW CREATE EVENT event_name
show create event test.e_test\G

结论
该特性确实非常有用,可作为定时清空数据表、监控主从服务器、汇总数据到另一张表等等,并且可以精确到每秒,实时性也可以得到保障。
不过如果当两个事件的针对相同的对象的时候,会出现冲突,这种情况还不明确是我理解的问题还是确实是这样,比如每秒插入和定时删除就会冲突。除了调度SQL语句之外,MYSQL的调度器也可以调度存储过程。

缺点

1
SELECT * FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME = 'test_insert'  AND EVENT_SCHEMA = 'troaudit_db'\G;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
*************************** 1. row ***************************
EVENT_CATALOG: NULL
EVENT_SCHEMA: troaudit_db
EVENT_NAME: event_session_table
DEFINER: egilance@%
TIME_ZONE: SYSTEM
EVENT_BODY: SQL
EVENT_DEFINITION: BEGIN
CALL create_table_process;
END
EVENT_TYPE: RECURRING
EXECUTE_AT: NULL
INTERVAL_VALUE: 1800
INTERVAL_FIELD: SECOND
SQL_MODE:
STARTS: 2011-08-23 10:51:28
ENDS: NULL
STATUS: ENABLED
ON_COMPLETION: PRESERVE
CREATED: 2011-08-23 10:51:28
LAST_ALTERED: 2011-08-23 10:51:28
LAST_EXECUTED: 2011-08-23 17:55:51
EVENT_COMMENT:
ORIGINATOR: 0
CHARACTER_SET_CLIENT: utf8
COLLATION_CONNECTION: utf8_general_ci
DATABASE_COLLATION: utf8_unicode_ci
1 row in set (0.00 sec)

MySQL只会记录最后一次调度的时间,如果时间往前调整,小于最近执行的时间,则不会执行事件调度。

转载自 http://www.2cto.com/database/201111/109752.html