Ubuntu 12.04 安装scribe 的笔记

首先,如果你不是很熟悉C++,请放弃安装scribe。这个项目有年头没更新了,分布式日志写入可以考虑haodoop的flume或是支持MongoDB,能直接获取scribe输出的fluentd。其次,建议按照这篇笔记记录的版本,或者手动修改代码,让scribe支持高版本的filesystem以及各种库,否则必然会出现各种错误。而且这些问题虽然是同样的报错但在Google上有各种千奇百怪的解释。

scribe依赖Boost库,用thrift实现跨语言,还需要fb303来做监控。在CentOS上找到了rpm包,在Ubuntu上,apt-get 安装的版本都是最新的,scribe用不了,都要手动安装…(稍微能体会到这篇笔记的艰辛了吗?=_,=)

在装坏一台vps后开始使用build目录…

mkdir scribe-build
cd scribe-build
mkdir dist

Install boost

http://sourceforge.net/projects/boost/files/boost/1.41.0/

cd boost_1_41_0
./bootstrap.sh --prefix=`pwd`/../dist
./bjam install
cd ..

还有libevent,没装就用apt-get顺便装上:

sudo apt-get install libevent-dev

Thrift && fb303

http://archive.apache.org/dist/incubator/thrift/0.5.0-incubating/

cd thrift
export PY_PREFIX=`pwd`/../dist
./configure --prefix=`pwd`/../dist --with-boost=`pwd`/../dist
make
sudo mak install
cd ..

下载的thrift包含fb303,在contrib目录下:

cd contrib/fb303
export PY_PREFIX=`pwd`/../../../dist
./bootstrap.sh --with-thriftpath=`pwd`/../../../dist --with-boost=`pwd`/../../../dist --prefix=`pwd`/../../../dist
make
sudo make install
cd ../../..

Install scribe

以上就算装完所有依赖的库了,如果缺少必要的库,编译时会有明确的提示,最后下载运行scribe。
https://github.com/downloads/facebook/scribe/scribe-2.1.tar.gz

设置各种需要用到的路径,注意其中java的版本和路径

export LD_LIBRARY_PATH=”`pwd`/../dist/lib:”"/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/:”"/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server”
export CFLAGS=”-I/usr/lib/java-6-openjdk/include/linux/”
export LDFLAGS=”-L`pwd`/../dist/lib “”-L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64 “”-L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server”
export LIBS=”-lhdfs -ljvm”
./bootstrap.sh --with-boost=`pwd`/../dist --with-thriftpath=`pwd`/../dist --with-fb303path=`pwd`/../dist --prefix=`pwd`/../dist
make
sudo make install

configure出错提示很明确。我之前是一直卡在make命令,花了几个小时才解决各种报错。只要make执行成功就真算是大功告成了。

cd dist
export LD_LIBRARY_PATH=”`pwd`/lib”
./bin/scribed ../scribe-2.1/examples/example1.conf

[Sun Apr 22 00:16:46 2012] “setrlimit error (setting max fd size)”

[Sun Apr 22 00:16:46 2012] “STATUS: STARTING”

[Sun Apr 22 00:16:46 2012] “STATUS: configuring”

Thrift: Sun Apr 22 00:16:46 2012 libevent 1.4.13-stable method epoll

以上,祝各位好运,出了问题请直接请教scrbie的Google Group,本人不负责解答,因为C++我也不懂 = =||

Django托管在Github上的实践

Django1.4上个月发布了,有些模块换了名字,加密方式也变了,最明显的变动是目录的组织方式,manager.py和其他配置文件分开存放。这些改动导致之前的目录组织方案将不再适用。所以整理一下1.3之前在Github上的实践,今后开发的新项目再转到1.4。

requirements.txt, local_settings.py

把Django项目托管到Github上,README是给不熟悉项目的人看的,未必得能给自己省多少力气。但写requirements.txt绝对是双赢。Django项目肯定会用到一些模块(至少得装Django…),用一个txt文件列出所有会用到的模块,以换行分割:

