杂记

总要写点什么吧?不为别的,为了2012-12-21前多写写文章,多给这个星球留下些琐碎。

还记得大学时,高崇伊老师跟我们讲,有人问大物理学家费曼,如果世界真的毁灭了,只能留给后人一句话,这句话是什么。费曼说,世界是由原子构成的。

假设2012-12-21真的是世界末日,你会愿意像这样生活、工作吗?会对现在做的一切都是满意吗?2011年,当我每天都对这些说no时,我再也无法忍受,我选择了重新开始。

写写过去一年的总结?新的一年的展望?

总结就罢了,过去的一年都在审视自己的现状,审视自己过去做过的事情,再怎么总结也挤不出什么味道。

展望也很简单,生活上希望有所改变;工作上面,能够把目前手上负责的几个项目做好,能够带出一个好的团队来。过去的一年真的没有什么进步。

听着王力宏的《唯一》,仿佛时间回到了十年前的傍晚,我坐在教室后面上自习,当时学校广播里放的也是这个歌。只是,这歌还是这歌,时间逝去,再已无法追回。大学的论坛很多时候都不敢上去,每每上去,看着熟悉又模糊的照片和文字,都会偷偷的把眼泪往肚子里咽;不是失望,也不是激动,而是对那段已经逝去的青涩,心里有诸多不舍和不甘。想念当时军训完用帽子舀花香的情形,虽然当时兵败2001高考,但幸运有一个基地班的过渡,我没有继续颓废下去。

有时候真的不知道从何说起,人真的是复杂的动物。罢矣,收拾心情,明天继续上班。

Share "杂记"

Share on: FacebookTwitter

mac中针对不同域名使用不同的dns服务器

一般情况下,我们使用一个dns服务器就能达到我们的需求,但有时候我们需要针对不同域名,使用不同的dns,如以下场景:

  • 需要dns服务器A去解释某国外域名
  • 需要dns服务器B去解释局域网内部的域名
  • 默认使用dns服务器C

通用的解决方法是使用自己搭建的dns forwarder服务器,然后针对不同的zone设置不同的dns服务器,bind和dnsmasq都可以做这种dns forwarder的工作。

但如果你是在mac中,则有更加简单的方法:

  1. 在 /etc/ 目录下建立 resolver 文件夹,即 /etc/resolver 目录
  2. 在/etc/resolver 目录下,针对不同的域名zone建立不同的解析文件;如我要对zwsun.com使用192.168.1.1的dns服务器,则建立文件zwsun.com,内容为: nameserver 192.168.1.1
  3. ping zwsun.com看看,证实一下是否设置成功

上述操作需要在root下,另外,需要说明的 是,nslookup的结果不会受这个文件的影响,但对ping程序是会生效的。

一般的策略是将大部分域名解析的dns设置在 /etc/resolv.conf中,也就是通过网络偏好设置,特殊解析需求的可以在/etc/resolver目录下建立对应的文件。

Share "mac中针对不同域名使用不同的dns服务器"

Share on: FacebookTwitter

增加虚拟机空间的一些方法

下面的讨论基于virtualbox(我选择virtualbox的原因是它免费,且支持各个平台),虚拟机为linux,宿主操作系统不限。

经常一开始建了一个固定大小的虚拟硬盘用来安装虚拟机,但过段时间数据越来越多,最终发现其空间不够用,这时候就很郁闷了,但如果不是你系统的目录不够用的话,下面的办法可以解决空间不够的问题:

1 增加一个虚拟硬盘的方法

优点:虚拟机中读写速度较快,虚拟硬盘也可以后面给其他的虚拟机使用

缺点:宿主机器无法读写块虚拟硬盘中的内容

操作方法:

1.1 先给虚拟机配备一个动态大小的虚拟硬盘

这个和一般的装虚拟机新建虚拟硬盘一样的操作。

打开虚拟机的配置 > storage 增加SATA控制器,然后在SATA控制器下增加一块虚拟硬盘;或者直接在IDE controller下面新增一块虚拟硬盘。

