54chen Twitter Memo 2011-07-10

    持续构建工具hudson使用手记
http://goo.gl/fb/Vpbh2 # 大家手里的项目,除了DAO/biz/service/controller的架子的,还有什么样子的?都是什么情况下出来的? # 突然回想,rose+jade+ice的基础架构完成后,还需要autoGenCode的机器人,这样,全公司工程师都是架构师,大家商量的是数据结构的设计,让代码自动生成。 # 54chen Twitter memo 2011-07-03 http://goo.gl/fb/rxaw5 #

持续构建工具hudson使用手记

hudson hudson是一个强大的持续性构建服务器。(现在开发者们分了一个分支,改叫Jenkins。)我(54chen)在使用过程中的手记如下: 下载 地址:http://hudson-ci.org/

wget http://java.net/projects/hudson/downloads/download/war/hudson-2.0.1.war
速度不咋的,60k/s. 先决条件 系统:centos 5.5
resin4下不work,换成了tomcat。
cp /opt/soft/hudson/hudson-2.0.1.war /opt/soft/apache-tomcat-7.0.16/webapps/
遇到的问题 1)tomcat使用utf8环境。
vim tomcat/conf/server.xml
找到8080,加入一行 URIEncoding="UTF-8"。

2)maven不工作
hudson启动后,系统管理里面,设置maven的地址:MAVEN_HOME指到maven的主目录,不是bin目录。

3)svn不工作
报re_version错误,在你的svn地址的最后面加上@HEAD

4)hudson一切正常后,有svn bug

FATAL: tried to access method hudson.scm.ChangeLogSet$Entry.setParent(Lhudson/scm/ChangeLogSet;)V from class hudson.scm.SubversionChangeLogSet

报上面的错误,我(54chen)在http://issues.hudson-ci.org/browse/HUDSON-8885里找到更新新的svn插件即可。进入到系统管理的插件管理中,选中svn 插件,安装更新即可。

5)定时执行
建立job时,有一个选项是Build Triggers,勾选 Build periodically ,schedule填写:0 10,22 * * *表示每天10/22点执行。

6)重启后jobs丢失
jobs都是定义在$HUDSON_HOME里的,如果一开始的时候没有设置,jobs将放在~/.hudson下,当重启的时候,可能发生各种找不到原来的jobs的问题,此时需要确定原来的HUDSON_HOME是啥,现在的是啥,如果不一致就会出问题。

54chen Twitter Memo 2011-07-03

    mediawiki脚本自动发内容实现
http://goo.gl/fb/V6Cyc # 根据祖国医学理论,春夏宜晚睡早起,每天需睡5~7小时;秋季宜早睡早起,每天需睡7~8小时;冬季宜早睡晚起,每天需要睡8~9小时。 # 用sonar分析项目架构:Package cycles design图中,如果对角线上下方都出现斑点,包有循环;保持每个包的一行只有一个斑点(保证只有一层在调用自己)。这样出来的项目必然是层次清晰的项目。 # 昨天新浪微博的xss看上去挺广的 # hudson很好用,早就应该用了。 # 54chen Twitter memo 2011-06-26 http://goo.gl/fb/B92fo #

Mediawiki脚本自动发内容实现

mediawiki auto post

相信很多公司都是在使用mediawiki做内部team的知识管理,同时也有一些边边角角的脚本去做诸如上线、报警一类的工作。经常会有这样的需求:在上线的时候自动更新wiki的一页内容。

实现起来很简单,只需要一个curl即可,mediawiki提供了http restful的接口,在api.php上,可以做很多事情,下面是实际使用的举例。

目标:上线脚本最后执行一下记录,更新wiki里的一页做为上线记录,Online logging包换的元素有:日期,项目,版本号,机器。

环境:安装了 curl的机器

实现细节(wiki.sh):

#! /bin/sh
OPS_APP=$1
shift
OPS_REV=$1
shift
OPS_SERVER=$1
OPS_TIME=`date`
echo "\nwrite to wiki"

TOKEN=`curl -s -d 'action=login&lgname=你的用户名&lgpassword=你的密码&format=json' http://你的wiki域名/wiki/api.php -D cookies.txt -b cookies.txt | sed -e 's/.*token":"//' -e 's/".*//'`

