Blog Archives

勤劳而默默无闻的开发机

办公室有台开发机,是2008年公司创立时,朋友给攒的PC装了当时的FreeBSD7.2系统,这台机器伴随我们团队从创立走到今天,一直默默无闻的工作着,6年时间里除了坏过一次电源风扇,一直工作着从未关机,团队的几个人几乎每天从早到晚都在利用这台机器保存代码和进行各种产品和功能测试,有时候看到它就像看着老朋友一样,既亲切又心疼,只可惜我们过去几年一直没有一个项目真正获得成功,要不然这台开发机真可谓是劳苦功高!

最近我们新项目启动,因为诸多因素,决定使用云主机来做开发机,于是要把开发环境和代码等移植到云主机上,这就意味着老朋友终于要退休了,想着还有点心酸,不过即便不作为主要的开发机了,这台机器依然将在办公室陪伴我们,做一些临时的功能测试和内部软件服务,这些年在技术平台和系统方面付出的心血真是不少了,多少次奔波于机房和多少个不眠夜,这两天迁移的时候,才真的体会到团队这些年真的付出了不少,希望这次开发环境的搭建和整体服务器迁移将是我们团队最后一次。

熬夜

熬夜有几种,一种被动的,一种主动的,还有一种是主动被动分不清的,不管哪种,共识的说法是熬夜伤身厉害。

我从大学开始习惯了熬夜,那会儿课余时间在中关村电脑公司打工赚学费和生活费,晚上在宿舍偷电熬夜学习计算机,并且总是自我安慰的说,同学都12点睡觉了,我平均2点睡觉,等于每天我比他们多学习了2小时,12年后我要比他们多活一年,那会儿的熬夜,说白了,还是因为要打工赚钱被动熬夜的成分多一些。

毕业后开始正式工作头几年,工作中总是时不时有白天忙不完需要夜里加班的事情,尤其搞IT这行,加班成为了家常便饭,不过因为初入社会,加上自己确实喜欢计算机方面的东西,一下子接触到很多的新知识,所以晚上熬夜如饥似渴的学习,整体来讲,这个时期的熬夜还是主动的多。

再过了些年,工作也稳定了,随着生活圈子的变化,自己也开始常常出没三里屯和工体一带,时不时的喝到夜里三四点回家睡觉,其实也不知道为什么要去喝酒,为什么要和一堆狐朋狗友瞎扯淡,好像那个年代,认为那就是年轻人的时尚和生活,这期间的熬夜,多半是模糊的。

后来,和朋友一起创业了,熬夜的日子几乎也是伴随每天,随着年纪的增长,对事业的渴望和对未来家庭责任的意识,成为拼命工作的最大动力,熬夜成为了理所当然,总感觉有忙不完的事情。

这么些年在北京,回想起来好像没有不熬夜的时间段,这已成为一种习惯,早了睡不着成为借口,其实也挺担心再过几年,身体会不会突然就垮了。我想很多和我生活在北京的朋友,应该也和我同样,一直熬夜并一直矛盾着,祝熬夜的朋友都可以身体健康。

北京的空气

前几天被一只刚一个月的小狗咬了,流了好多血,因为打针的事情百度到一个人陌生人的博客,一个北漂11年后离开北京回到老家武汉的小伙子,坚持写了好些年的博客,我不自觉的挨着看了好多篇,被一些共同北漂的经历触动,也受到此人坚持多年写博客的过程触动,想想自己荒废写博客都有一两年了。

最近这些时间,来回好几个城市,每次回到北京,下飞机的第一个感受就是北京的空气确实太差了,事情都是这样,不对比不知道,你天天生活在北京可能感受不明显,你去了海南、重庆这些地方后回来,尤其飞机上下来后,非常明显,空气里面的灰土气息很重,和工地感觉差不多,好在我对这些东西还不过敏。

回想起来,我也算是北漂十多年了,对北京这个城市,多少还是有一些感情的,经历了那么多的人和事之后,尤其这两年,当静静的自己问自己的时候,觉得对北京的感情基本都是停留在过去的某一些时间段,而这种感情似乎在慢慢的变淡,这个城市到底什么好? 我无数次总结,其实真没什么好,我回答最多的就是一个,这个城市包容性好,虽然竞争激烈,但是只要你能吃苦耐劳能坚持,总能找到养活自己的路, 事实上现在看来,就是一句话,在北京你基本不会被饿死。

这几年,北京恶劣的空气、拥堵不堪交通成为这个城市的慢性毒瘤,慢慢的开始磨灭很多人对北京的那份好感,越来越多人觉得,在北京只是为了生存,却没有生活,大部分打工者天不亮起来挤公交挤地铁扮照片,天黑了在看不见星星的夜晚拖着疲惫的身躯回到“住”的地方,周而复始。。。 最后赚的钱好多都只够吃饭和给房东打工。即便是这样,为什么还是这么多人来北京?是因为汪峰的歌?还是因为这里是首都?我觉得很多人其实都不知道为什么,只是在一种认为北京就是好的潜意识下重复着每天枯燥无味的动作。

换过来想,在其他城市的人们难道就没有工作,没有饭吃么? 我想都不至于吧,从幸福指数来说,一份好的工作只是其中一部分,在其他城市的人们,可以比背井离乡的北漂们多更多的幸福,比如可以每天和父母亲人一起吃饭,可以时不时和儿时朋友聚聚,和高中初中小学同学常见面,还不用每天呼吸这么差的空气,忍受如此糟糕的交通。 那我们到底为了什么要在北京呢?

