2010年1月14日星期四

《大秦帝国》--一部脑残的魔幻传记

这个魔幻传记的作者是崇尚黑暗的魔族云游诗人孙皓辉,此人法力高深,是一个时空云游诗人。据说,他为了完成这篇故事花费了几十年的时间,收集已经非常残缺不全的魔族资料,确实非常地辛苦。史称,魔族对外发动战争的军队是一个叫做秦的前人类种族组成的。秦族被魔族的第一代白袍巫师--商鞅,您没有看错,不是萨鲁曼,而是商鞅,改造成了魔族最强大的战士--强兽人,对人类发动百余年的战争,最终彻底征服了人类等其他种族。不过,魔族在彻底征服其它种族之后,魔族自己竟然莫名其妙地崩溃了。最令人震惊地是,魔族的皇族赢氏也神奇地消失了,而魔族的巫师们重新进入地下,伺机而动。来自中土东部的人族重新统治了中土。因此,此后的历史记载多对秦族以及其建立的帝国持否定态度。这无疑增加了魔族时空云游诗人孙皓辉编写故事的难度,因为他不愿意相信人类记载中有关魔族的描述。不过,幸好魔族时空云游诗人孙皓辉有时空穿越的法力,每当他看到不喜欢的史料,他通常就会进行思想地穿越,回到历史寻找他喜欢的历史材料。

其实很多人类记载的作者或多或少地也具有魔族血统,例如,编写《史记》的作者太史公司马迁其实是魔族后裔,其祖上是魔族将军。不过他的记载备受纯正的魔族云游诗人孙皓辉指责,他认为司马迁背叛了魔族,在《史记》中持有一些同情人类的思想,对于魔族缺少赞美。这其实也怨不得司马迁,因为他自己在写书的时候,遭到了魔族“至尊魔戒”继承人刘彻(按照魔族对首领的称呼,他应该被称为汉武帝)的迫害,用现在流行的话说--“被宫刑了”。据说,刘彻是正宗的人族,不过从他的做派来看,我们有理由相信,他绝对具有魔族血统。

上小学地时候,老师就谆谆教导我们,写作文的时候一定得注意时间、人物、事件这三要素,伟大的魔族时空云游诗人孙皓辉的水平当然要比我们的小学老师强得多。在看这个魔幻传记之前,我们需要先看一下故事的发生的各种背景,也就是交代一下故事的时间、人物、事件。

这个故事发生的时间被人类叫做战国时代。人类的圣人孔子生活在战国的前一个时代--春秋,他认为春秋是一个礼崩乐坏的时代。而到了战国时期,估计礼已经崩得差不多了,乐也基本从交响乐变成了重金属摇滚。我们自己在听摇滚的时候,经常会不由自主地随着节奏活动,有时候甚至会出现狂躁情绪。以此推论,战国时代摇滚乐的普及,造成了中土各国君主以及整个人类显得躁动不安,整个社会越来越不和谐,战争越来越多,规模越来越大。据八卦人士统计,这段时期中土战争的规模在世界上居于先进水平,远远领先于其它世界,据说领先两千多年,好事者可以考证一下。而号称现代文明发祥地的西土,直到两千多年之后的第一次世界大战,才出现了规模超过中土战国时期的战役。这样的历史背景,无疑为魔族的出现提供了基础。这段历史也被魔族时空云游诗人孙皓辉赞美为“大争之世”。

在这个历史背景下,中土人类君主不但要维护自己的统治,还经常不得不终止别的君主的统治,压力真的很大。因此早在春秋时代,人类的各个君主就已经开始请各种各样的巫师铸造自己的魔戒,不过,这些魔戒并非戴在手上,而是要戴在被统治的人类头上,被称为“法”。在人类后来的一篇神话(不是魔幻)小说《西游记》中,把“法”这种东西形象地称为紧箍咒,掌握紧箍咒的人完全可以根据自己的喜好,灵活掌握被控制的人能做什么,不能做什么。这对于各国君主来说,无疑非常具有吸引力。而全天下君主热火朝天、大干快上地铸造魔戒的行为,被后世称为“变法”运动。

铸造魔戒的行为到了战国中期达到了高潮。而铸造魔戒的巫师中,有人族的,也有魔族的,他们被后世人称为“先秦诸子”。据说“先秦诸子”有百家之多,这些“子”在铸造魔戒时,经常会进行技术和思想的交流。“子”们都喜欢使用老子留下的技术模型---“道”来阐述技术问题,但是由于老子留下的技术模型过于高深,几乎可与爱因斯坦的相对论,流体力学的纳维—斯托克斯方程相提并论。而由于学历、出身和智商所限,比如,姓墨的那位“子”工人出身,所以绝大部分“子”根本无法掌握老子的模型。大部分“子”们基本都是通过道听途说了解的“道”,根本没有受过老子的系统教育,连聪明的孔子只跟老子学习过几天而已,而其他人基本根本就没有见过老子。而且,老子自己也不是一个善于表达的人,辛辛苦苦写了一本《道德经》作为教材,写得云山雾罩,反而把人弄得更糊涂了。因此,“子”们对于技术的理解出现很多偏差,互相也根本无法说服对方,最后技术交流演变成互相对骂,骂战的胜负也只能以声音的大小决定的,因此史称“百家争鸣”。

另外,这些“子”们有一个显著的特点,就是喜欢替别人想事,准确点说,是为圣人或者人主策划一些事情,很少有人考虑自己,经常会为了自认为的一个崇高目标而赴汤蹈火,据说这叫士人精神,魔族第一代白袍巫师商鞅是一个很好的例子。当然,也有一些“子”不愿意搀和这些事情,最著名的就是杨朱、庄子这两位“子”,从师承上论,这两位其实才真正是“诸子”鼻祖--老子的正宗传人,但是这两位只替自己考虑事情,看看他们的学说知道了。庄子喜欢灵魂脱壳,骑着大鸟去做逍遥游。而杨朱更过分,只留下一句话:“拔一毛而利天下不为也”,想让他写本书,他认为这是利天下的行为,所以他不干。这两位被其它“子”,甚至整个中土人类视为异类。”诸子“对这二位的歧视,对中土人类带来非常不好的影响,至今东土人类都喜欢替别人打算事情,比如,帮别人盘算一下钱应该怎么花,还有即使到了现在,还有很多明明处于社会最底层的人类,总是喜欢替最高统治者考虑事情,对统治者的所作所为总能报以理解的态度。另外,中土人类还比较喜欢窥探别人隐私,他们总是对同类的收入比较感兴趣,而这种行为经常会被统治者所利用,据小道消息说,有位老太太几年如一日地对某位亲西土的人士进行盯梢。

最后,有几家铸成了自己的魔戒,在铸就的魔戒中,比较著名的有仁义魔戒,铸造者是人类儒家圣人孔子和孟子;黄老魔戒,铸造者是道家第一大门派黄老宗;而威力最为强大的是魔族第一代白袍巫师商鞅铸造的至尊魔戒。

