作者归档:成成

北京地区摩托车驾照学习考试流程分享

Published / by 成成 / Leave a Comment

挨过一个漫长的冬季过完春节,天气逐渐好转,早高峰的路上依旧蜗行牛步,这时候看着在车流中自由穿梭的摩托车羡慕不已,一时兴起觉得自己需要一个合法的摩托车驾驶手续,本人持有C1驾照,但是C1驾照的准驾车型里并不包含摩托车,如果骑摩托车被警察叔叔查获会被按照无照驾驶处理所持有的C1驾照也会被吊销得不偿失,于是开始考虑考取摩托车驾照了,由于持有驾照需要的是增驾(D或是E、F),D驾照是普通三轮摩托车;E驾照普通二轮摩托车;F驾照是轻便摩托车,D驾照的准驾车型可以覆盖E和F,E驾照的准驾车型可以覆盖F,建议大家直接学习D驾照,准驾车型更加丰富而且考试通过率更高,接下去就是开始了增驾摩托车驾照的过程,与大家做个分享供大家参考。

选择驾校

北京能够学习摩托车驾照的驾校很多,比如海淀驾校、东方时尚、北方驾校、老山驾校、公交驾校等,不同的驾校在费用上面会有一定的差异具体查看各家的官网即可,比如海淀驾校整体的价格就比北方驾校贵300元左右,选择一家适合自己且参加考试学习方便的即可,由于我是在海淀驾校学习的驾照下面的描述都是以海淀驾校为例子,相信其他驾校学习考试的过程也都是大同小异。

材料准备

选择好的驾校之后就要准备报名材料了,近期1寸照片8张(蓝底或是白底),报名需要交6张,2张通过考试后办理驾照会用到,身份证原件、居住证原件(非北京户口,部分驾校可以提供代办服务)、驾照(增驾适用,如果原驾照还在实习期内不可以增加)、报名费用、体检费用,备好这些材料就可以找个驾校的报名点或是预约驾校工作人员上门办理报名即可。

学习考试

摩托车驾照的考试跟汽车类似同样要参加4个科目的考试,分为科目一法规考试(50道题100分)、科目二场地考试(单边桥、坡起、绕桩等)、科目三路考、科目四安全文明驾驶知识考试(50道题100分),了解了需要进行哪些考试剩下的就是参加驾校针对考试进行的训练了。

科目一的考试需要参加一个法规培训,在报名完成之后的第一个周六会组织学员参加法规培训考试,摩托车驾照的法规培训没有刷卡因为驾校就没法过卡,但是法培老师会进行多次点名,点名的时候都在的同学可以参加下周二下午组织的科目一考试,满分100分在题库内共选取50道题每题2分,90分以上包含90分算通过考试,关于学习手机安装一个驾考宝典做2-3遍题,之后再看看错题满分通过考试并不是难事。

科目二、三的训练学习会占用大家一点时间,当然如果您是摩托车方面的高手那另当别论,本人之前并不会骑摩托车所以参加了2天的训练学习,由于学习的D驾照,训练和考试车型均为挎斗摩托(如图,嘉陵600边三轮摩托),E驾照的训练和考试车型为二轮摩托(豪爵125),三轮摩托和两轮摩托的科目二、三的考试也是从日常训练的摩托中选择几辆作为考试用车,科目二、三会一起进行考试以及日常的训练也是一起进行。科目二、三的训练教练会直接让学员骑车,教练坐在挎斗里面给进行一圈的讲解注意事项,三轮摩托和两轮摩托的差异是二轮摩托考试和训练需要佩戴头盔参加,且两轮摩托在参加考试的时候除非考试科目必要考试过程中是不能脚挨地面,三轮摩托车有一次车熄火的机会点火继续考试即可,二轮摩托如果熄火除非脚不挨地可以点火继续考试也可以哈,科目二、三的训练同样也不需要刷卡,教练会有个签到的册子参加训练的同学到了之后去签字即可,一个学期的学员会安排从周一下午考试到周日的训练时间,学员可以自行选择时间参加训练,考试的会安排到下周的周一上午进行,考试前确保签到册上面满足训练次数要求即可。考试以及训练的其他注意事项谨遵教练嘱咐即可。科目二、三的考试会安排学员们排队依次参加考试,考试未通过当场会安排再次进行考试,如果还未通过需要学员在单独约下一次考试,三轮摩托学员考试通过率远高于二轮摩托学员,以本人参加的那次考试为例,三轮摩托学员全部通过考试,二轮摩托学员部分同学只能再次电话约考。科目二、三考试通过之后拿着身份证直接去驾校指定的地点约当天下午的科目四考试。嘉陵600

科目四考试,和科目一考试类似,在科目二、三的训练过程中会安排进行一次科目四的培训同学不需要刷卡法培老师会进行点名点名时候再的同学法培老师会帮助其登记记录,只有参加了法规培训的学员才可以参加科目四的考试。科目四题库相较科目一题库数量少了一些,学习方式还是类似。

持照骑车

通过了科目一到科目四的考试当天会获得摩托车驾照,再加上合法手续的摩托车就算是合法骑车了。本人从报名到拿到驾照共用了23天,3月11日报名,4月2日拿到驾照,整体学习考试过程还是非常顺利的,拿到摩托车驾照以后骑车再也不怕被警察叔叔检查了,不过朋友们还是要注意安全,法培老师说的好什么叫安全?无危为安,无损为全。大家路上切记带好护具安全驾驶。