1.2 在虚拟机中进行分区,格式化,然后挂载

1.2.1 分区:

PS:必须要在root下操作,下面的描述中,橙色字体的为输入的命令。

先用fdisk -l看看,如果没有找到你的虚拟硬盘,那就是前面的虚拟硬盘没有配置对。

root@dev-desktop:/home/dev# fdisk -l
Disk /dev/sda: 8589 MB, 8589934592 bytes255 heads, 63 sectors/track, 1044 cylindersUnits = cylinders of 16065 * 512 = 8225280 bytesDisk identifier: 0x00015130
Device Boot      Start         End      Blocks   Id  System/dev/sda1   *           1         993     7976241   83  Linux/dev/sda2             994        1044      409657+   5  Extended/dev/sda5             994        1044      409626   82  Linux swap / Solaris
Disk /dev/sdb: 2845 MB, 2845835264 bytes255 heads, 63 sectors/track, 345 cylindersUnits = cylinders of 16065 * 512 = 8225280 bytesDisk identifier: 0x00000000
Disk /dev/sdb doesn't contain a valid partition table

可以看到第二块虚拟硬盘 /dev/sdb 上面没有任何分区信息,当然无法用了。

接着 fdisk /dev/sdb 在第二块虚拟硬盘上建立分区,关于fdisk的详细用法请在进入fdisk后按m或者搜索之。

root@dev-desktop:/home/dev# fdisk /dev/sdb
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabelBuilding a new DOS disklabel with disk identifier 0xadff2d79.Changes will remain in memory only, until you decide to write them.After that, of course, the previous content won't be recoverable.
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)
Command (m for help): n

Command action

e   extended
p   primary partition (1-4)p

Partition number (1-4): 1
First cylinder (1-345, default 1): 1

Last cylinder or +size or +sizeM or +sizeK (1-345, default 345):
Using default value 345
Command (m for help): w

The partition table has been altered!

1.2.2 格式化

有分区了,还是无法使用的,这时候需要格式化,linux下普遍使用的是ext3。我们通过mkfs对刚才的分区格式化:

root@dev-desktop:/home/dev# mkfs.ext3 /dev/sdb1
mke2fs 1.40.8 (13-Mar-2008)Filesystem label=OS type: LinuxBlock size=4096 (log=2)Fragment size=4096 (log=2)173888 inodes, 692795 blocks34639 blocks (5.00%) reserved for the super userFirst data block=0Maximum filesystem blocks=71303168022 block groups32768 blocks per group, 32768 fragments per group7904 inodes per groupSuperblock backups stored on blocks:  32768, 98304, 163840, 229376, 294912
Writing inode tables: done
Creating journal (16384 blocks): doneWriting superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 38 mounts or180 days, whichever comes first.  Use tune2fs -c or -i to override.

1.2.3 挂载

通过mkdir先建立一个挂载点,如在根目录下建立一个data目录用于挂载 mkdir /data/

root@dev-desktop:/home/dev# mount /dev/sdb1 /data/

通过df命令看看挂载情况,如果有相应的挂载信息就ok了。

root@dev-desktop:/home/dev# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1             7.6G  6.1G  1.2G  85% /
varrun                352M  128K  352M   1% /var/run
varlock               352M     0  352M   0% /var/lock
udev                  352M   48K  352M   1% /dev
devshm                352M     0  352M   0% /dev/shm
lrm                   352M   40M  313M  12% /lib/modules/2.6.24-27-generic/volatile
/dev/sdb1             2.7G   69M  2.5G   3% /data

1.2.4 设置 /etc/fstab

做这一步的目的在于将第二块虚拟硬盘的信息写入系统分区信息表,便于开机自动挂载,否则,每次都需要手动去mount

在目前的/etc/fstab文件后面增加一行

/dev/sdb1       /data           ext3   defaults 0 2

关于fstab的配置和各个参数的含义,可以自行搜索之。

2 和宿主机器通过数据空间共享的方法