1
2
3
4
Django==1.3.1
django-notification
PIL
simplejson

在部署的时候,直接使用pip -r install requirements.txt 就可以把需要的模块都安装上了。
Read more

从Discuz中整合用户数据到Django

国内很多论坛使用的都是Discuz,Discuz为了满足各种需求,已经变得非常臃肿,很多新技术如果要在Discuz上应用成本很高。于是用Django重写了一个,只保留基本的发帖功能。

老论坛中有近10w的用户数据,有些是注册机注册的,也有一些已经不活跃的用户,因此不考虑直接导入用户数据。大致的思路是:当某个用户登录时,查询旧的Discuz数据库,如果用户名和密码都正确,则把这个用户写入新系统Django的用户表中。这部分逻辑我是写在forms里,登录仍然用Django自带的auth_view来处理。

1
2
3
4
5
6
7
8
#在url中引用auth_view.login时,使用自己的from
from django.contrib.auth import views as auth_views
from django.conf.urls.defaults import patterns, url
from accounts.forms import LoginForm
 
urlpatterns = patterns('accounts.views',
    url(r'^login/$', auth_views.login, {'template_name': 'accounts/login.html', 'authentication_form':LoginForm }, name = 'login'),
)

在forms.py中创建LoginForm,继承自AuthenticationForm,用户登录时查询uc-center数据库。
Read more

一折

高中语文老师说过,为文者绝不能用“很久没动笔了”这种折煞士气,又自曝其短的说法作为开头。如今虽颠沛于北京,投笔已久愧对师恩。教诲终归还记得,于是删掉俗烂的套话,重拟开头。

孟丽君其中一折,名为《探病》,孟夫人装病暗中认女,少华借画像以表思念之情,丽相意欲说破又恐连累两人,这一折用婉转的越剧唱出来实在是把个中纠结诠释得天衣无缝。如果换做其他场景,比如祝寿,效果必然大打折扣,所以生病是一个很不错的flag。

年初总会病一场,虽是低烧却难受异常,外加之前踢球攒下的肌肉酸疼,病痛交加之下倍感悲凉。更悲哀的是如此一年一遇的重要场景居然没有触发任何剧情。请假回家又会很无聊。人总是要偶尔做点自虐的事测试一下身体状况才行。于是决定先码篇文章再谋工作之事。

到北京一年有余,搬家两次,如今和一群狐朋狗友混在一起,甚是惬意。同龄人大多喜欢看武林外传或是爱情公寓,不外是一群性情各异却又臭味相投的人,忙时正经做点小生意,闲时一起不正经。江湖中再大的腥风血雨,名利场上再多的大起大落,都只是茶余饭后的谈资,尚不及莫小贝的一串冰糖葫芦。所谓造化易知,然微妙无穷说的就是这般境界。而不像如今,以理想为借口彼此相忘。这一年我送走了不少人,回家的工作调动的出国的,也隐约明白其中几位是无期之別,奈何只能顺其自然。所以三哥才一直念叨着什么时候在北京买个四合院,凑一院闲人,以后老了东家抓个人下副本,西家找俩人凑个牌局。我笑说这太难了,等买了四合院,以前那群没心没肺插科打诨的弟兄们估计都成了鼻息干云的人物,我这种不上进的倒还可以屈尊住个耳房。

小说中常见的桥段:某人被禁锢于一段时间之中,比如一天,这一天不断循环,经历的事不断重复,未知和未来都被剥夺了,这大概是我们能想出的最可怕的刑罚。无论记忆中逝去的岁月如何美好,终究只可供一时回味,何况旧时光又不能重现。就像折子戏和电影,要么神似,要么形似,不可能两者得皆。编剧能写出比我们的生活华丽十倍的剧情,但再优秀的导演也无法诠释众生形形色色的心理,只能将它剥离出一部分展现,这种明显投其所好的做法总会让人嗅到浓厚的商业味,