关于系统重构的10点经验总结

Published / by 成成 / Leave a Comment

做我们的日常工作中系统重构都应该是最让人头疼的工作了,无论是错综复杂还是经意简单的系统在发展的过程中都会经历重构,而系统重构也是任何一个技术团队都无法回避的问题,在我服务的多家公司几乎每家公司都经历了一次甚至多次系统的重构,本文就我在多年的重构工作中总结出来的几点建议分享给各位朋友,希望能够给朋友们带来帮助。

1、重构确定并且聚焦目标

首先我相信我们大家都确信系统重构是会有巨大的成本投入的,业务可能需要暂缓、新系统引入的问题(BUG)带来业务的不稳定、研发人员以及配合人员的投入还有各种隐性成本等等,我们服务的是一家商业公司获取利润是最终目的,在投入具体成本做一个项目就肯定要获得收益的。重构的目标一定要能够获得更大的提升无论是业务流程还是系统性能或是其他方面,如果仅仅一个很小的改善完全没有如此的大费周章,权衡好成本是否能够获得良好的收益。

无论如何进行系统重构都是一次伤筋动骨的过程,是涅槃重生还是飞蛾扑火,完全取决我们项目执行的过程中是否明确了目标且一直聚焦于目标的实现,保持目标的聚集是能否取得良好结果的必要促销,如果我们仅仅确立了目标没有聚集于目标在多个非重要的节点投入较大资源必然会导致我们对目标的投入降低,工作中的原始资本投入都是8个小时,当然如果每个人都愿意乐于加班的话另外讨论,而我们的实际情况往往是8个小时都是不够用的,这就更加需要我们明确目标聚焦目标,把有限的资源投入到最重要的事情中,才能获得既定目标的良好结果。

2、重构要有可量化的指标

团队确认了重构的目标之后,下一步一定要将目标量化,确定好目标之后也就能够确认边界,围绕在边界内要将需要实现的事项一一罗列出来,并且尽可能对每个实现制定可以用数据清晰表现出来的指标,比如用户操作的响应时间缩短到100毫秒、单元测试的覆盖率达到80%、发现问题时长降低到30分钟以内等等,有了明确的数据指标我们才能评估最终是否获得了良好收益,这些目标必须要在重构团队,包括产品、研发、测试等等,甚至包括业务方在内达成一致,是团队的目标清晰明了,防止出现过度或是不达标是最终不能获得良好收益。

3、重构要有更好的质量

既然决定了要对系统进行一次重构,那么我们肯定要做到的就是要比之前做的更好,如果之前接口响应时间在100毫秒,而经过重构之后反而减低到了200毫秒以上那么岂不是很难看,大家辛苦付出的努力是不是也更加不值得。而进行重构往往是一件十分引人注目的事情,一个微小的问题反而容易在众人注目下变得非常严重的问题。为了减少引起不必要的麻烦,重构团队就更加要注重各个方面的问题,无论是系统性能、用户体验还是BUG数量等

4、重构之前要和业务方沟通

技术团队进行系统重构的工作的时候往往忽略掉了业务方,认为这是技术团队内部的事情,不需要知会业务方,这个想法是非常错误的,进行重构的目标就是为了改善改进业务流程,而不去和业务方提前沟通进行闭门造车,最后的结果很可能和进行重构的初衷背道而驰。进行系统重构首先我们必须了解现有系统的业务需求,是否有待改进的业务需求点,是否有新的业务诉求等这些需求往往会影响到我们重构的进度和目标,甚至出现南辕北撤的事情。
技术团队和业务方往往对待问题的出发角度不同,思考问题的方式也不同,在进行重构之前和业务方沟通获得业务方的支持,往往能够事半功倍。
例如,我的团队在进行一块业务系统重构的时候进入到了系统切换的试运行的阶段,由于拿出的方案给到业务方无法被业务方接受,业务方提出的解决方案我们还需要进行再次开放对整个项目进度影响了足足一个月时间之多。吸取教训的我们在进行下一个项目的时候提前和业务方进行了沟通,业务方从他们的角度给予了很多的意见和建议以及业务未来的发展方向的指引,我们发现这些建议和意见帮助我们更好理解业务的同时也大大的降低了我们工作量,减少了我们很多冗余的设计。

5、重构应该才用迭代的方式

参与过重构项目的朋友都知道,重构项目往往是个时间跨度很长的工作,少则一两个月多则一年半载都有,如果不将整个重构进行合理拆分,而是采用全部开发完成,再进行系统切换的方式会对整个重构引入很大的风险,首先长时间的时间跨度内业务会进行持续变更,其次团队面临长时间没有结果输出面临来自各个方面的压力还有系统问题持续累积,这种蒙头狂奔的方式往往造成了项目失败或是目标便宜,而采用迭代方式进行重构,可以以更小的颗粒度持续交付工作成果,交付-试用-反馈-调整,持续有交付,持续有反馈,持续调整能够保证团队的目标不会偏移,形成一个正向循环,保证最后的重构目标。

6、重构要清晰了解旧系统