为了事业? 为了自由? 为了爱情? 每个人可能都有自己的答案,离开的理由有无数个,留下来只需要一个就够了, 但是我想有一天,我离开北京了,那其中很重要的一个原因,一定是因为北京的空气。

Haproxy: uptime = 465d 9h37m14s

今天需要对服务器进行架构方面的调整,无奈需要重启Haproxy服务,发现它已经运行了465天没有重启过了,这一年多,还是挺省心的!

QQ截图20140107025807

今天才注意到,FreeBSD的ports已经升级使用svn了

公司一台开发机,5年前攒的,中间换过一次电源风扇,其他时间因为意外断过几次电,一直开着用到今天还很稳定,5年前安装的FreeBSD7.2的系统,升级过几次内核,最近280多天未重启也没升级,今天安装新的音频解码包的时候,发现官方的ports树已经早就更新为使用svn了,早前使用了很多年的cvs终于走到了尽头,真是个很好的进步啊!

也不知道身边还有多少人在用FreeBSD作为服务器系统,感觉有点孤独,国内的好几个cvsup镜像站貌似都已经不再维护,一度很好用的163的镜像站也不能访问了,其实FreeBSD真是很优秀的服务器系统,开发团队也是很伟大的,辛苦你们了!

Category: Linux / BSD  One Comment

在4.2.2系统上ScrollView包含LinearLayout不滚动的问题

之前写过的一个APP每日美图,支持最低的API版本是7,也就是2.1以上系统都没有问题,过了一年多没有维护了,前不久用安装有最新的4.2.2系统的手机测试,发现瀑布流图墙不滚动了,这里面其实是自定义的ScrollView中OnTouchListenr捕获手指事件后分发流程的问题,早期的实现有好多方式,大致都是通过在ScrollView上实现自定义的onTouchListener,重写onTouch()方法,把事件进行捕获,但是在API17以上不知道为啥就总是失败,会被ScrollView里面的LinearLayout给屏蔽掉了。

我重新梳理了这部分流程,用实现onGestureListener的自定义ScrollView方式搞定,因为我还需要在这个里面得到手指滚动的方向,这就是曾经一度很流行的LazyScrollView的改进版,支持判断方向的版本,经我测试,在API7-17的版本上都能正常滚动和捕获事件。

下面是ScrollView代码部分,layout和Activity部分就不贴了,和大部分的实现类似。

more »

ApnsPHP完成推送后处理错误日志的正确方法

通过苹果的apns批量发送push消息,如果中间发生错误,应该需要捕获错误发生的对象,然后对那些发生错误的消息应该在后台进行标识,这是我们常见的处理逻辑,在ApnsPHP中很好的实现了这个逻辑,大致的代码如下:


//假设前面已经有了下面一句
$message->setCustomIdentifier($id); //这里的id可以是你消息对于的数据库id

...

$push->send();
$push->disconnect();

//在发送完以后,可以进行下面的处理

$aErrorQueue = $push->getErrors();
$error_ids = array();
if (!empty($aErrorQueue)) {
foreach ($aErrorQueue AS $e) {
$error_ids[] = $e['MESSAGE']->getCustomIdentifier();
}

这里面关键的一句是 $e[‘MESSAGE’]->getCustomIdentifier();

getErrors()返回的数组,每条记录也是个数组,key为MESSAGE对应的值是个ApnsPHP_Message对象,该对象可以使用getCustomIdentifier()方法取回前面通过 setCustomIdentifier($id)传入的$id值

android中获取当前activity的名称

之前看到网上和教程中通常的做法如下:

private String getRunningActivityName(){       
        ActivityManager activityManager=(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        String runningActivity=activityManager.getRunningTasks(1).get(0).topActivity.getClassName();
        return runningActivity;               
    }

这个方法不好的是需要在AndroidManifest.xml里面定义权限

<uses-permission android:name="android.permission.GET_TASKS" />

事实上有更简单的方法,我一般都这么干!

private String getRunningActivityName(){   
        String contextString = context.toString();
        return contextString.substring(contextString.lastIndexOf(".")+1, contextString.indexOf("@"));

既不用定义权限,也代码简单。

发布个竞彩足球预测软件测试版本

前些日子碰巧得到个有经验的朋友指点,研究了一番竞彩足球,实战几番后,萌发了用数学的方法了尽可能的提高选择投注命中率,经过前一段的测试验证,已经有了比较满意的算法结果,这两天把android的客户单弄了个屌丝版本发布出来,欢迎对足彩有兴趣的朋友下载交流!说不定你会发现找到了新的投资理财机会,哈哈!

安装APK下载地址: http://www.toplee.com/caipiao.apk

iphone的版本过些时间也会发布一个出来,尽请期待!

Yii rules验证中可以使用的占位符列表

Here’s a list of many placeholders and the validators that are using them:

  • CBooleanValidator: {true} {false}
  • CCaptchaValidator: {id}
  • CCompareValidator: {compareAttribute} {compareValue} {operator}
  • CExistValidator: {table} {column} {value}
  • CFileValidator: {file} {limit} {extensions}
  • CNumberValidator: {min} {max}
  • CRequiredValidator: {value}
  • CStringValidator: {min} {max} {length}
  • CTypeValidator: {type}
  • CUniqueValidator: {table} {column} {value}
  • CUrlValidator: {schemes}

Of course, {attribute} is known in all validators. So, which placeholders are known depends on the validator and the condition as well: By default {min} is only used when the value is below the min value (as defined in rules) and {max} when the value is above the max value.