优点:宿主和虚拟机都可以操作共享的文件,虚拟机内的空间完全决定于宿主机器的物理硬盘和实际分区,虚拟机开启后也可以使用该办法。

缺点:速度较慢

方法:

在虚拟机的设置 > 数据空间中设置宿主的目录和权限。

进入虚拟机后以root身份运行以下命令:

mount -t vboxsf  数据空间名称  挂载点

总结:如果你在宿主能够访问虚拟机中文件这方面没有需求,推荐使用增加虚拟硬盘的方法。

Share "增加虚拟机空间的一些方法"

Share on: FacebookTwitter

让mac的cpu不再狂转

众人皆知,在mac上,flash绝对是cpu杀手,只要一开有flash的网站,那cpu马上疯狂的转,不知道是adobe的问题,还是mac的问题。

鉴于此,禁用flash是个最直接的解决方法,而且一般网站大部分flash都是广告。safari中推荐使用 clickplugins这个扩展,他可以将flash暂时屏蔽,若你需要看,点击一下即可。firefox中同样有这样的插件,名字叫做flashbock,使用方法一样,需要看的时候点一下。

关于视频网站的解决方法:在safari中可以将user agent设置为iPad,这样,大部分视频网站将会给你html5的视频,这样播放起来无压力。firefox下由于不支持html5,那都是浮云了。事实上,clickplugins这个插件会对国外网站上的视频转成html5,无需切换user agent,可惜这些网站在我朝是不存在的。

Share "让mac的cpu不再狂转"

Share on: FacebookTwitter

关于js执行顺序和jquery.html

下面这些知识虽然是前端相关的,但是做为一个想深入web的人,还是非常有必要知道的。很多时候当前端跟你抱怨为什么我的js中明明声明了变量,但还报未定义的错;为什么我写一个alert调试就好了?很有可能就是下面所提到的问题。

1 js为什么不按代码中的次序执行了?

正常的html中外联script,script无法并行下载,阻塞后面其他资源的下载;且执行顺序可以得到保证(新版本浏览器有改进,可以并行下载js,执行顺序也会保证)。所以我们一般在html中写的js都没有问题,但问题是,这个会影响整个网页相关资源下载速度。

鉴于此,人们又想了很多方法来“欺骗”浏览器,以达到加速下载js和相关资源文件的目的,方法大概有以下几种:

  • XHR Eval :ajax获得js内容,然后执行
  • XHR Injection : ajax获得js内容,然后创建一个script的node,插入到文档dom tree中
  • Script in Iframe : iframe src为js文件
  • Script DOM Element :动态创建script,然后设置其src
  • Script Defer : script标签加入 defer属性
  • document.write Script Tag :document.write("<script type='text/javascript' src='A.js'><\/script>");

既然可以并行下载,那么执行顺序就是一个需要确认的问题了,可惜的是,不是每种技术都能保证脚本执行的次序。具体情况可以参考下表(节选自 《Even Faster Web Sites》):

2 jquery的html函数好像有时候也不灵啊!

假设我们如此调用:

$('#content').html(data);

jquery 的html函数使用同步ajax下载data中的外联js。对于inline的js,执行Script DOM Element在head节点插入一个script节点。

从上面的分析来看,data中js的执行顺序是可以保证的。但有时调用jquery.html,却仍然出现执行顺序混乱的情形,原因是外联的js是不同的域。由于ajax无法跨域,故这时候无法通过同步ajax下载来加入外联js,而是通过和内联js一样的方式:将外联的js以Script DOM Element 的方式插入到head节点。按照上面的图,执行顺序是无法在所有浏览器上保证的(ensures order)。

解决方法: 在调用jquery.html前,使用 document.write Script Tag将外联的js载入。

3 文章开头提到的问题

外联js定义了js变量,但还报undefined错:很有可能就是执行顺序不对,执行使用变量的代码时,定义的js虽然在前面,但还没有下载完呢。

alert一下,一切就是好的了:还是一个道理,定义的外联js没有下载完成,同时,你可以试试setTimeout,将你使用外联js的变量的代码晚点执行,也会是好的。