知己知彼,百战不殆,系统重构是一个与旧系统对抗的过程,不对旧系统的弄的清清楚楚怎么能够比旧系统做的更好呢?其实了解现有系统是一个学习的过程,如果有旧系统的开发人员还在公司那么就事半功倍了,旧系统的开发同学帮忙给做次分享省去了我们重构团队很多的工作,比直接去读代码更能清晰明了的了解到旧系统的相关知识以及有哪些需求点和应该注意的问题等等,通过学习和了解旧系统设定目标基准值避免引入老旧问题也是避免重蹈覆辙的一个好办法。

7、重构要提前规划系统切换方案

不知道朋友有没有遇到过重构完系统发现如果进行新旧系统的切换是个难题,反正我是遇到过,由于没有提前做好规划和切换步骤导致最后临时抱佛脚,开始使用各种奇葩办法做系统切换,有的还需要增加额外工作量甚至各种办法的刷脸求人,总之这不是一个很好的体验。系统切换往往是在重构中被我们忽略的一个步骤,但是这是非常重要的一个环节,在做最初的计划就应该考虑到如何进行系统切换,一个设计好的切换方案也应该贯穿重构始终,避免因为切换方案引起服务不可用或是引入系统BUG。尤其是前期整个团队付出巨大努力取得了一定成果的时候在最后一步切换的时候出现问题对团队是个非常大的打击,也使得业务方对团队失去信心,带来很不必要的麻烦。

8、重构高度重视系统数据

一次系统重构大多数情况下会涉及到数据结构的修改,对数据结构进行修改必然引入很大的风险,尤其在一些老旧的业务系统重构精简业务去掉冗余数据的时候,往往需要将老数据的业务数据重新写入到新系统的数据库。重构的目标是为了比旧系统更好无论是性能还是业务方面,如果我们对数据的操作导致外部依赖旧系统的业务无法正常运行那将是影响SLA指标的问题还有,说到系统数据有些同学可能仅仅关注的是业务数据其实数据也包含了系统运行所产生的日志数据,无论新旧系统的日志数据都是很重要的,如果因为重构影响到数据的读取、处理、分析那么岂不是得不偿失的事情。

9、重构要才用成熟的技术选型

技术选型是重构工作的基石,选择一套成熟稳定的技术方案是重构项目完成的必要条件。有些时候我们引入最新版的数据库虽说会有性能提升但是也会引入一定的不稳定因素,之前我们团队在使用MongoDB的一个新版本的时候发现主从库的数据并不能很好的同步出现过丢失数据的情况,进入社区发现这个版本使用的用户很多都反馈了这个问题,这时候我们不得不选择了大多数人共同的一个选择降低了一个版本来解决问题,相信此类情况比比皆是。在不是很成熟的方案带来并不显著的性能提升反而还会引入不确定的风险的时候我们需要权衡利弊得失,重构更是要保证系统的稳定性。
技术方案能否有足够强大的支撑也是我们需要考虑的一个方面,现在我们团队面对的重构是从单体式架构往微服务转变,旧系统的版本构建在是PHP语言上,新的系统我们由两个选择继续选择用PHP进行重构或是才用公司统一的微服务框架,我们毫不犹豫的选择了使用公司统一的微服务,这样做有几个显而易见的好处。
1、和公司内部进行交互更加方便快捷;
2、可以直接获取成熟的经验;
3、基础服务有公司级的支持;
以上的好处显然对我们能否成功重构系统并且获得足够的帮助起到了显著的帮助,反而才用PHP进行微服务,公司内部并无成功经验可以借鉴,业内也并无太多可靠的方案可以进行选择。一个成熟可靠的的技术方案是我们能否更进一步的保障和基石。

10、重构更加关注重视团队成员

参与过重构的同学都知道重构工作是一项枯燥乏味的工作,往往周期长、复杂度、 难度大、牵扯广、优先级低而且很有可能是一件费力不讨好的工作,开发一个业 务方期待的新功能、新模块往往比一场翻天覆地的重构更能引起业务方的重视也 更容易获取良好结果与反馈,反而不需要承担大多的压力。而越是面对这样的情 况越是需要加大对团队的鼓励增强团队的信心,消除团队的疑虑困惑,给予团队 持续的鼓励,给整个团队注入正能量,让团队保持积极向上的团队氛围,即使面 对各种困难、问题,也始终对团队保持信心保持乐观,让大家轻松愉快的投入到 重构工作中,尽量不担负额外的压力。

以内内容均为工作中的总结反思,分享给大家希望以上的这些总结能够对大家有所帮助,文章所讲述的内容如有不足之处还望指出。

log4php日志框架的配置使用介绍

Published / by 成成 / Leave a Comment

随着系统和业务的复杂度提升我们会对日志进行各种分类处理如通过日志的级别分类或是对不同的业务的日志进行分类处理,即使面对以上的需要我们仍然需要有一个统一的日志格式,这样就需要我们有一个标准的日志模块来完成这些工作,然而我们也希望这个日志模块是性能优良且方便易用的。

Java有一个比较出名的日志组件log4j,PHP语言也有类似的日志框架,同样来自于Apache的log4php是一个多功能的为PHP使用的日志框架。和log4j类似,通过log4php我们也可以控制日志信息输送的目的地是控制台、文件、数据库甚至是套接口服务器、syslog守护进程等,同样我们也可以控制每一条日志的输出格式;通过定义日志信息的级别,我们能够更加有效细致地控制日志的生成过程。更加惊喜的是以上叙述的这些功能甚至不需要我们修改代码,而是通过一个配置文件来灵活地进行配置。