可能我们所处的当下就注定了只能这么飘来飘去,这也不坏。佛家说空无一物,只是既然空无一物,又何必让空无一物的信念束缚,既要降服其心,那先得顺从其心才是。于是一直以来我就这么随性的活着,终究不想陷入工作,存钱,娶媳妇,生孩子,孩子工作,存钱,娶媳妇这样的无限循环。直到模糊了爱恨,以诸多的谎言作为保护世故的活着。所以我认识的人大多很狂妄,这没什么不好,二十来岁就循规蹈矩,这人肯定也不会有什么成就。就像冗长的老旦唱白,翻来覆去总是一个调。

我算是又演到生病这一折了,虽说不能触发妹子上门探望的剧情。也不能拖着,先看病吃药才是正道。

从零开始搭建Django Solr的环境

本文介绍在Ubuntu系统中,用django-haystack处理Django搜索请求的方法。如果有涉及连词、多条件等较为复杂的搜索需求,这是一个很不错的解决方案。如果只需要基本的搜索功能,或是刚接触Django的用户则不推荐使用,这个模块功能强大相应的配置也很繁琐,稍有不慎就会出错。

安装tomcat, solr, django-haystack:

$ sudo apt-get install tomcat6
$ sudo apt-get install solr-tomcat6 #Ubuntu 11.10 12.04里是 solr-tomcat
$ pip install django-haystack

安装成功后打开:http://127.0.0.1:8080/solr 可以看到Solr的管理界面。接下来开始配置Django,首先在项目目录中新建search_sites.py文件,内容是:

1
2
import haystack
haystack.autodiscover()

Read more

Django用uploadify实现图片批量上传

分享一下在Django中使用uploadify——一个jQuery批量上传插件——的方法。github上的django-uploadify使用的是2.1.4版本,上传button只能使用图片,不能很方便的修改样式。本文针对的是uploadify 3.0.0版本。

uploadify可以结合Django自身的ImageField,或是配合easy_thumbnails等第三方app来使用。比较稳定,我在几个项目中处理批量上传都是用它,没有出现什么问题。但因为是用flash上传,在开发工具中监控不到network的动作,只能通过函数返回的错误信息来调试,所以比较麻烦,但调通一次就一劳永逸了。

不重要的CSS样式,可以跳过。