人类的另外一位早于孔子的圣人--老子,早在春秋时代就睿智地预见了这个过程存在的风险,在他传世的伟大经典--《道德经》中,他非常忧虑地谈到:“法物滋起,盗贼多有”。而从老子的行为来看,老子非常想化解这个风险,也做出了一定的努力,比如,编写《道德经》希望君主们停止铸造魔戒的行为,施行无为的政策。另外,老子并非像大家所认为地那样,超然物外,以一双冷眼看世界。其实,他应该是非常热心地一个人,以至于为了提前化解魔族带来的危机,他甚至亲自西出函谷关,来到秦族,希望能够教化秦族,使他们不受魔族蛊惑。但是,从后面的历史看,老子的努力彻底失败了,历史也按照老子所预见地方式堕落下去----“失道,失德,失仁,失义,失礼”,最终至尊魔戒(法)统治了中土世界。

而魔族时空云游诗人孙皓辉为了掩盖老子的努力,伪造了一位老子,将后来的一位与曾经与老子从事同样职业的人---太史儋当作老子。魔族云游诗人孙皓辉还曲解和编造了两段预言,其中一段与太史儋有关,据记载是这样的:”秦周同源,均起西陲;秦为诸侯,而秦周分离;离五百年,而大合于秦;合十七年,则霸王出。“。另外一段是舜帝赐给魔族皇族嬴氏祖先皂游时的预言:“嬴氏一族必将大出于天下。”。不过,从历史的演进来看,很明显魔族把预言理解错了,这两段语言明明是说魔族皇族会被斩尽杀绝,没有文化真是害人不浅。第一句,印证了人类的复仇使者项羽的出现。而第二句很明显是出现了一个错别字,“出”应该改为“除”,就是嬴氏一族必将大”除“于天下,这样就好理解了。可见人类的圣贤还是非常有预见能力的。

据魔族时空云游诗人孙皓辉所说,魔族其实也有一位大巫师--鬼谷子。在故事中,伟大的魔族大巫师鬼谷子没有出场,一直在幕后活动,按部就班、有条不紊将秦族改造成强兽人,在一代代魔族巫师和魔族皇族的带领下,向人类发动战争,最终彻底征服了人类。鬼谷子的计划是通过一帮徒弟实现的,他们分别是:第一代灰袍巫师--庞涓和孙膑,职业:将军,他们的目的是搅乱天下,这两人为了魔族的崇高理想,不惜自相残杀,兄弟相残,真是人敬佩。第二代白袍巫师--商鞅,职业:炼金师,目的是为魔族铸造至尊魔戒,在完成目标之后,商鞅以身相殉,施展天魔解体大法,加强了至尊魔戒的法力,使魔族至尊魔戒威力大大超出了东方人类种族的魔戒。与其它魔戒相比,商鞅炼制的魔戒具备极权和军国两大必杀技。另外,据魔族时空云游诗人孙皓辉所说,魔族第一代白袍巫师商鞅在炼制至尊魔戒时,得到过姓墨的那位“子”的门人相助,因此必杀技之外,还有一个尚同的辅助加成技能。

而在东方人族炼制的魔戒,比如:人族道家炼制的黄老魔戒,儒家圣人孔子和孟子炼制的仁义魔戒,从威力上差了很多。与魔族的至尊魔戒相比,仁义魔戒根本就没有任何杀伤力,因此,几乎没有任何人族君主接受仁义魔戒,而黄老魔戒崇尚柔弱和无为,也渐渐被人族君主所抛弃,这样东方人族的悲剧最终无可避免。

鬼谷子的第三代弟子叫做张仪和苏秦,他们的目标是从政治层面搅乱人类各国。不过,两人结局不同,张仪凭借一张三寸不烂之舌和两行伶俐之齿以及鬼故门生的圆滑,成功回山交差。而苏秦生活作风出现问题,与人类燕族国王的女人有染,遭人刺杀。总之,魔族大巫师鬼谷子成功地将历史进程纳入自己的轨道,剩下工作的就由魔族皇族和强兽人完成。为了加快这个进程,魔族大巫师通过其它途径培养了一位强兽人将军,这位强兽人将军不负鬼望,通过几次战争打破了魔族与人族的平衡。据记载,这位叫做白起的强兽人将军,一生屠杀人类的记录是一百六十万以上。魔族时空云游诗人孙皓辉特意为这位伟大的强兽人将军白起立传,叫做《金戈铁马》。最终收官工作是魔族皇族的赢政完成的,这位伟大的魔族君主为后世的人族和非人族君主起了一个很好的名字---皇帝。另外,据传说,被魔族时空云游诗人孙皓辉鄙视的太史公司马迁的祖先是强兽人将军白起的部下。

魔族时空云游诗人孙皓辉为了避免打打杀杀地让人腻味,在这套魔幻传记中加入了第一代魔族白袍巫师商鞅与人类圣女白雪之间的一段凄美的爱情故事。不过,魔族时空云游诗人孙皓辉在爱情方面的描写明显比不上西土的作家莎士比亚。据称,很多人会选择在吃饭时看他写的感情戏,这样会有一种呕吐的感觉,降低食欲,最终达到减肥的目的。

最后需要说明的是,魔族时空云游诗人孙皓辉取得了巨大的成功。他的书在很多人中引起巨大的反向,这些人主要是对一部分对现实不满的人,幻想恢复至尊魔戒的统治。当然,并非所有对现实不满的人希望至尊魔戒重现。很多人更愿意接受从西土传入的普世魔戒。对于普世魔戒的功能,不在本文的讨论范围。为了扩大这个魔幻故事的影响力,魔族时空云游诗人孙皓辉将故事的第一季编写成了电视剧,以便让更多脑仁和松子一样大,打开脑袋盖里面就一碗卤煮的人接受他的思想。但是,电视剧的命运很凄惨,拍完之后被当代真理部封杀。不过,在现实题材电视剧《蜗居》出现之后,真理部意识到,还是魔幻题材的更好控制。因此为了对抗现实主义的《蜗居》,当代真理部放开了对这个魔幻电视剧的管制,由这个魔幻故事的故乡电视台播放。

2009年4月12日星期日

flare编译问题

flare是一种创建数据可视化flash程序的actionscript库,采用apache-ant作为编译程序,具体操作见官方教程:http://flare.prefuse.org/tutorial。但是,由于flex-sdk的target-player参数设置问题,会造成在编译过程中提示以下错误:
Error: 找不到类型,或者它不是编译时常数: Vector。
或者
Type was not found or was not a compile-time constant: Vector.

这是因为编译时,默认支持的Flash Player的版本是9.0.124。遇到这种错误时,需要修改flex-sdk/frameworks/flex-config.xml,将<target-player>9.0.124</target-player>改为<target-player>10.0.12</target-player>。如果使用flexbuilder,可以通过Project > Properties > Flex Compiler 设置附加编译器参数-target-player=10.0.12。

2009年3月19日星期四

picviz

Picviz是一个平行坐标绘图程序。通过简单的脚本,picviz可以轻松将各种输入数据(tcpdump、syslog、iptables logs、apache logs,等等)形象化,用户可以从中发掘有意思的东西。另外,Picviz还可以帮助用户创建、理解平行坐标图。

Picviz的目标是通过将数据图形化的方式,帮助用户快速分析问题,发现各种因素的关联关系。在安全分析领域,这个程序具备非常好的扩展能力,能够处理百万级的数据。