安装介绍

log4php提供了两种安装方式,一是通过直接下载源码包,Apache log4php – Download;二是通过PEAR渠道安装。

PEAR方式安装命令

pear channel-discover pear.apache.org/log4php
pear install log4php/Apache_log4php

目录结构

├───apidocs – API生成文档
└───src

├───assembly – Maven的配置
├───changes – 更新日志
├───examples – 各种用法示例
├───main
│       └───php – 主要源码
├───site – 网站源码
└───test – 单元测试

配置介绍

log4php支持XML、PHP以及Properties三种配置文件,我们今天主要通过Properties方式的配置文件来讲解,此种方式的配置较为全面。如果不在日志记录前调用Logger::configure()方法进行配置,log4php使用默认方式进行配置

日志输出方式

名称                                     介绍
LoggerAppenderConsole         控制台,标准输出或标准错误流。
LoggerAppenderEcho             控制台,通过PHP的echo方式输出
LoggerAppenderFile               文件
LoggerAppenderDailyFile        文件(通过日志生成新文件)
LoggerAppenderRollingFile     文件 (通过尺寸设置生成新的日志文件).
LoggerAppenderMail              通过电子邮件发送日志,整个日志在一个电子邮件发送。
LoggerAppenderMailEvent      通过电子邮件发送日志,每条日志通过单独的电子邮件发送。
LoggerAppenderMongoDB      MongoDB
LoggerAppenderNull              忽略所有的日志事件
LoggerAppenderPDO             数据库
LoggerAppenderPhp              通过使用PHP trigger_error()函数PHP用户级的消息
LoggerAppenderSocket          通过套接口输出日志
LoggerAppenderSyslog          syslog

日志内容输出格式方式

名称                                   介绍
LoggerLayoutHTML              输出到HTML表格中
LoggerLayoutPattern            灵活格式,通过一个字符串配置
LoggerLayoutSimple             简单格式,不可配置
LoggerLayoutSerialized         输出序列化对象
LoggerLayoutTTCC               包括时间,主题,类别和嵌套诊断上下文的 (不建议使用)
LoggerLayoutXml                 输出到XML文件

示例说明

示例一

配置示例

;定义输出方式名称default
log4php.appender.default = LoggerAppenderEcho
log4php.appender.default.layout = LoggerLayoutSimple

;定义一组新的输出方式名称为test
;日志输出方式设置
log4php.appender.test = LoggerAppenderDailyFile
;日志内容格式设置
log4php.appender.test.layout = LoggerLayoutPattern
;日志内容参数设置(日期 PID 日志级别 日志名称 日志文本 换行符)
log4php.appender.test.layout.ConversionPattern = “%d{Y-m-d H:i:s.u} [%t] %p %c: %m%n”
;日志文件名称配置
log4php.appender.test.datePattern = Ymd
;日志文件路径配置
log4php.appender.test.file = /var/log/daily_%s.log

;日志输出方式以及输入级别设置
log4php.rootLogger = DEBUG, default

如果设置为已下值,日志可同时使用default和test两个输出定义进行记录
log4php.rootLogger = DEBUG, default,test

代码示例

<?php

require_once dirname(__FILE__) . ‘/log4php/main/php/Logger.php’;
Logger::configure(dirname(__FILE__) . ‘/log4php.properties’);
$logger = Logger::getLogger(‘exception’);
$message = ‘hello world!’;
$logger->error(‘error,’ . $message);//会产生记录
$logger->info(‘info,’ . $message);//会产生记录
$logger->trace(‘trace,’ . $message);//不会产生记录,因为设置的日志级别DEBUG,只有高于等于DEBUG级别的日志才会记录

输出示例

2016-12-15 16:25:55.55 [121215] ERROR exception: error,hello world!
2016-12-15 16:25:55.55 [121215] INFO exception: info,hello world!

示例二

配置示例

;定义输出方式名称default
log4php.appender.default = LoggerAppenderEcho
log4php.appender.default.layout = LoggerLayoutSimple

;定义一组新的输出方式名称为test
;日志输出方式设置
log4php.appender.test = LoggerAppenderDailyFile
;日志内容格式设置
log4php.appender.test.layout = LoggerLayoutPattern
;日志内容参数设置(日期 PID 日志级别 日志名称 日志文本 换行符)
log4php.appender.test.layout.ConversionPattern = “%d{Y-m-d H:i:s.u} [%t] %p %c: %m%n”
;日志文件名称配置
log4php.appender.test.datePattern = Ymd
;日志文件路径配置
log4php.appender.test.file = /var/log/test_daily_%s.log
;日志输出方式以及输入级别设置
log4php.logger.test = INFO, test

;定义一组新的输出方式名称为pro
;日志输出方式设置
log4php.appender.pro = LoggerAppenderDailyFile
;日志内容格式设置
log4php.appender.pro.layout = LoggerLayoutPattern
;日志文内容式参数配(日期 PID 日志级别 日志名称 日志文本 换行符)
log4php.appender.test.layout.ConversionPattern = “%d{Y-m-d H:i:s.u} [%t] %p %c: %m%n”
;日志文件名称配置
log4php.appender.pro.datePattern = Ymd
;日志文件路径配置
log4php.appender.pro.file = /var/log/pro_daily_%s.log
;日志输出方式以及输入级别设置
log4php.logger.pro = INFO, pro