1
2
3
4
5
6
7
8
.uploadifyButton{background-color:#505050;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;color:#FFF;font:12px Arial, Helvetica, sans-serif;text-align:center;width:100%;padding:8px 0}
.uploadify:hover .uploadifyButton{background-color:gray}
.uploadifyQueueItem{background-color:#F5F5F5;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;font:11px Verdana, Geneva, sans-serif;margin-top:5px;max-width:350px;padding:10px}
.uploadifyError{background-color:#FDE5DD!important}
.uploadifyQueueItem .cancel{float:right}
.uploadifyQueue .completed{background-color:#E5E5E5}
.uploadifyProgress{background-color:#E5E5E5;margin-top:10px;width:100%}
.uploadifyProgressBar{background-color:#09F;height:3px;width:1px}

添加一个上传按钮,引入相应的js文件。uploadify 3.0中把swfobject.js和uploadify.js写到一个js文件里了。

1
2
3
<input type="file" id="id_upload" name="upload"/>
<script type="text/javascript" src="/static/js/jquery.js"/>
<script type="text/javascript" src="/static/js/jquery.uploadify.js"/>

Read more

在Dotcloud上搭建NodeJS+MongoDB环境

主要目的是练习KnockoutJS和Bootstrap,后台为了保持一致就用现成的NodeJS + MongoDB了。写好需要的功能,本地测试通过之后想试着布置一下,正好也可以了解Dotcloud架设这种环境的方法,网上没有现成的文档,有相关的文章,但不是用ExpressMongoskin写的,所以自己动手搭建了一个,现在把方法分享一下。

Dotcloud Configure

新建一个项目,目录结构和其他应用基本相同。忘了的话可以参考这篇架设Django的文章。根目录是kanoya-on-dotcloud,kanoya是NodeJS项目目录,目录中的文件列表如下:

kanoya-on-dotcloud/
├── kanoya
│   ├── app.js
│   ├── node_modules
│   ├── package.json
│   ├── public
│   ├── supervisord.conf
│   └── views
└── dotcloud.yml

Read more

初学前端的MVC架构

Web应用的功能越来越强,Javascript代码也越来越多,大量的JS代码要以何种架构来组织就成了一个亟待解决的问题。老牌软件架构模式MVC(Model-View-Controller)就是一种相当不错的方案,虽然它定义不明确需要很多时间来思考如何组织,崇尚代码分离增加了调试难度,但毕竟脸熟(……),从用CakePHP的时候就接触过这个概念,以我能理解的方式描述就是:Models用来处理数据,View将处理结果呈现给用户,Controller用来连接这两者。所以一个Web应用的流程通常是这样的:

  • 1. 用户在View上进行操作——比如在文本框输入数值或是点击按钮
  • 2. Controller处理这个动作
  • 3. Controller通过Model对数据进行增删改查,将其传递到View
  • 4. View将数据展示给用户

以上描述来自Javascript Web Applications一书,其中有用MVC组织JS代码的具体方法。如果想偷懒的话,也有一些现成的JS框架来做这件事。说到JS框架可能最先想到的是jQuery,这类MVC框架和jQuery解决的问题不同,jQuery主要用来对页面元素进行操作上,比如我要移动一个按钮,或是将某个按钮设置为隐藏。而前端MVC框架除了将代码合理的组织以外,操作上也不是侧重于设置一个动作,当触发时进行某些处理这种方式。而是绑定Model,当Model改变时,View接收到通知,重新渲染。不需要手动指定页面元素更新HTML,改变Model时直接改变View。

Read more

在Django中使用LESS

上次振宇介绍duoshuo的开发,前台用的是backbone和LESS,backbone很久之前mentor就提到过,当时没弄懂,等下周休息的时候抽空学学,LESS倒是没什么学习成本。

LESS一种动态样式语言,简单来说就是对CSS语言的扩展,可以类比于coffeescript对javascript提炼。我因为javascript写习惯了,转到coffeescript效率不升反降。但用LESS重写了几个CSS文件,绝对是快了很多。因为LESS没有改变CSS的写法(唯一变化的是注释可以用//了),所以没有转换障碍。LESS拥有语言的特征,例如变量、函数、命名空间等,和只是样式表的CSS比起来灵活了许多。

在前台使用LESS的方式和coffeescript很像,也是载入一个js文件用来处理less后缀的文件,将其转换成CSS。

1
2
3
<link rel="stylesheet/less" type="text/css" href="/static/css/styles.less">
<script src="/static/js/less.js" type="text/javascript"></script>
</link>

当然如果真这么处理,就和Django没什么关系了,我一般是在模板里直接用{%block style%}写CSS样式,所以如果能自定义一个templatetag,直接在里面写LESS那是最顺手的。

Read more

Django复制记录的方法

最近的Django项目中有复制记录的需求。数据库里有一张名为Party的表,记录用户创建的party,现在要让用户能够复制一个新的party。本身非常简单的一个功能,但运行的时候出错了。我以为是复制过程出错,所以测试了一下Django中复制记录可能遇到的情况(后来发现是其他代码的逻辑出了问题),结果整理如下。

1.Reset pk

在Django中复制一条记录最简单的方法应该是先取出这条记录,将它的主键设置为None,然后再保存一次。

1
2
3
old_party = Party.objects.get(pk=1)
party.pk = None
party.save()

2.Keyword Arguments

如果某张表除了主键还有其他AutoField字段,就要换一种方式了,虽然也可以手动根据字段名将其指定为空,但直接遍历出字段名和相应的值,把其中的AutoField字段赋值为None会比较简单。

Read more