Picviz使用专用的语言来描述图形,类似于graphviz的图形描述语言。通过一个引擎,能够生成平行坐标图像。另外,Picviz还提供了python语言绑定,用来收集计算过的数据、原始数据,并使用python和qt4实现了一个前端程序。

2009年3月10日星期二

Bro支持的数据类型

Bro ids的策略层分析和检测组件是由一种脚本语言实现的,这种脚本语言主要面向网络连接和流量的处理,支持特定的类型。Bro数据类型系统支持18种数据类型:

  • bool:二进制数据;
  • count、int,和doublet:统称数字,可以进行数学、逻辑,和对比操作;
  • enum:类似于C语言的枚举;
  • string,、character:字符串和字符,可以进行对比和查询操作;
  • pattern:定义用于模式匹配的正则表达式;
  • time、interval:表示绝对时间和时间间隔;
  • port:传输层的端口号;
  • addr:IP地址;
  • net:网络前缀;
  • record:一组数据的集合(可能是不同类型),每个数据都有自己的名字;
  • table:联合数组;
  • set: 标量元组的集合;
  • file:一个被写入的硬盘文件;
  • function:能够通过一组参数调用,并且有返回值;
  • event:事件处理器,事件产生后,通过一组参数进行调用。

bro脚本中的每个变量都必须是上述类型之一。对于大多数类型,有很多方式将变量指定为常量。例如,2.71828是一个双精度类型的常量,80/tcp是一个port类型的常量。


最后,Bro的变量是静态类型,意味着他们的类型是固定的,但即使这样,也可以通过重新指定变量的方式,对其类型进行转换。例如,通过以下操作,整数a能够直接被转换为双精度数字:

   local a = 5;
local b = a * .2;

2009年3月9日星期一

bro的事件

什么是事件

在Bro中,事件(event)用于反应特定网络行为。而事件处理引擎是Bro的核心。事件可以针对底层的网络协议,也可以针对应用层协议。

事件处理器

事件处理器从语法上非常接近于函数,两者的不同是事件处理器没有返回值,也不能被调用。事件处理器可以采用如下方式声明:

event ( argument*  )

例如:

local eh: event(attack_source: addr, severity: count)

声明了局部变量eh,eh是一个事件处理器类型,有两个参数:attack_source是地址(addr)类型;severity是计数(count)类型。

如果想声明一个有处理代码的事件处理器,语法是:

event handler  ( argument  )  { statement @code{}}

另外,可以把事件处理器赋值给一个相同类型的变量。

事件产生的方式

事件的产生有以下三种方式:

  • 事件引擎产生

当事件引擎检测到一个定义了事件处理器的事件时,会将其放入队列中,等待事件处理器处理。一旦事件引擎处理完当前数据包,会立即调用事件处理器。

  • 通过事件语句产生

例如,在策略脚本中使用:

event password_exposed(c, user, password);

事件引擎就会以参数c、user、password调用事件处理器password_exposed。注意:必须已经在调用之前,对password_exposed进行声明,而且参数也必须兼容。

  • 通过调度表达式

调度表达式在将来的某个时刻启动事件表达式。例如:

schedule 5 secs { password_exposed(c, user, password) };

表示password_exposed将在5秒之后启动。

事件处理机制

强大的事件模型是bro的核心,通过bro的通讯框架,可以实现事件处理的分布操作,这也是bro入侵检测系统能够分布式部署的基础之一。

将事件检测机制与事件处理机制分离是bro的核心思想之一。事件由bro核心的分析器产生。分析器持续地进行分析操作,一旦看到相关的行为就以异步的方式 出发事件,例如,新建了一个TCP连接,或者看到了HTTP请求的URL。Bro核心的分析器能够进行广泛的协议分析,例如:TCP、UDP、FTP、 HTTP、ICMP、SMTP、RPM等。不过,为了降低CPU资源的占用,需要注意:只启用分析所需的事件触发。

一旦某个事件触发,事件处理引擎将其投递到策略层。每个Bro阶段都有相关的策略来控制器策略层的行为。这些策略对应于站点的安全策略,由Bro脚 本语言写成。这种语言是一种强类型,函数风格的语言,为网络行为分析提供了大量的数据类型。在策略层还维护着大量状态信息变量,这些变量主要是描述相关的 网络行为。每种事件,都可以定义一种或多种事件处理器进行处理,事件处理器甚至还可以触发新的事件。事件类型由名称和一系列参数组成,可以唯一识别特定的 事件。

2009年3月6日星期五

ossec的新功能--预编译规则之三:对预处理规则的评价

对预处理规则的评价

插件化是很多开源软件采取的,非常流行的扩展方式,例如:

  • apache:采用动态共享对象的方式,提供扩展;利用Apache扩展工具(apxs),可以无需重新编译apache,即可加入apache插件;
  • nessus:nessus自创了一种叫做nasl的脚本语言来实现差价的扩展,由于其功能的局限,这种语言较受争议;
  • nmap:通过NSE(Nmap Script Engine,nmap脚本引擎)实现插件的扩展,使用目前非常流行的lua作为其寄生语言;
  • snort:在snort3的代码中,也引入了lua作为扩展语言;
  • bro-ids:采用了一种自定义的脚本语言,来扩展对网络流量的处理功能。

与上述开源产品相比,ossec的预处理规则显得非常粗糙,从技术上看,甚至有些画蛇添足,因为:

  • ossec的xml规则编写的难度比c语言编写的预处理规则更容易掌握;
  • 预处理规则只局限于检测规则,其提供的扩展能力,不见得比在xml规则中定义正则表达式更强大;
  • ossec的预处理规则不具备动态编译部署的能力,加入新的预处理规则,必须重新编译ossec的源代码;
  • 由于预处理规则c程序的引入,有可能会给ossec加入新的bug,反而造成ossec的不稳定;

而与上述问题相比,预处理规则只能满足对c语言的偏好,所以前景不会太乐观,除非效法nmap做改进。另外,预处理规则出现的真正原因或许是出于商业的考 虑,因为利用预处理规则,Third Brigade公司可以对某些检测功能封闭源代码,直接编译到其商业版中,不用担心技术的泄露。

2009年3月5日星期四

ossec的新功能--预编译规则之二:预编译规则

预编译规则

根据上面的介绍,我们知道ossec有两种规则,其中解码器负责日志解码、分类,规则实现入侵检测和日志分析。想了解预编译规则能干什么,我们现看看ossec处理日志(以syslog为例)的基本处理流程:

  1. ossec-logcollector(源代码在src/logcollector)监控各种日志的变更,ossec支持syslog、mysql、postgresql、snort、nmap,以及djbmultilog等日志;
  2. 一旦发现日志变动,就读取信产生的日志,根据日志类型的不同,分别调用read_syslog、read_djbmultilog、 read_nmapg、read_mysql_log、read_snortfull、read_postgresql_log等函数进行处理。在这里我 们只关注syslog的处理。
  3. read_syslog读取日志条目,调用SendMSG向analysisd(源代码在src/analysisd)投递。在ossec启动时,analysisd会打开一个UNIX套接字,接收事件日志,进行分析处理。
  4. ossec-analysisd调用OS_ReadMSG_analysisd函数接收事件信息,然后调用OS_CleanMSG将收到的数据转换为Eventinfo结构。