4 参考资料

下面这些资料,非常值得一读:

  • 《Even Faster Web Sites》
  • http://www.cnblogs.com/sanshi/archive/2011/02/28/1967367.html
  • http://www.cnblogs.com/sanshi/archive/2011/03/01/1968275.html
  • http://www.cnblogs.com/sanshi/archive/2011/03/02/1969224.html

Share "关于js执行顺序和jquery.html"

Share on: FacebookTwitter

从leopard升级到lion

1 前言

话说上回将iPad2升级至iOS5,正欢天喜地的尝试wifi同步,但可惜的是我的leopard系统里面竟然连wifi同步选项都没有!我非常、极其的生气,打了一通apple的客服,无果;上苹果的论坛一看,一大堆人反映和我一样的问题。有人实测,只有在10.6.8后才能够wifi同步,连10.6.6都不行。我恨啊。

难道真的要升级系统了吗,现在老系统的问题越来越多,主要有以下方面:

  1. 输入法,可恨的输入法,竟然大部分都不支持10.6.8以下的系统
  2. 还是输入法,10.5.8里面不能设置不同窗口使用不同输入法,实在不爽(据说10.4还是可以设置的)
  3. 没有mac app store,下载软件完全靠游击战
  4. qq等很多软件不再支持10.6.8以下
  5. webkit在编译有些部分时,不支持10.6以下的系统
  6. 刚才说的,没有办法和iOS设备wifi同步

之前没有升级,主要是偶尔工作时会用,当心开发环境什么的;现在好些了,那狠下心来升级吧,为避免后面再升级,准备现在一次升到lion算了,同时,加内存到8G。

 

2 升级过程

升级的过程是 10.5.8 -> 10.6.3 -> 10.6.8 -> 10.7 -> 10.7.2,也就是从leopard到snow leopard再到lion,因为leopard是无法直接升到lion的。

其中10.6.3 -> 10.6.8和10.7 -> 10.7.2算更新,去apple网站下载更新包即可;其他的嘛,要么买正版(其实也不贵,snow lepord卖¥248,lion 下载时卖$29.9),要么你懂得。

升级到10.6.3的时候,最后时刻出现了安装失败,真的是让我心都凉了;幸好重新安装后成功,估计是光驱读盘的问题吧。

硬件的升级放在了安装上10.6.8之后,原有的2G内存早已不够lion用的了。内存倒是亲民价,2条4G的三星金条连350都不到。

拆开后盖,拔出之前的内存,换上新的内存(顺便可以清理一下风扇什么的),开机一次点亮。之前网上有人说可以使用1333MHz的内存,我这里算也是再次验证了,不过它工作的频率应该还是1066MHz。

系统信息

下面是我机器的更加详细的信息,可以看到,虽然是2008年后期的mb 466,但是还是可以升级到lion的。
系统简介

整个升级过程还算顺利,只需开机放入光盘或者点击安装程序即可,默认情况下也是升级安装,也就是说用户的程序(包括应用程序下的程序)和文档都还在的,甚至连之前应用程序的数据都在,比如safari的浏览历史,下载记录。iTunes无法识别iPad2,不过重装一下iTunes就好了,app、音乐以及图书都还在。

 

3 使用感受

  • 8G的内存没白加,lion使用起来还是非常顺畅的;另外,系统占的硬盘空间也比leopard少了4G左右。
  • 由于从leopard切换过来的,一时无法适应手势滚动方向的改变:之前leopard中,手势滚动的是滚动条,而现在lion滚动的是内容,这也和移动设备是一致的。
  • 手势程序切换以及全屏是目前使用起来比较舒服的功能。
  • safari浏览时,前进后退比以前更加酷了。
  • iTunes终于可以iPad2无线同步了。

Share "从leopard升级到lion"

Share on: FacebookTwitter

iOS5使用有感

ipad gestures

10月12号,apple正式发布iOS5,现在更新,虽然算不上第一时间,但这时候稳定些。下面将相关过程和初步使用体会分享一下。