代码示例

<?php
require_once dirname(__FILE__) . ‘/log4php/main/php/Logger.php’;
Logger::configure(dirname(__FILE__) . ‘/log4php.properties’);

/*
* 使用名称为test的方式处理日志
*/
$logger = Logger::getLogger(‘test’);
$message = ‘hello world!’;
$logger->error($message);//会产生记录

/*
* 使用名称为pro的方式处理日志
*/
$logger = Logger::getLogger(‘pro’);
$message = ‘Hey, beautiful!’;
$logger->error($message);//会产生记录

输出示例

/var/log/test_daily_20161215.log文件

2016-12-15 16:25:55.55 [121215] ERROR test: hello world!

/var/log/pro_daily_20161215.log文件

2016-12-15 16:25:55.55 [121215] ERROR test: Hey, beautiful!

log4php的配置文件十分灵活和简单,以上的只是很简单的两个示例,还不能全面的展示出来log4php配置方面的简单易用以及灵活性,仍然希望这能够对大家有所帮助,log4php的官方提供了良好的文档以及十分丰富的API,几乎满足了我们对于日志模块需要的全部需求,大家也可以通过查阅相关文档调整配置做出自己需要的日志模块。

log4php文档地址:http://logging.apache.org/log4php/index.html

希望这篇文章对你有所帮助,如果没有任何帮助抱歉浪费了你的阅读时间但是我不负任何责任,如有不足支持还望指出

给开发工程师关于日志记录的建议

Published / by 成成 / Leave a Comment

摘要

对于工程师而言懂得记录合理正确的日志是件很艰巨的任务。日志是记录必要的信 息和数据,方便问题定位和追踪,给我们足够的依据解释和发现问题,以及帮我们清晰 反映出应用的运行状况,这或许能够决定一个工程师是升职还是被开除。记录日志也是 有一定原则或是技巧的,并不是把所有内容有加以记录就可以了,一是可能收到运维工 程师的抗议;二是记录过多内容反而不容易查找关键信息,说来我们的日志记录的简单 可依赖即可,简单可以依赖的关键性数据。

一.日志要分级

日志一定要分级。多个级别的日志等级TRACE、DEBUG、INFO、NOTICE、 WARNING、ERROR、FATAL等,不同级别的日志应当分类处理,在大型应用的海量 日志面前不分级的日志处理起来非常麻烦,我们必须要对日志进行分级分类处理,清楚的明白哪些级别的日志需要时刻关注,影响到了应用的正常运行,有些日志只是帮我们在记录应用的运行状态。

二.日志记录必要的信息即可

日志记录必要的信息即可,无意义的信息必须要排除在日志之外,开发工程师作为对程序最了解的人如果在记录含糊不清的日志只会增加我们查询关键信息的困难,且过多的内容记录也会招致运维工程师的反感和增加应用运行的成本,我们要明白当应用出现问题的时候日志是你唯一可以依赖的,请让保存记录最关键的信息。

三.日志要让其他人也能看懂

为什么要记录日志,是因为有一天我们要去读他,而读他日志的不一定是谁,有一定加密属性的日志读起来总会给我们带来很大困惑,请善待日志的读者,因为每个人都会是日志的读者。
1.排版整洁有序,格式统一规范。随笔式的日志看起来会很麻烦,给日志读者增加很多困难。
2.采用关键字来突出显示如:时间、操作名称等,让读者能够轻松通过关键字来精确定位日志内容。

四.关于程序中加入日志的方法

千万不要自己写个记录日志的方法!千万不要自己写个记录日志的方法!千万不要自己写个记录日志的方法!重要的事情说三遍,绝对不要这么做,即便是用打印输入或者是自己 写入到日志文件中,第一个这么做的朋友也会影响其他同事——首先,这会让你的代码不那么美;其次也会给你的运维工程师带来很大麻烦。每个人都自己写个日志会很容易造成日志 个格式不统一,这会给日志的收集分类带来很大麻烦,PHP有不少第三方的log类库弥补了上述缺陷,如log4php、plog、Analog等还有内置error_log、syslog函数功能强大且性能 极好,用Java开发也有很多选择,例如Log4j、SLF4J、和Logback等其他语言如Python、ruby也有相应的日志类库或是组件,请调用标准类库来完成日志记录。

五.日志要做到方便解析

日志记录下来一定要做到可以方便解析,因为有些时候需要做到报警或是数据提取,这 些功能往往是需要自动化实现的,如果没有一个方便解析的日志实现起来就增加了很多成本。如下,日志记录了时间、日志级别、脚本、IP地址,以及数据:
2015-12-15 12:00:00ERRORlist.php127.0.0.1PAGE=1&NUM=500 解析以上日志是不是需要正则表达式或是更麻烦的程序逻辑来处理?答案是肯定的,如果换一种方式,很可能需要很少的工作就能达到我想要的效果。如下:
2015-12-15 12:00:00||ERROR||list.php||127.0.0.1||{‘PAGE’:1,’NUM’:500} 这样解析起来awk -F‘||’就可以轻松解决了。

总结

希望这篇文章对您在开发过程中记录日志有所帮助,如果有什么遗漏之处还望见谅。看了这篇文章之后发掘没有任何帮助,抱歉我概不负责。