Eventinfo

我们先看一下Eventinfo:

typedef struct _Eventinfo
{
/* 从事件信息中提取的数据 */
char *log;
char *full_log;
char *location;
char *hostname;
char *program_name;

/* 从解码器中提取的数据 */
char *srcip;
char *dstip;
char *srcport;
char *dstport;
char *protocol;
char *action;
char *srcuser;
char *dstuser;
char *id;
char *status;
char *command;
char *url;
char *data;
char *systemname;

/* Pointer to the rule that generated it */
RuleInfo *generated_rule;

/* Pointer to the decoder that matched */
OSDecoderInfo *decoder_info;

/* Sid node to delete */
OSListNode *sid_node_to_delete;

/* Extract when the event fires a rule */
int size;
int p_name_size;

/* Other internal variables */
short int matched;

int time;
int day;
int year;
char hour[9];
char mon[4];
}Eventinfo;

Eventinfo是ossec检测的核心对象,所有的检测都是针对Eventinfo进行的。对Eventinfo的处理又分以下阶段:

  1. 预处理阶段。OS_CleanMSG函数从接收到的信息中,提取相关数据,填写Eventinfo的第一部分;
  2. 解码处理阶段。调用DecodeEvent函数,完成解码处理。
  3. 检测阶段。剩下的检测过程全部由OS_ReadMSG_analysisd调度完成。

预编译规则

ossec预编译规则的位置是源代码的src/analysisd/compiled_rules目录。在上述阶段中,预处理规则只能用于检测阶段,与xml定义的检测规则等同。下面我们看一下ossec源代码中的一段示例,检测源用户和目标用户是否相同。

void *comp_srcuser_dstuser(Eventinfo *lf)
{
if(!lf->srcuser || !lf->dstuser)
{
return(lf);
}

/* 对比Eventinfo中,srcuser是否等于dstuser */
if(strcmp(lf->srcuser, lf->dstuser) == 0)
{
return(lf);
}


/* In here, srcuser and dstuser are present and are different. */
return(NULL);
}

编写预处理插件时,我们只需要编写我们需要的功能即可,剩下的相关工作可以由register_rule.sh脚本完成,然后重新编译ossec的源代码,即可完成安装。register_rule.sh支持以下选项:

  • add <函数明> #添加函数
  • list #列出加入的函数
  • build #生成头文件 compiled_rules.h
  • save #备份函数列表
  • restore #恢复函数列表

2009年3月4日星期三

ossec的新功能--预编译规则之一:ossec的规则

OSSEC的预编译规则(Compiled Rules)为了方便不喜欢编写xml格式规则的用户。利用这项功能,用户可以直接使用c语言来编写日志处理规则,在编译的时候,连接到 analysisd程序。并非一种动态的规则扩展机制。为了了解预编译规则,我们先看一下ossec的规则定义。

1. ossec的规则

ossec的规则是XML格式的,主要有两种:

  • 解码规则:用于判断日志的种类和格式,所有的内容都在decode.xml文件中;
  • 检测规则:依赖于检测规则,主要用于检测日志中记录的安全问题。

1.1. 解码规则

根据decoder.xml的定义,ossec的日志分析程序会从被监控的日志中提取某些字段,根据这些字段判断日志的种类,例如:sshd日志、 web日志,然后在根据其中的某些字段,确定日志记录了那种信息,例如:sshd登录成功、失败。下面我们看一段linux sshd日志的片段(来源于ossec wiki的日志样本):

  • 登录成功:

May 21 20:22:28 slacker2 sshd[8813]: Accepted password for root from 192.168.20.185 port 1066 ssh2
May 21 20:22:28 sol2 sshd[23857]: [ID 702911 auth.notice] User test1, coming from 192.168.2.185, - authenticated.
Oct 11 08:05:46 hostname auth|security:info sshd[323808]: Accepted publickey for usr1 from 2.3.4.5 port 37909 ssh2


  • 登录失败:

May 21 20:22:28 slacker sshd[21487]: Failed password for root from 192.168.20.185 port 1045 ssh2

  • 无效的用户登录企图:

Jul 7 10:51:24 chaves sshd[19537]: Invalid user admin from spongebob.lab.ossec.net
Jul 7 10:53:24 chaves sshd[12914]: Failed password for invalid user test-inv from spongebob.lab.ossec.net
Jul 7 10:53:24 kiko sshd[3251]: User dcid not allowed because listed in DenyUsers



decoder.xml文件中,相关规则如下:

<!-- 判断sshd日志的规则,从日志条目的开头匹配是否存在字符:sshd。 -->
<!-- 也是其它sshd日志解析规则的上级规则。 -->
<decoder name="sshd">
<program_name>^sshd</program_name>
</decoder>


<decoder name="sshd-success"><!-- 解析sshd登录成功日志 -->
<parent>sshd</parent><!-- 只有符合sshd的条件才启用这条规则 -->
<prematch>^Accepted</prematch><!-- 判断是否为登录成功,条件是从头搜索,发现Accepted字符 -->

<!-- 从日志条目中,利用正则表达式提取变量 -->
<regex offset="after_prematch">^ \S+ for (\S+) from (\S+) port </regex>

<!-- 两个(\S+)提取的值分别赋给变量:user(用户名)和srcip(源IP地址) -->
<order>user, srcip</order>

<!-- 根据name, user, location判断fts??? -->
<!-- fts是首次看到(First Time Seen)的简写 -->
<fts>name, user, location</fts>
</decoder>

<!-- 无效的用户或者失败的登录 -->
<decoder name="ssh-invfailed">
<parent>sshd</parent>

<!-- 判断 -->
<prematch>^Failed \S+ for invalid user|^Failed \S+ for illegal user</prematch>

<!-- 提取源IP地址 -->
<regex offset="after_prematch">from (\S+) port \d+ \w+$</regex>
<order>srcip</order>
</decoder>

<!-- 登录失败 -->
<decoder name="ssh-failed">
<parent>sshd</parent>
<prematch>^Failed \S+ </prematch>
<regex offset="after_prematch">^for (\S+) from (\S+) port \d+ \w+$</regex>
<order>user, srcip</order>
</decoder>

<!-- 无效用户 -->
<decoder name="ssh-invalid-user">
<parent>sshd</parent>
<prematch>^Invalid user|^Illegal user</prematch>
<regex offset="after_prematch"> from (\S+)$</regex>
<order>srcip</order>
</decoder>


1.2. 检测规则

检测规则位于etc/rules/目录中,还是以sshd的规则为例:

<group name="syslog,sshd,"> <!-- 定义规则组 -->
<rule id="5700" level="0" noalert="1">
<decoded_as>sshd</decoded_as> <!-- 判断是否为sshd日志 -->
<description>SSHD messages grouped.</description>
</rule>

<rule id="5701" level="8">
<if_sid>5700</if_sid> <!-- 只处理sshd日志 -->
<match>Bad protocol version identification</match>
<description>Possible attack on the ssh server </description>
<description>(or version gathering).</description>
</rule>

<!-- 其余规则省略 -->
</group>

2009年2月19日星期四

netmate在x86_64平台编译遇到的问题和解决方案。