更新的过程:

  1. 更新iTunes至10.5
  2. 直接在iTunes中升级至iOS5(也可以直接下载对应的固件文件,然后通过iTunes里面options(shift in windows)+恢复完成)

直接下载固件的列表:

关于更新后app都需要重新下、游戏记录都没有的问题,我这边倒是没有发现,更新后app照样在,照片也在。应该是始终用一台电脑的原因吧。总之,更新过程没有遇到什么问题,就是下载固件时间长了些。

使用感受,下面的功能是个人觉得比较好用的:

  1. 手势:通过手势切换应用程序,回到主屏幕,查看正在运行的程序等等;有了手势,可以少按home键了
  2. 更新的键盘:有输入法切换的改进,增加常用的符号输入,支持浮动、分开的布局键盘;总之,输入更加方便
  3. safari的更新,标签操作直接可以在safari的主界面搞定,和mac版的safari类似;另外还有read later以及阅读器的功能
  4. 和电脑通过wifi 同步,可惜我的Leopard系统(10.5.8)好像不支持,完全没有
  5. iCloud,可以同步一大堆数据
  6. 更好的通知中心

当然,也有些更新其实不是那么好玩了,比如报刊杂志,个人觉得是鸡肋,至于iMessage,我觉得还不好说呢。

Share "iOS5使用有感"

Share on: FacebookTwitter

苹果10月4日秋季产品发布会有感

10月4日,苹果举行了今年秋季的产品发布会。按apple之前的惯例,本应该今年早些时候发布新产品的;拖到现在,使很多投资者和消费者有了更多的期待,但总体来说还是让人比较失望的,这在苹果的股价上有很好的体现。发布会主要有以下信息:

  1. 没有iPhone5,只有iPhone 4 的升级版iPhone 4s,即使这样,连iPhone 4s的介绍也不是CEO Tim
  2. ios 5的介绍,主要是iCloud, Find my Friend 以及一个Card的程序
  3. iPod, iPhone产品全线降价
  4. 其他相关apple store, iPod, mac,iPhone, iPad, ios等数据介绍