最苦与最乐

Published / by 成成 / Leave a Comment

  梁启超

  一九二二年八月十二日《时事新报·学灯》

  人生什么事最苦呢?贫吗?不是。失意吗?不是。老吗?死吗?都不是。我说人生最苦的事,莫苦于身上背著一种未了的责任。人若能知足,虽贫不苦;若能安分(不多作分外希望),虽然失意不苦;老、死乃人生难免的事,达观的人看得很平常,也不算什么苦。独是凡人生在世间一天,便有一天应该的事。该做的事没有做完,便像是有几千斤重担子压在肩头,再苦是没有的了。为什么呢?因为受那良心责备不过,要逃躲也没处逃躲呀!

答应人办一件事没有办,欠了人的钱没有还,受了人的恩惠没有报答,得罪了人没有赔礼,这就连这个人的面也几乎不敢见他;纵然不见他的面,睡里梦里,都像有他的影子来缠着我。为什么呢?因为觉得对不住他呀!因为自己对他的责任,还没有解除呀!不独是对于一个人如此,就是对于家庭、对于社会、对于国家,乃至对于自己,都是如此。凡属我受过他好处的人,我对于他便有了责任。凡属我应该做的事,而且力量能够做得到的,我对于这件事便有了责任。凡属我自己打主意要做一件事,便是现在的自己和将来的自己立了一种契约,便是自己对于自己加一层责任。有了这责任,那良心便时时刻刻监督在后头,一日应尽的责任没有尽,到夜里头便是过的苦痛日子;一生应尽的责任没有尽,便死也带著苦痛往坟墓里去。这种苦痛却比不得普通的贫困老死,可以达观排解得来。所以我说人生没有苦痛便罢,若有苦痛,当然没有比这个加重的了。

翻过来看,什么事最快乐呢?自然责任完了,算是人生第一件乐事。古语说得好:“如释重负”;俗语亦说是:“心上一块石头落了地”。人到这个时候,那种轻松愉快,直是不可以言语形容。责任越重大,负责的日子越久长,到责任完了时,海阔天空,心安理得,那快乐还要加几倍哩!大抵天下事从苦中得来的乐才算真乐。人生须知道有负责任的苦处,才能知道有尽责任的乐处。这种苦乐循环,便是这有活力的人间一种趣味。却是不尽责任,受良心责备,这些苦都是自己找来的。一翻过去,处处尽责任,便处处快乐;时时尽责任,便时时快乐。快乐之权,操之在己。孔子所以说:“无入而不自得”,正是这种作用。

然则为什么孟子又说:“君子有终身之忧”呢?因为越是圣贤豪杰,他负的责任越是重大;而且他常要把这种种责任来揽在身上,肩头的担子从没有放下的时节。曾子还说哩:“任重而道远”,“死而后已,不亦远乎?”那仁人志士的忧民忧国,那诸圣诸佛的悲天悯人,虽说他是一辈子感受苦痛,也都可以。但是他日日在那里尽责任,便日日在那里得苦中真乐,所以他到底还是乐,不是苦呀!

有人说:“既然这苦是从负责任而生的,我若是将责任卸却,岂不是就永远没有苦了吗?”这却不然,责任是要解除了才没有,并不是卸了就没有。人生若能永远像两三岁小孩,本来没有责任,那就本来没有苦。到了长成,责任自然压在你的肩头上,如何能躲?不过有大小的分别罢了。尽得大的责任,就得大快乐;尽得小的责任,就得小快乐。你若是要躲,倒是自投苦海,永远不能解除了。

python import this python 哲学

Published / by 成成 / Leave a Comment


Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>>

Beautiful is better than ugly.
优美胜于丑陋。
Explicit is better than implicit.
明了胜于晦涩。
Simple is better than complex.
简单胜过复杂。
Complex is better than complicated.
复杂胜过凌乱。
Flat is better than nested.
扁平胜于嵌套。
Sparse is better than dense.
间隔胜于紧凑。
Readability counts.
可读性很重要。
Special cases aren’t special enough to break the rules.
即便假借特例的实用性之名,也不可违背这些规则。
Although practicality beats purity.
虽然实用性次纯度。
Errors should never pass silently.
错误不应被无声的忽略。
Unless explicitly silenced.
除非明确地沉默。
In the face of ambiguity, refuse the temptation to guess.
当存在多种可能,不要尝试去猜测。
There should be one– and preferably only one –obvious way to do it.
应该有一个 – 最好只有一个 – 明显的能做到这一点。
Although that way may not be obvious at first unless you’re Dutch.
虽然这种方式可能不容易,除非你是 Python 之父。
Now is better than never.
现在做比不做好。
Although never is often better than *right* now.
虽然过去从未比现在好。
If the implementation is hard to explain, it’s a bad idea.
如果这个实现不容易解释,那么它是个坏主意。
If the implementation is easy to explain, it may be a good idea.
如果这个实现容易解释,那么它或许是个好主意。
Namespaces are one honking great idea — let’s do more of those!
命名空间是一种绝妙的理念,我们应当多加利用。

Ubuntu下安装GoAccess过程中对源代码编译时产生错误的处理方法

Published / by 成成 / Leave a Comment