在x86_64平台上编译netmate时,会遇到以下错误信息:

...
../../src/include/stdincpp.h:46:22: error: multimap.h: No such file or directory
../../src/include/stdincpp.h:47:22: error: hash_map.h: No such file or directory
../../src/include/stdincpp.h:58:21: error: iomanip.h: No such file or directory
../../src/include/stdincpp.h:59:23: error: streambuf.h: No such file or directory
In file included from ../../src/netmate/FlowRecord.h:35,
from ../../src/include/ExportModuleInterface.h:39,
from ./ExportModule.h:34,
from testexp.cc:33:
../../src/netmate/MetricData.h: In member function 'char* MetricData::align(char*, DataType_e)':
../../src/netmate/MetricData.h:101: error: cast from 'char*' to 'unsigned int' loses precision
testexp.cc: In function 'char* getErrorMsg(int)':
testexp.cc:121: warning: deprecated conversion from string constant to 'char*'
testexp.cc: In function 'char* getModuleInfo(int)':
testexp.cc:127: warning: deprecated conversion from string constant to 'char*'
make[3]: *** [testexp.lo] 错误 1
...

g++版本和操作系统分别是gcc版本 4.3.2 (Ubuntu 4.3.2-1ubuntu12)或gcc version 4.1.2 20071124 (Red Hat 4.1.2-42)。

这个问题可以分为两部分:

  1. error: cast from 'char*' to 'unsigned int' loses precision
  2. 头文件找不到的问题。

error: cast from 'char*' to 'unsigned int' loses precision是由于指针的长度造成的,在传统32位系统中,指针的长度是32为,与int的长度相同,但是在64位Unix系统中,指针的长度已是64位(LP64)。所以char指针转换为unsigned int会出现问题。相关代码如下:

    inline char *align(char *var, DataType_e type)
{
return (DataTypeSize[type] == 0) ? var :
(char*) (((unsigned int)(var) + DataTypeSize[type]-1) /
DataTypeSize[type] * DataTypeSize[type]);
}

将其中的unsigned int修改为unsigned long,编译通过。

而第二个问题,在ubuntu 8.10中无法解决,这是libstdc++的版本造成的,在centos5中,安装compat-libstdc++-33即可解决问题。

2008年12月10日星期三

“百姓”古今意义之别对阅读《道德经》造成的误解

中国与西方在思维、表达方式存在巨大的差异。西方从很早就形成了严密的形式逻辑体系(在欧儿里得几何学中)。而中国从历史上就没有形成这方面的体系,走的是另外一条道路,就是观象取意,在思维上叫做像思维,以《易经》为代表。这种表达方式不对事物下定义,而是从不同角度取象来对事物来进行描述,因此周易中讲“观物取象、象以尽义”。“象思维”大致可以分为三个层次:具象、意象、体悟之象。

作为古代经典之一的《道德经》也是采用这种描述,书中涉及治国、修身、谈兵、自然等很多的象,而几乎没有任何概念性的内容。采用这种描述方式的直接后果是,由于某些词在演变过程中发生了很大的变化,给后人造成了很大的误解,道德经中的“百姓”就是一例。下面我们来看这两段内容:

第五章

天地不仁,以万物为刍狗;圣人不仁,以百姓为刍狗。天地之间,其犹橐龠乎?虚而不屈,动而愈出。多闻数穷,不如守中。

第四十九章

圣人常无心,以百姓心为心。善者吾善之,不善者吾亦善之,得善。信者吾信之,不信者吾亦信之,得信。圣人在天下,歙歙焉,为天下浑其心,圣人皆孩之。


我们先说第五章的“天地不仁,以万物为刍狗;圣人不仁,以百姓为刍狗”,按照现在的理解,百姓当然指的是人民大众了,所以有一些注家在点评这段时认为,这是老子对天地和圣人的控诉,当然现在这种论点极少。而大部分注家认为这一句的意思是天地和圣人无私心,任万物和百姓自生自灭,这种观点与《道德经》全文的意思相近,所以是主流的。

其实,这也是有问题的。问题就在对于“百姓”的理解。在古代庶民无姓,有土有官爵者才有姓。所以“百姓”作贵族的通称,而战国之后才泛指平民。我们知道老子应该是春秋晚期的人,而且是周王室的史官,因此他不可能将“百姓”指代平民,在《道德经》中百姓只能是有官爵的人,或者是贵族。刍狗是古代祭祀时用草扎成的狗,在祭祀时披红挂绿,备受尊崇,而祭祀完成之后,被任意丢弃。因此,第五章这段话的意思应该是这样的:

天地没有任何偏爱,把万物当成刍狗,需要其繁盛时,就让其繁盛,需要其枯萎时,就使其枯萎。
圣人没有任何偏爱,把百官当成刍狗,适合就任用他,不适合就罢免他。


这不就是最佳的管理诀窍吗?选择合适的时机,任用合适的人选作合理的事情,而且官员能上能下。:)

同样,第四十九章中的意思也就好理解了:

圣人不固执己见,在做事之前,先听取百官的不同意见。

我们知道,老子是崇尚远古的,这段话其实反应了远古原始社会的一种民主方式。

2008年12月5日星期五

ElementTree如何输出XML的版本

默认的lxml.etree是用ascii编码,在输出的XML文件中没有,如果需要在输出的XML文件中包含,需要在tree.write()函数中设置参数。例如:

import lxml.etree as et
tree = et.parse('sample-ns.xml')
tree = tree.write('test.xml', encoding='utf-8', xml_declaration=True)

原始文件是:

<root xmlns='namespace'>
<element key='value'>text</element>
<element>text</element>tail
<empty-element/>
</root>


输出的文件是:

<?xml version='1.0' encoding='utf-8'?>
<root xmlns="namespace">
<element key="value">text</element>
<element>text</element>tail
<empty-element/>
</root>

2008年11月1日星期六

Ubuntu8.10发布了

经过半天多的下载,总算升级完成了。按照惯例,恐怕半个月之内会问题不断,平常自己弄的东西太多,所以升级出现了一些问题。不过慢慢会解决地。出现的最大问题是nvidia显卡的驱动,查了一些资料,发现推荐的nvidia-177-kernel-source存在问题,另外nvidia-xconfig也有一些问题,最后使用envyng安装nvidia-173-kernel-source,算是解决了问题。

2008年10月29日星期三

利用开源技术建立数据仓库

利用开源技术建立数据仓库

简介

本文的主要内容是建立数据仓库。数据仓库是一种计算机数据库系统,用于收集、整合和存储组织的数据,帮助生成准确的、时间性的管理信息,以及支持数据分析。本文解释了一个好的数据仓库的重要性,并涵盖了利用开源技术建立一个数据仓库的流程。

本文面向的读者

本文主要面向软件开发者、数据库管理员、软件集成商,或者其它有兴趣面临大数据量业务数据分析挑战的读者。阅读本文的读者需要具备数据库、信息系统和业务事务的基本只是。

为什么要建立数据仓库

有很多理由说明建立数据仓库的重要性,但是大部分理由都可以归纳为一个基本的愿望:提供一种数据分析的方式,来支持管理决策。你可能已经为管理者提供过很 多数据,例如:信息系统网站的使用统计,引用趋势,以及注册用户的数量。这些都是基本的信息,可以直接从信息系统获得。然而,这些数据存在很大的缺陷。