curl -s -d "action=login&lgname=你的用户名&lgpassword=你的密码&lgtoken=${TOKEN}&format=json" http://你的wiki域名/wiki/api.php -b cookies.txt -D cookies.txt > result

RET=`curl -s 'http://你的wiki域名/wiki/api.php?action=query&prop=info&intoken=edit&titles=Online_logging&indexpageids=&format=json' -b cookies.txt -D cookies.txt `

ETOKEN=`echo ${RET}|sed -e 's/.*token":"//' -e 's/".*//' -e 's/+/%2B/g'`
ETOKEN=`echo ${ETOKEN}|sed -e 's/\\\\/%5C/g'`
TIME=`echo ${RET}|sed -e 's/.*starttimestamp":"//' -e 's/".*//'`
URL="action=edit&title=Online_logging§ion=0&appendtext=%0A|${OPS_TIME}||${OPS_APP}||${OPS_REV}||${OPS_SERVER} %0A |-&summary=robot change&starttimestamp=${TIME}&token=${ETOKEN}&format=json"

curl -s -d "${URL}" http://你的wiki域名/wiki/api.php -b cookies.txt -D cookies.txt > result
echo "\n**write successful**\n"

具体使用: 首先新建一个名字为Online_logging的页面,内容如下:

{|border="1" cellspacing="0"
|-
! 日期 || 项目 || 版本号 || 机器
|-

sh wiki.sh 项目 版本号 服务器ip

api参考: http://www.mediawiki.org/wiki/API:Login

54chen Twitter Memo 2011-06-26

    java log4j 日志分析工具分享
http://goo.gl/fb/GiLWg # http://wenku.baidu.com/view/97ed964ce518964bcf847c14.html 双lan设置,有人用吗? # Ray Ozzie被盖茨称为“宇宙中最顶尖的5位程序员之一” # Ray Ozzie @ Xiaomi office now # 很火爆啊,大家都收到了盛大2-3倍的地点任选的猎头邀请,感觉和国内最大的集团“铁观音”一样一样的说。 # 按下葫芦起来瓢,先睡一觉重新按。 # 产品许多时候是需要许多功能的,但工程师一次只需要去实现一种功能,功能太多反而不能专注,所谓做减法,更应该是做分解,一点一滴积少成多。 # 推荐facebook系列的thrift(通讯框架)、scribe(海量日志server)、hive(hadoop的类SQL tool),用于各种线上应用、离线用户数据挖掘足矣。 # 54chen Twitter memo 2011-06-19 http://goo.gl/fb/CysHM #

Java Log4j 日志分析工具分享

log4j,analyzer java线上项目往往有许多的exception出现了没来得及去看,通过下面的工具,可以在每天早晨上班的时候通过邮件发出头一天出现的异常次数,是提高生产力和提早发现问题的好办法。
配置:

1.解压到指定目录
/data/analyze
2.email发送配置
vim mail.pl
5行,6行,7行,14行 修改为自己的配置
3.server配置
ssh-keygen打通ssh
cd server
项目名_server写服务器ip,多个机器一行一个
4.其他
可能会有不相同的log目录地址,看着修改一下shell就行。
*修改自烧饼的脚本,点击下载: http://ishare.iask.sina.com.cn/f/16530420.html

Hive迁移hadoop Namenode时遇到的问题

hadoop hive namenode 迁移

使用了一段时间的hive和hadoop,在迁移datanode时很容易,要迁移namenode,hive里就闹情绪了。更改namenode后,在hive中运行select 依旧指向之前的namenode地址。

要如何解决呢,具体操作如下:
1.复制打包老的namenode
2.复制打包老的namenode的hdfs目录
3.到新机器准备好:修改master的值 复制到各节点 修改hive的定义
4.hive这里使用了mysql来保存metadata
因为这些信息会被写死在hive的DBS和SBS表里,下面是关键的一步:
进入mysql,执行下面的sql,

update DBS set DB_LOCATION_URI=REPLACE(DB_LOCATION_URI,'old host','new host');
update SDS set LOCATION=REPLACE(LOCATION,'old host','new host');

启动,一切正常了!迁移hive namenode成功。

54chen Twitter Memo 2011-06-12

    高考应该是结束了吧,许多年后你还会因为梦中发现自己没有带2B铅笔进考场而惊醒吗?
# ubuntu 10.04 Empathy很久以前不能上之后,今天试了试居然上去了,大悟,原来那个特殊的日子过了。 # java实时日志大文件分析 http://goo.gl/fb/unwA6 # 54chen Twitter memo 2011-06-05 http://goo.gl/fb/EWLGY #

Java实时日志大文件分析

java logger tailer 日志分析时经常会遇到这个问题:一个正在增长中的大文件,要分析新增的每一行的固定内容进行统计并展示啥的。用java的RandomAccessFile盯住文件的末尾,是一个不错的选择,下面的实现,是一个高效的java tail工具,实现类似linux的tail工具的功能。用来做大日志文件的实时分析,是一个不错的选择。

public class LogFileTailer extends Thread {
private Logger logger = LoggerFactory.getLogger(LogFileTailer.class);

/**
* How frequently to check for file changes; defaults to 5 seconds
*/
private long sampleInterval = 5000;

/**
* The log file to tail
*/
private File logfile;

/**
* Defines whether the log file tailer should include the entire contents of
* the exising log file or tail from the end of the file when the tailer
* starts
*/
private boolean startAtBeginning = false;

/**
* Is the tailer currently tailing?
*/
private boolean tailing = false;

/**
* Set of listeners
*/
private Set listeners = new HashSet();

/**
* Creates a new log file tailer that tails an existing file and checks the
* file for updates every 5000ms
*/
public LogFileTailer(File file) {
this.logfile = file;
}

/**
* Creates a new log file tailer
*
* @param file The file to tail
* @param sampleInterval How often to check for updates to the log file
* (default = 5000ms)
* @param startAtBeginning Should the tailer simply tail or should it
* process the entire file and continue tailing (true) or simply
* start tailing from the end of the file
*/
public LogFileTailer(File file, long sampleInterval, boolean startAtBeginning) {
this.logfile = file;
this.sampleInterval = sampleInterval;
}

public void addLogFileTailerListener(LogFileTailerListener l) {
this.listeners.add(l);
}

public void removeLogFileTailerListener(LogFileTailerListener l) {
this.listeners.remove(l);
}

protected void fireNewLogFileLine(String line) {
for (Iterator i = this.listeners.iterator(); i.hasNext();) {
LogFileTailerListener l = (LogFileTailerListener) i.next();
l.newLogFileLine(line);
}
}

public void stopTailing() {
this.tailing = false;
}

public void run() {
long filePointer = 0;

if (this.startAtBeginning) {
filePointer = 0;
} else {
filePointer = this.logfile.length();
}

try {
this.tailing = true;
RandomAccessFile file = new RandomAccessFile(logfile, "r");
while (this.tailing) {
long fileLength = this.logfile.length();
if (fileLength < filePointer) {
file = new RandomAccessFile(logfile, "r");
filePointer = 0;
}
if (fileLength > filePointer) {
file.seek(filePointer);
String line = file.readLine();
while (line != null) {
this.fireNewLogFileLine(line);
line = file.readLine();
}
filePointer = file.getFilePointer();
}
sleep(this.sampleInterval);
}
file.close();
} catch (IOException e) {
logger.error("IO ERROR:", e);
} catch (InterruptedException e) {
logger.error("InterruptedException:", e);
}

}
}

使用起来很简单,只需要实现一个LogFileTailerListener后加入到tailer,这个tailer会去自动去执行。

类似:

public class Tail implements LogFileTailerListener {
/**
* The log file tailer
*/
private LogFileTailer tailer;

/**
* Creates a new Tail instance to follow the specified file
*/
public Tail(String filename) {
tailer = new LogFileTailer(new File(filename), 1000, false);
tailer.addLogFileTailerListener(this);
tailer.start();
}

/**
* A new line has been added to the tailed log file
*
* @param line The new line that has been added to the tailed log file
*/
public void newLogFileLine(String line) {
System.out.println(line);
}

/**
* Command-line launcher
*/
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: Tail ");
System.exit(0);
}
Tail tail = new Tail(args[0]);
}
}

上面的代码出处:http://www.informit.com/guides/content.aspx?g=java&seqNum=226,我(54chen)对其进行了一些修改,保障出现异常时不会出现死循环。

下载修改后的可用的代码: http://ishare.iask.sina.com.cn/f/15999043.html