前几日在VPS上面重新安装了下GoAccess,以前博主为图省事直接用的apt-get install goaccess进行的安装,没有对源代码进行编译安装,在Ubuntu下编译的时候不能通过报出了两个错误,博主于是发邮件给GoAccess官方需求解决方法,很快得到的回复。对了GoAccess官方邮件地址是goaccess(at)prosoftcorp.com,有问题可以直接给他们发邮件,很快就会得到答复!
我安装的时候产生的错误是这样的

gcc -g -Wall -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include   -lmenuw -lncursesw -lm  -o goaccess settings.o error.o commons.o goaccess.o parser.o ui.o util.o  -lglib-2.0 -lmenuw -lncursesw 
ui.o: In function `create_graphs':
/usr/local/goaccess/ui.c:300: undefined reference to `log10'
/usr/local/goaccess/ui.c:300: undefined reference to `floor'
ui.o: In function `data_by_total_hits':
/usr/local/goaccess/ui.c:390: undefined reference to `log10'
/usr/local/goaccess/ui.c:390: undefined reference to `floor'
collect2: ld returned 1 exit status
make[1]: *** [goaccess] Error 1
make[1]: Leaving directory `/usr/local/goaccess'
make: *** [all] Error 2

官方的给出的解决办法是
首先安装autoconf,如果没有安装的话

apt-get install autoconf

打开Makefile.am文件查看是否有如下两行的内容,没有则进行添加

AM_CFLAGS = -g -Wall @GLIB2_CFLAGS@
goaccess_LDADD = -lm

修改configure.ac文件

vi configure.ac

注释掉AM_INIT_AUTOMAKE,然后执行以下命令

autoheader
autoconf

再次修改configure.ac文件

vi configure.ac

将AM_INIT_AUTOMAKE注释去掉,然后执行以下命令

aclocal
automake -a
autoconf

再次进行编译顺利通过,GoAccess官方建议用git获取源代码

git clone git://goaccess.git.sourceforge.net/gitroot/goaccess/goaccess

我也是通过这种方式获取的源代码进行修改之后编译安装顺利通过

简述uWSGI+Nginx+Python 搭建过程

Published / by 成成 / 简述uWSGI+Nginx+Python 搭建过程有1条评论

由于服务器上面的Python和Nginx都已经安装完毕,咱们就直接叙述uWSGI的安装,对照各方面的测试数据uWsgi在性能方面相对其他方式还是比较不错的!他是一个快速的、纯C语言开发的、自维护的、对开发者或是系统管理员友好的应用程序服务器。

官方网址:http://projects.unbit.it/uwsgi/

文档地址:http://projects.unbit.it/uwsgi/wiki/Doc

准备

cd /usr/local
wget http://projects.unbit.it/downloads/uwsgi-1.0.2.1.tar.gz

安装

tar zxvf uwsgi-1.0.2.1.tar.gz
cd uwsgi-1.0.2.1/
python uwsgiconfig.py --build

配置

cp nginx/uwsgi_params /usr/local/nginx/conf/
vi /usr/local/nginx/conf/nginx.conf

编辑Nginx配置文件添加,uWSGI监听8000端口,这个原理跟PHP的fastcgi相同

    server {
        listen        80;
        server_name py.wuwangwo.net;

        location / {
            root  /data/htdocs/py.wuwangwo.net;
            include uwsgi_params;
            uwsgi_pass 127.0.0.1:8000;
        }

        access_log  /data1/logs/py.wuwangwo.net.access.log;
    }

重新启动Nginx

/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf -s reload

配置web站点

cd /data/htdocs/py.wuwangwo.net
vi uwsgi.xml

编辑uWSGI配置文件,他也同样支持.ini文件等的配置形式,个人习惯不同,具体可以参照官方示例:http://projects.unbit.it/uwsgi/wiki/Example


127.0.0.1:8000
myuwsgi

/data/htdocs/py.wuwangwo.net
2

编辑web.py文件

#!/usr/bin/env python

import os
import web

urls = ('/(.*)', 'hello')

app = web.application(urls, globals())

class hello:
    def GET(self, name):
        if not name:
            name = "World"
        return "Hello" + name + "!"

application = app.wsgifunc()

启动uWSGI,添加–daemonize参数以后台方式运行

/usr/local/uwsgi-1.0.2.1/uwsgi -x /data/htdocs/py.bukaopu.org/uwsgi.xml --daemonize /data/htdocs/py.wuwangwo.net/uwsgi.error.log

停止uWSGI

killall -9 uwsgi

MongoDB之no db response数据库没有响应

Published / by 成成 / MongoDB之no db response数据库没有响应有1条评论

今天查看PHP的error log有很多错误产生,有Fatal error也有Warning,本着错误的级别先开始处理Fatal error除了几条还被搜索机器人抓取的不在使用的页面产生这种错误外,发现了一个多行的Fatal error仔细查看下是:

[17-Jan-2012 11:16:19] PHP Fatal error:  Uncaught exception 'MongoCursorException' with message 'no db response' in XXXXX.php:194

乍一看是为捕获抛出的异常,异常的错误信息是’no db response’数据库没有响应,接下去查看代码:

省略...
$query = array('type' => 5);
$cursor = $collection->find($query);
foreach($cursor as $key => $val) {//出错的行
	省略...
}
省略...

变量$cursor为查询MongoDB的返回结果,但是抛出的异常是’MongoCursorException’异常信息是’no db response’,查看PHP手册解释是:This may not even be an error, for example, the database command “shutdown” returns no response. However, if you were expecting a response, this means the database didn’t give one.坑爹的PHP手册上来就说:This may not even be an error(这甚至有可能不会是一个错误),for example, the database command “shutdown” returns no response.(例如,数据库输入’shutdown’命令而没有获得相应)。
访遍Google、百度没有获得满意的答案,不过问题应该已经比较清晰出现在了MongoDB或是网络上面,于是继续想办法查找问题中,截止到博文发布还没有找到问题原因!

GoAccess,Apache/Nginx 日志统计分析软件

Published / by 成成 / GoAccess,Apache/Nginx 日志统计分析软件有2条评论

 

什么是GoAccess?

GoAccess是运行在Unix系统终端,开源、实时分析Apache日志(其实也能够分析Nginx日志)并且能够动态呈现的软件。它为系统管理员提供了一个快速、有价值的HTTP统计,动态的可视化的服务器报告。

它是做什么以及如何工作?

从本质上讲,GoAccess的工作方式是,它将解析众所周知的Apache访问日志文件 access log,GoAccess通过解析日志收集的数据,将会显示它的控制台或某个终端。收集到的信息或生成的报告将显示给在视觉、交互窗口的系统管理员用户。报告包括:

  • 综合统计
  • 访客排行榜
  • 请求文件排行榜
  • 请求的静态文件排行榜,如图片、JS文件、CSS文件等
  • 访问来源
  • 404页面
  • 访问者的操作系统
  • 访问者的浏览器
  • 浏览器和蜘蛛(搜索爬虫)
  • 主机,反向DNS,IP位置
  • HTTP状态码
  • 推介网站
  • 搜索关键词
  • 显示时不同的配色方案
  • 无限制日志文件的大小(决定了GoAccess的打开速度)

日志文件格式

GoAccess可以解析Apache的日志格式,通用日志格式(CLF)和组合日志格式(XLF/ ELF),包括虚拟主机. 它也能够解析Nginx日志. (如果你按照Apache日志的格式配置了Nginx日志)

GoAccess主页 http://goaccess.prosoftcorp.com/

安装方法

1、安装GoAccess需要一些系统支持库

Ncurses 提供字符终端处理库,包括面板和菜单
GLib C语言的函数库(大于2.0的版本)
GeoIP 通过IP,定位他的经纬度,国家/地区,省市,甚至街道等位置信息。(如果不需要这个不是必须的,配置时候去掉这个选项 –enable-geoip)

CentOS下yum安装

yum install ncurses-devel
yum install glib2-devel

Ubuntu下apt安装

apt-get install libglib2.0-dev
apt-get install libncursesw5-dev

2、安装GoAccess

CentOS下安装

wget http://sourceforge.net/projects/goaccess/files/0.4.2/goaccess-0.4.2.tar.gz
tar zxvf goaccess-0.4.2.tar.gz
cd goaccess-0.4.2
./configure --enable-utf8
make
make install

Ubuntu下安装

apt-get install goaccess

GoAccess使用介绍

启动参数介绍:

  • -b 流量消耗统计,如果想要提高解析速度,不要开启这个选项。缺省值为不开启此选项
  • -f 日志文件路径。
  • -s HTTP 状态码报告,为了能够更好的解析日志,选项被默认关闭。
  • -e 指定IP地址的访问统计。
  • -a 通过代理的请求统计。

菜单介绍

  • F1 帮助菜单
  • F5 刷新
  • q 退出当前口窗、菜单、或是当前查看的选项
  • o 打开当前的选项、菜单
  • c 改变窗口配色(目前只有两种 默认和绿色)
  • SHIFT + TAB 从当前选定模块向后切换
  • RIGHT 打开当前选中模块,查看详细信息
  • s 通过日期排序,只会在访问请求模块起作用
  • S 通过点击次数排序,只会在访问请求模块起作用
  • / 查看详细信息的窗口进行搜索
  • n 通过/进行查找后,查找下个匹配的内容的位置,如果没有则在窗口底部显示“search hit BOTTOM”
  • t 在查看详细信息窗口,移动指针到最顶部
  • b 在查看详细信息窗口,移动指针到最底部

使用实例

  • 最简单、快速的使用方式
goaccess -f /data1/logs/blog.wuwangwo.net/access.log
  • 产生完整、全面统计数据的使用方式
goaccess -f /data1/logs/blog.wuwangwo.net/access.log -a -s -b
  • 通过管道的方式将更多access log 通过GoAccess解析
zcat access.log.*.gz | goaccess

或者

zcat -f access.log* | goaccess
  • 另外一种通过管道使用GoAccess解析日志的方式
sed -n '/05\/Dec\/2010/,$ p' access.log | goaccess -s -b
  • 低优先级运行GoAccess的方式
nice -n 19 goaccess -f access.log -s -a -b
  • 如果你只把GoAccess安装到了一台服务器上
ssh user@server 'cat /var/log/apache2/access.log' | goaccess -s -a -b

注意事项

  1. 每一个详细信息窗口,只显示300条数据
  2. GoAccess 通过管道解析日志时将禁用实时解析的功能

总结

GoAceess 不是很大的一款软件却有着强大的功能即使软件可能还有些BUG,软件的更多介绍信息请查看GoAccess的官方网站«./GoAccess»,当前版本的官方手册页面 Man Page