首先,直接从信息系统提取数据无疑会增加系统的负载。而数据分析过程通常需要进行大规模地数据处理。另外,处理过程中可能会发生其它一些问题,例如,在数据提取过程中系统数据库的表被锁定。而数据仓库与信息系统是完全分离的,甚至可以运行于不同的系统。

其次,一个OLTP(联 机事务处理)系统的数据模型是针对数据分析专门优化的。以前,我们都是根据我们的实体关系,来开发使用正规化数据库模型的系统。这对于信息系统来说,是合 适的,因为基础模型能够正确反映系统的情况。但是,这种模型使得查询大数据量聚合数据变得非常困难。而且,这种数据库设计的冗余能力很差,因为难以维护, 经常造成数据不一致,甚至更糟。而对于数据分析,数据冗余非常有用,它会提高处理效率。

此外,OLTP(联机事务处理)系统中的数据可以随时间变化。例如,在一个在线的客户关系管理系统中,客户迁徙到其它国家,在这种情况下,可以采用多种方式进行数据处理:

  • 更新客户的记录,消除其先前的国家信息和分析信息;
  • 在应用系统中创建新的记录,用于记录这个客户信息。

这两种方式都不太令人满意,因为它们丢失了客户的历史信息。而数据仓库能够解决这个问题,在数据仓库中,可以保存客户在所有时期内的状态记录,从中很容易得到起变化情况。

最后,可能存在很多信息系统不用的数据源,这些数据源可以用于数据分析。数据仓库可以为所有这些数据提供集中的存储,收集到的信息可以在一步内完成查询。

创建数据仓库

在本章中,我将指导你使用不同的方式来创建数据仓库。我将用一个基于web的简单信息系统来描述如何建立一个数据仓库。这个基于web的信息系统包括请求、用户和页面之类的信息实体。这个信息系统的数据模型暂缺。

设计一个纬度化的数据仓库

提出问题

创建数据仓库最重要的步骤是设计。你可能会嘀咕:“管理层希望知道什么?”。首先,你不得不通过分析数据的属性,找出需要回答的问题。例如,用户和 页面存在关联吗?是否存在某类的用户只访问某些页面,不访问其它的页面?访问者从哪些页面来,到哪些页面去?我相信通过这种方式,至少在80%的问题上, 管理层会给出满意的答案。

既然你已经读到了这里,我就假定你公司管理层已经回答了类似的问题。如果没有,就让他们做。不要小看这个阶段,它是数据仓库成败的基础。

结构模型化

一旦你通过一些问题获得了管理层的关注点,下一步就是要根据这些关注点决定如何安排数据仓库中的数据。例如,销售人员的数据应该在多种不同的结构中进行操作,而不应该只局限于职位。在OLAP世界中,这些结构叫做数据立方体(Cube?),因为它是传统二维数据库的扩展。根据数据的不同,一个数据立方体可以有两个以上的纬度。我们将在关系数据库中,利用星形模式为数据立方体(Cube?)建模,利用一个fact(好多人翻译为事实?)表,将一系列的纬度表连接起来。

选择事实元素的粒度(fact grain)

创建数据立方体(Cube?) 的关键是为其找一个好的事实表(fact table)。这一步的操作很简单,在事实表(fact table)中,每一个“事实(fact)”元素各占一行,因此难点变成了如何添加有用的纬度。好的事实表的标准是,数据的粒度尽可能细。数据立方体经常 是单个事务,例如支付,在我们的例子中,是页面请求。

添加纬度

现在我们有了一个数据立方体的中心起始点,现在是时间加入新的纬度来修饰基本事实元素,纬度表保存事实元素的属性。如果你想不出事实表的任何纬度, 可能是因为起始的粒度选择存在问题。在所有的纬度中,时间纬度是最为显而易见的。在时间轴上,每个请求都有一个位置,因此我们建立一个纬度表"time" 来保存所有的请求实体,这个表的每个记录代表每个记录发生的时间。如果两个请求同时发生,在时间纬度表中它们被连接到同一个实体。

我们还需要添加一个代表页面的纬度。每个条目都是一个页面信息,对应事实表中的一个请求。

最后,我们还需要添加一个纬度,表示发起请求的用户。事实表中的每个请求,都是由已知用户,或者根本不是用户发起的,所有这些都报存在用户纬度表。

在我们创建并连接纬度表时,需要遵循一个重要的规则,不要使用在线系统的现有键,因为我们根本无法对其进行任何控制,它们或许会改变,甚至消失。作 为替代,每个纬度都需要一个自己的代理键,这个键称为“技术键(technical key)”,在整个数据仓库中都是唯一的。

构建数据仓库

现在我们知道,数据立方体会被表达为星形模式,下面我们将开始构建工作。在这一步,我们将使用来自于OLTP系统的数据填充一个数据仓库。这个阶段的流程叫做ETL?,即提取、转换、加载。这是我们所需要做的,从各种数据源中提取事实表和纬度表所需的数据,转换为我们所需要的形式,加载到数据仓库,以备查询、分析。我们将使用KETTLE执行这些操作,KETTLE是一个开源的ETL?工具。KETTLE有两个软件包组成。Spoon和Pan用于创建和执行转换(transformation)操作,而Chef和Kitchen用于从转换(transformation)中定义作业并调度和执行它们。

使用Spoon设计转换

现在,我们开始使用Spoon创建一个用于填充数据仓库的转换(transformation)。为了填写事实表,到所有纬度的键必须是事先知道的。因此,我们需要明确区分两类纬度:

  1. 纬度的组成数据事先已经明确位于在线的信息系统。
  2. 纬度的组成数据需要从事实数据和周边数据源中生成。

在第二种情况下,我们是在填写事实表的过程中,生成或更新纬度数据的,因此可以同时得到其键值,但在第一种情况下,我们做不到。

在我们的例子中,时间和页面纬度属于第二种情况,就是说他们是在更新事实表的时候生成的。然而,由于用户纬度基于信息系统的表,需要提前获取其键 值。因此,我们将通过两个独立的转换(transformation)来填写数据仓库,第一个针对数据已经存在的用户纬度,而第二个针对其它纬度和事实 表。

一些准备工作

在使用Spoon之前,我们需要先定义数据源。在这个例子中,我们只有一个数据源:信息系统的数据库。我们需要将这个数据库作为一个连接(Connection)添加到Spoon。我们的目的数据库连接也可以在此定义。

更新第一种纬度

在我们的例子中,用户纬度是唯一一个不能在填写纬度表的过程中更新的纬度。用户数据已经被保存在源信息系统的一个表中,所以我们需要使用Spoon的“Dimension lookup/update”功能将数据读出、处理。

这一步用于创建、更新和查询变化缓慢的纬度。数据源中的数据还会发生变更,例如用户信息会发生变化,处理数据更新有以下两种方式:

  1. 更新现有记录;
  2. 创建另外纬度记录,维护全部的过程记录。

如果使用第二种方式,就需要在纬度表中加入数据变更的识别信息,例如:“version”, “date_from” and “date_to”等。