其实我等围观之,主要是想要看看apple能够有哪些新功能的推出,但是创新也不是那么容易的,不可能每次发布会都能像iPhone, iPad刚推出来那样让人耳目一新。但个人觉得本次发布会,Siri还算是一个亮点了(Let 's talk iPhone 中 的talk应该是指这个意思吧),Siri虽然基础是语音识别,之前也有很多类似的语言识别程序,但之前的程序交互性不强,大多数的功能也是将语言转换成文字;而Siri则更在问答、帮忙人们完成任务这一方面更进一步。

Share "苹果10月4日秋季产品发布会有感"

Share on: FacebookTwitter

经典算法问题-表达式求值

上次和同事聊到了验证码中有表达式求值的问题,说起来应该是比较简单了,也是数据结构上经典的算法问题。可是自己写一写才会发现,做对一件看似简单的事情不是那么容易。

本来自己弄了一个c的stack,但是c没有模板,想不到怎么支持不同的类型,只好换用c++了。

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

#include <stack>
#include <iostream>

using namespace std;


/**
 * 比较运算符之间的优先级
 */
static short int Precede(char c1, char c2) {
    if (c1 == c2) {
        if (c1 == '#') {
            return 0;
        } else if(c1 == '(') {
            return -1;
        } else {
            return 1;
        }
    }
    
    switch (c1) {
        case '+':
        case '-':
        
        if (c2 == '*' || c2 == '/' || c2 == '(') {
            return -1;
        } else {
            return 1;
        }
        break;
        
        case '*':
        case '/':
        if (c2 == '(') {
            return -1;
        } else {
            return 1;
        }
        break;
        
        case '(':
        if (c2 == ')') {
            return 0;
        } else {
            return -1;
        }
        break;
        
        case ')':
        return 1;
        break;
        
        case '#':
        return -1;
    }
}

/**
 * 对加减乘除进行求值
 */
static float Operate(float a, char theta, float b) {
    switch (theta) {
        case '+':
        return a+b;
        break;
        
        case '-':
        return a-b;
        break;
        
        case '*':
        return a*b;
        break;
        
        case '/':
        return a/b;
        break;
    }
    
    printf("bad operator");
    return 0;
}


int main() {
    
    stack<char> optr;
    stack<float> opnd;
    
    optr.push('#');
    
    char theta, tmp[20], *tmppoint, basechar[20];
    tmppoint = basechar;
    float a, b;
    
    char c = getchar();
    
    while (c!='#' || optr.top() != '#') {
        if (isdigit(c)) {
            *(tmppoint++) = c;
            c = getchar();
        } else {
            
            if (tmppoint > basechar) {
                *tmppoint = '
';
                opnd.push(atof(basechar));
                printf ("push number %s\n", basechar);
                tmppoint = basechar;
            }
            
            if (c != '+' && c != '-' && c != '*' && c != '/' && c != '(' && c != ')' && c != '#' ) {
                c = getchar();
                continue;
            }
            
            short int precede = Precede(optr.top(), c);
            switch (precede) {
                case -1:
                optr.push(c);
                printf("pushed operator %c \n", c);
                c = getchar();
                break;
                
                case 0:
                optr.pop();
                c = getchar();
                break;
                
                case 1:
                theta = optr.top();
                optr.pop() ;
                
                if (opnd.empty()) {
                    printf("opnd is empty\n");
                }
                b = opnd.top();
                opnd.pop();
                
                a = opnd.top();
                opnd.pop();
                
                cout << " cal a=" << (float)a << " theta=" << theta << " b=" << (float)b << endl;

                opnd.push(Operate(a, theta, b));
                break;
            }
        }
    }
    
    /* 最后的结果 */
    printf("%f\n", opnd.top());
    printf("%c\n", optr.top());
    
    return 0;
}

Share "经典算法问题-表达式求值"

Share on: FacebookTwitter

从svn迁移到git

最近需要从svn迁移到git了,之前虽然有简单的用过的git,但那远远不够,最近先花了点时间来看看git的使用。

git和svn的最大区别是git是分布式的,而svn仅仅是一个svn服务器,实际的来说,git有本地的代码库,可以离线提交自己的修改至本地的代码库。通过下面这个图可以有一个直观的印象。

若要修改代码,从一个版本库开始的方法:

  • git是git clone
  • svn是svn checkout

提交代码至远程服务器的方法:

  • git是git commit -am 'comment' 提交至本地的代码库,若要提交至远程服务器,再执行git push
  • svn 则很简单,svn commit即可

从中央服务器更新到本地代码的方法:

  • git是git fetch到本地代码库,然后再git merge,简单的办法是 git pull
  • svn很简单 svn update

撤销本地修改:

  • git是git checkout . (该命令就是将本地的workspace修改撤销至本地代码库)
  • svn是删除掉修改的文件,然后svn update

比较差异:

  • git是 git diff (获得当前workspace还没有计划提交的差异,若计划提交后但仍未提交至本地代码库则用git diff --cached)。 git diff  <remote_branch> <branch> (比较本地代码库和服务端的差异),一般的命令就是 git origin/master master
  • svn 则是svn diff即可

 

其他一些问题:

git 的本地代码库commit的撤销:

  • git revert 这个会撤销本地代码库的修改,但这个动作本身会创建一个版本,因此很容易搞混。
  • git reset --hard HEAD 这个会撤销本地代码库的修改。

git push 目标分支:

git push 可以将local的分支push到远程不同的分支上(non-fast-forwording),但是最好不要这么做。

合并本地分支:

git merge  和 git rebase, 这两个的动作都可以合并,但最终得到的分支线路会不太一样。

最简单的类似svn的工作流程:

git workflow

有用的参考:

  • http://progit.org/book/zh/
  • http://book.git-scm.com/index.html
  • http://schacon.github.com/git/everyday.html

Share "从svn迁移到git"

Share on: FacebookTwitter

blog built using the cayman-theme by Jason Long. LICENSE