在我们的例子中,我们需要按照第二种方式来处理用户纬度,所以Spoon中的转换(transformation)如图3所示。首先,从信息系统用户表中读出数据;接着,按照纬度表的要求使用"select"指令对其进行过滤;最后,将过滤后的数据插入数据仓库的user_dim表中。在Spoon的文档中有详细的说明,所以我们接下来只介绍如何配置纬度查询/更新(dimension lookup/update)。

由于我们是直接从信息系统的表中创建用户纬度表,所以信息系统用户表中的主键是多余的。在示例信息系统中,使用用户的email作为主键。而在数据 仓库中,我们使用一个唯一的技术主键代替原来的主键。后续的流程能够取得这个技术主键,用于纬度表和事实表的关联。在我们的例子中,这个技术主键字段叫做user_id。

在信息系统用户表的字段中,我们需要指定对于纬度比较重要的字段。在我们的例子中,我们需要持续跟踪用户全名、所属公司和性别等信息。

对于第二种纬度,版本字段用于跟踪缓慢变更纬度的不同版本。而日期范围用于表示每个版本存在的期限。如果信息系统能够跟踪记录的变更,这有助于使用Stream Datefield进行更好的数据校验,不过这已经超出本文的范围。通常,默认的已经足够了。



更新第二种纬度表和事实表

现在,第一种纬度已经准备就绪,现在需要做得是填写事实表。在这个流程中,需要更新剩下的纬度表,在需要时,使其技术建准备就绪。

我们以从请求日志中,为事实表提取基本粒度信息,作为工作的起点。

接着,使用Spoon的JavaScript step提取请求日志的时间戳字段,生成日期纬度,代码见附录B:使用JavaScript生成日期纬度。使用Dimension Lookup/Update,我们将这些数据放入数据库,然后使用技术键time_id进行引用。

接下来就是用户纬度。记住,我们在上一步已经对用户纬度进行过更新,所有现在我们应该将其与事实表中的每个请求实体进行关联。通过对用户登录行为与会话的 查询,我们可以将会话与用户实现对应,进而实现用户与请求行为之间的对应。如果会话没有实现与用户的匹配,其键值(email)就设置为NULL,它匹配 一种特殊的情况:未知用户(the unknown user)。由于过滤操作是多线程操作的,因此我们使用Spoon的排序步骤(sort step)对用户信息数据流进行排序。当数据进入“Lookup user_dim“,这股数据流包含一个额外的字段叫做"email",这个字段包含每个请求的email,如果未知则为NULL。记住,我们指定email作为查询主键,所以使用这个字段,转换(transformation)步骤能够为数据流中的每个条目找到一个技术键,最后加入一个额外的字段user_id,就构成了用户纬度表的条目内容。

页面纬度表所需的数据已经保存在请求日志中了,填写这个纬度表的都是层次化的数据,包括域名、路径、页面,最后生成一个技术键字段,就构成了一个页面纬度表的条目。

我们另外加了一个访问来源(Referrer)纬度,这个纬度我们上面没有提到过,与页面纬度相对应。

最后,将填写事实表的数据过滤出来,只包括纬度的技术键和事实元素。将他们插入表request_facts中。

聚合数据

解释如何创建聚合表来加速分析操作。

将所有工作合到一起

通过上面的工作,我们完成了转换(transformation)设计,下面需要使用Kettle的Chef和Kitchen将这三个转换(transformation)顺序结合成一个作业,并在流程中加入日志和调试功能。

工具Chef无需多做解释,因为他的界面与Spoon是一样的。只不过,Spoon是将步骤(step)结合成转换(transformation),而 Chef将转换(transformation)组合成作业。由于Chef的文档很好,所以这里我们只用一个截屏来解释。

在我们的案例中,有两类纬度,因此将数据仓库的填写流程分为两个转换(transformation)阶段。首先,Chef执行更新用户纬度的转换 (transformation)。如果转换失败,它就发送一个包含细节错误信息的邮件;如果转换成功,就进入第二个阶段,更新其他纬度和事实表。在这个 例子中,我希望如果全部工作成功完成也收到一封邮件,因此将最后一步转换连接到Mail。

最后需要说明,Chef可以对作业进行调度。利用命令行工具Kitchen,使Kettle成为一个强大的系统,用于创建、更新和维护数据仓库。

使用数据仓库

本章将讲述如何对数据仓库进行分析。

准备在线分析处理

在结构模型化,我们从采用星形模式建立一个数据立方体开始,数据立方体包含一个事实表将各个纬度表关联到一起。在数据立方体内,每个纬度都能够与其他纬度实现多对多的关联。

这种特殊的数据组织形式,使通过一种广义的表单方式进行数据查询成为可能。这就是OLAP服务器的任务。在我们的案例中,我们将使用开源的关系形OLAP服务器Mondrian完成这个工作。

从关系化到纬度化

上面解释过,数据仓库中的数据采用关系的方式存储。事实表是多个纬度的连接点,每个纬度都有自己的表和数据。在一个OLAP数据立方体中,数据以多维的方式进行组织。

每个数据立方体都包含多个指标(measure),这些指标可以从事实表中得到,用于计算聚合和分组数据。一个数据立方体的指标可以包括诸如:销售额、产 品价格或者这些事实元素的综合等。在非事实化的事实表中,可以没有任何指标。每个数据立方体都有多个纬度。一个纬度是一个查看数据的方向,由关系数据库的 一个一维表构成。最显而易见的纬度当然就是时间了。

每个纬度都可以有一个活多个层次。正如你所期待的那样,通过层次可以纬度的信息进行逐次聚合。例如,在时间纬度中,可以使用天-月-季度-年作为层次。在数据分析过程中,层次对于数据集合和分组是很有用的。

上述概念可以被OLAP服务器用于多维数据查询。下面我将告诉你如何配置Mondrian OLAP服务器来从事这个工作。

使用Mondrian做数据分析

Mondrian OLAP服务器的安装在此就不赘述了。安装完成之后,我们需要告诉它数据仓库的结构。这是由一种XML格式的文档实现的,文档包含OLAP数据立方体信 息,及其纬度、层次和指标信息,以及如何从关系数据库中生成这些信息。在我们的案例中,Mondrian的相关XML模式见附录C:Mondrian XML schema示例。其中,只有一个数据立方体,叫做"Requests",这个立方体直接关联到表“request_facts”,有一个指标和四个纬度。

在事实表中只有一个事实元素,因此我们无需过多关注,而指标也只有一个:每个请求id的数量,当然它永远等于一。

在数据立方体中,我们定义了四个纬度,用户(User)、页面(Page)、访问来源(Referrer),以及时间(Time)。每个纬度都有一个或多个层次。对于每个纬度,Mondrian需要知道是由那个表表示的,以及哪个键是事实表的外链键。

一旦Mondrian知道如何解释数据仓库的关系数据库,它就可以作为一个转换层,将多维数据查询转换到关系数据库。

执行多维查询

Mondrian利用OLAP数据立方体的纬度属性,向数据仓库提出尽可能复杂的问题。为了完成这项工作,Mondrian使用一种叫做MDX的语言,实现将多维变量到SQL转换。其语法如下所示:

SELECT [

[, ...]]
FROM []
[WHERE []]

MDX与SQL不同,SQL查询只能范围二维数据集:一个表,包含固定的列数、多行记录,而MDX查询是针对多维数据集,返回的结果也可以有任何数量的纬度。例如,下面的一个查询可以查询在某些月中,哪些公司访问国我们的信息系统。

SELECT 	{[Time].[Months].Members} ON COLUMNS,

{[Users].[Company Name].Members} ON ROWS
FROM [Requests]
WHERE [Time].[2006]

可视化和展示

最后,最终用户需要通过一个系统看到多维查询得到的各种结果,这可以通过JPivot实现。

JPivot已经包含到Mondrian的发布版本中了,无需多做设置。它的配置也非常简单:只要指定JSP文件使用的数据集,启动查询即可。再进一步, 大家可以考虑Pentaho。很多工程如:JPivot和JFreereports都已经集成到了Pentaho中,更加简化了生成展示界面的工作。

附录A:技术简介

在这一章中,我将简单介绍一些数据仓库创建过程中涉及到的一些关键技术,以及相关工程的连接。

Kettle

http://www.kettle.be

Kettle是一个开源的ETL套件,能够从多种不同的数据源中提取数据,转换后加载到数据仓库。

Kettle包含部分工具:

  • Spoon和Pan用于创建和执行数据转换。
  • Chef和Kitchen用于将多个转换组合为作业,并调度和执行这些作业。

Mondrian

http://mondrian.sourceforge.net

Mondrian是一个关系型OLAP服务器,作为关系数据库之上的一层,执行多维数据查询操作。。

Jpivot

http://jpivot.sourceforge.net

JPivot是一个基于Mondrian的表示层工具。它生成多维查询指令,并将结果以交互式的数据透视表(pivot table)展示出来。

附录B:使用JavaScript生成日期纬度

A dimension present in almost all data warehouses is that of time. Spoon's JavaScript? step makes it easy to extract hierarchical data from date or time fields in the source system. While most of this is described in Spoon's documentation, an example of how to do this is given here. JavaScript code

// The fields we want to calculate

var day_of_month;
var week_of_year;
var month_of_year;
var year;
var quarter;
var name_day;
var name_month;

// Calculate!
day_of_month = dateTime.Clone().dat2str("dd");
week_of_year = dateTime.Clone().Clone().dat2str("ww");
month_of_year = dateTime.Clone().dat2str("MM");
year = dateTime.Clone().dat2str("yyyy");

name_day = dateTime.Clone().dat2str("E").getString();
name_month = dateTime.Clone().dat2str("MMMM").getString();

if(month_of_year <= 3) {
quarter = "Q1";
}
else if(month_of_year <= 6) {
quarter = "Q2";
}
else if(month_of_year <= 9) {
quarter = "Q3";
}
else {
quarter = "Q4";
}

附录C:Mondrian XML schema示例



name="DataWareHouseTest">
name="Requests">
name="request_facts"/>
name="Users"foreignKey="user_id">
hasAll="true"allMemberName="All Users"primaryKey="user_id">
name="user_dim"/>
name="Company Branche"column="companybranche"uniqueMembers="false"/>
name="Company Name"column="companyname"uniqueMembers="false"/>
name="Role"column="role"uniqueMembers="false"/>

hasAll="true"primaryKey="user_id">
name="Sex"column="sex"uniqueMembers="false"/>
name="User"column="email"uniqueMembers="true">
name="First Name"column="firstname"/>
name="Infix"column="infix"/>
name="Last Name"column="lastname"/>



name="Page"foreignKey="page_id">
hasAll="true"primaryKey="page_id">
name="page_dim"/>
name="Domain"column="domain"/>
name="Path"column="path"/>
name="Page"column="page"/>


name="Referrer"foreignKey="referrer_id">
hasAll="true"primaryKey="referrer_id">
name="referrer_dim"/>
name="Domain"column="referrerDomain"/>
name="Path"column="referrerPath"/>


name="Time"type="TimeDimension"foreignKey="time_id">
hasAll="false"primaryKey="time_id">
name="time_dim"/>
name="Year"column="year"type="Numeric"uniqueMembers="true"
levelType="TimeYears"/>
name="Quarter"column="quarter"uniqueMembers="false"
levelType="TimeQuarters"/>
name="Month"column="month_of_year"uniqueMembers="false"type="Numeric"
levelType="TimeMonths"/>

hasAll="true"name="Weekly"primaryKey="time_id"
defaultMember="[Time.Weekly].[All Time.Weeklys]">
name="time_dim"/>
name="Year"column="year"type="Numeric"uniqueMembers="true"
levelType="TimeYears"/>
name="Week"column="week_of_year"type="Numeric"uniqueMembers="false"
levelType="TimeWeeks"/>
name="Day"column="day_of_month"uniqueMembers="false"type="Numeric"
levelType="TimeDays"/>


name="Pages"column="id"aggregator="count"datatype="Integer"formatString="#,##"/>


参考

  • A Dimensional Modeling Manifesto – Ralph Kimball 1997
  • Slowly Changing Dimensions – Ralph Kimball 1996
  • Spoon Documentation – Pentaho 2001-2006

版本介绍

v146 - 1st of September 2006 – Initial release

The first version to be released to the community, still in draft form. I would like to thank my employer, Better be, for giving me the time and resources to work on this document. Without their support, this document would not exist. Also, I would like to thank, in advance, anyone who will contribute to this document in the future. You make open source to what it is today.

- Michel Jansen

v197 - 6th of October 2006

A revision with a lot of the sharp edges removed. 1.Fixed the calculation of quarters in the JavaScript? example – Thanks Paul Keenan 2.Corrected the “Asking questions” section – Thanks Ronald van der Blink

- Michel Jansen

2008年10月16日星期四

虚拟化方案的不完全对比

厂商 qumranet Citrix Micro$oft Vmware SUN
名称 SolidICE、kvm XenSource Hyper-V Vmware xVM(原virtualbox)
操作系统 Linux Linux Windows2008 Windows、Linux Windows、Linux
授权方式 开源 KVM内核模块(GPL),已经是Linux的标准虚拟运算组件。 xen Hypervisor,曾经是Linux标准虚拟运算组件的有力竞争者,但是败给kvm,前景不明朗,即使有citrix撑腰。 无 无 目前还存在一个virtualbox的开源分支,叫做virtualbox-ose,开发相当活跃。
免费


Vmware ESX SUN xVM
商业 SolidICE XenSource Hyper-V 其它产品
虚拟模式 半虚拟化 测试阶段 支持 支持 支持 支持
全虚拟化 不支持 不支持
支持(是全虚拟化的鼻祖) 支持
硬件虚拟化 支持 支持 支持 支持 支持
客户机OS Linux 支持 支持 支持 支持 支持
Windows 支持 支持 支持 支持 支持
其它 支持 支持 支持 支持 支持
远程接入协议 SPICE(VNC的基础上进行了修改)、RDP、XDMCP ICA(专有) RDP(专有,与ICA同源) 无 RDP

2006年12月20日星期三

fsf对vista宣战

自由软件基金会fsf于12月15日建立了一个名为badvista 的网站,对vista宣战。

这个网站好像是plone作的 :)