Hello 2012

0

差不多一年前写了篇博客《本命年了》,刚才红着脸又看了一下,不少计划都坑掉了,不过总的说回来,虽然学习方面进步不如预期,但这年做的几个决定还是让自己挺满意的。

2011流水账

2011年入夏之前,实在忍受不住iOS开发的诱惑,从公司辞职,宅在家中开始捣鼓一些自己感兴趣的技术。虽然很多时间浪费了过去,但最终还是写了些小玩意儿出来,界面丑陋功能简单没几个用户,但偶尔会多出一两个评论说“很有用!”,这就让我开心半天。

十一回家住了一段时间,返回上海后身上已经没几个钱了,这时元元同学慷慨地伸出双手:“来杭州吧~”,于是又得以在杭电混吃混喝混学过了三周。

再度返回上海已经进入十二月,马上开始投简历找工作,很幸运的进入了一个由自己想要成为的那类人创建的创业公司中,专职iOS应用开发,每天开心的工作着^_^

春节时全家人去了深圳过年,说起来姐姐在那边都成家这么多年了,我这才第一次去…对深圳的印象挺不错的,最起码绿化比上海要好得多。

年后一起合租的金牌同学被诱去了西安,我和外挂就换了一个房子租,虽然房租贵了不少,但——总算不用再忍受毛坯房了!

挖坑

鉴于去年的不良记录,我就不把这个叫做计划了。

学习
  • Local App
  • 继续钻研iOS开发,争取做到在实现时不用为程序结构犹豫。
    做好公司新产品的开发。
    改进自己的上一个app,至少再发布一个新的。

  • Web
  • 完成Ruby的学习,能利用Rails完成小网站的开发。
    学习JavaScript/Html/CSS。

业余

继续英语和日语的学习。
坚持学琴。
坚持锻炼。

其他

把积攒的那些书读完!
跳入手办坑。
正版化一部分音乐。

TCP/IP协议学习

0

前些天在杭电待了三周,找元元同学补习了一下网络基础。每天睡醒了就爬起来跑到他们实验室看书读代码,学习效率还算不错。
下面记录一下学习过程:

使用书籍

基础知识:《TCP/IP协议族》,原书为Behrouz A. Forouzan的TCP/IP Protocol Suite。这本书是介绍TCP/IP协议族基础知识的经典教材,我看的是第3版,发现不少翻译错误。最新版本是第四版,中文版今年年初已经出了。后来借到新版翻看了一下,整书结构改动不小,而且讲得更加详细,翻译错误也更少。
代码阅读:《用TCP/IP进行网际互联第二卷–设计、实现与内核(ANSI C版)》,原书为Douglas E. Comer的Internetworking with TCP/IP Vol. II。这本书讲的是TCP/IP协议的实现细节,代码使用的是XINU系统(Xinu Is Not Unix,Comer在Purdue大学写的教学用操作系统)中TCP/IP部分的实现。
代码下载地址:ftp://ftp.cs.purdue.edu/pub/comer/TCPIP-vol2.dist.tar.gz

阅读方法

阅读时,先看《TCP/IP协议族》的1~6章,了解基础知识后,开始看《用TCP/IP进行网际互联第二卷》的前两章。之后就基本是看一章《TCP/IP协议族》的基础知识,读一章《用TCP/IP进行网际互联第二卷》的代码。阅读代码时最好用纸打印出来,然后逐行加注释,这样读过的代码才好真正的理解,很多很重要的细节才能注意到。前面的代码没太多难度,理解了原理就很容易。到TCP的时候,涉及到状态机和拥塞处理,代码量会大一些,此处可以把涉及信号量的部分先跳过去,第二遍读的时候再特意总结一下信号量的使用。TCP/IP部分到这里就算是完成了,再往后就是应用层的东西,忽略掉以后看Linux源码也行。

后续学习

《Internet技术基础》、《计算机网络与因特网》,这两本都是Comer写的,对应用层的东西讲得更多些,算是宽度上的扩展。
《TCP/IP 详解 卷1》,又一本经典书,基础知识上会讲得更深入些。
《UNIX网络编程》、《UNIX环境高级编程》,有了底层基础,再利用这两本书学习Socket编程就会很顺利了。也可以跳过这个直接学其他的API。

其他

  • 这种方法学习门槛很低,之前没什么网络基础也很容易上手。
  • 看书看代码有什么不理解的地方直接给Comer发邮件就是了,回复很快很耐心。
  • 之前读的C代码不多,这次好好读一套后对C的理解深入了不少,而且由于目前很多其他语言的编译器解释器都是用C实现的,对其他语言的理解也很有帮助。比如看到路由表项结构中的reference count时,一下子想到了Objective-C的内存管理方式,认真想一下也就是这么回事,只是C是结构化语言,只在某些struct中使用,而面向对象的Objective-C直接就把这种方式弄成标配。

最后要感谢元元同学这三周的教导和包吃包住,哈哈,说不定又吃胖了些lol

适合代码阅读的Vim配置和使用

0

从大学时开始,断断续续使用Vim也许久了,但由于之前只是把它当作一个快速编辑器来使用,熟悉的也仅仅是最基本的光标定位、复制粘贴等命令。而最近跑来杭电读一套C代码,手上仅有一台装着Debian的本子,便花了点功夫对Vim进行了一些定制,让它具备Source Insight的部分功能。
下面记录一下和代码阅读相关的Vim配置和使用方法:

跳转到使用速查

基本设置

Vim的配置一般都是通过修改~/.vimrc文件来完成的。在Vim的安装目录中,有一个此文件的范例,可以将它直接拷贝到家目录中使用。

$ cp /usr/share/vim/vim73/vimrc_example.vim ~/.vimrc

这个文件已经包含了自动缩进和语法高亮的设置,不过对于阅读代码来说,显示行号是必不可少的。
在~/.vimrc文件最后添加:

" custom config
set number

winmanager

这是一个可以在vim中显示出一个文件管理窗口的插件,插件主页为:
http://www.vim.org/scripts/script.php?script_id=95
下载插件后,按页面上的install details进行安装,然后在~/.vimrc中添加:

nmap mm :WMToggle

这里把打开/关闭窗口的快捷键映射成mm,更方便试用。

ctags

使用过IDE的话应该都用过“跳转到函数定义”之类的功能,ctags即使提供此类功能的一个工具。奉行简单折腾原则,直接在apt里安装:

# apt-get install ctags

用ctags命令在你要阅读的源代码根目录下生成tags文件:

$ cd ~/SourceCodeFolder
$ ctags -R

然后在~/.vimrc文件最后添加相应的配置,指定tags文件的位置:

" ctags
set tags=tags;

这条设置会让vim自动在当前或上层文件夹中寻找tags文件,很方便。
常用操作:

<C-]>      跳转到光标所在函数的定义处
<C-T>      跳回调用处

taglist

taglist是一个vim插件,可以在vim中显示一个边栏样式窗口,将ctags分析到的所有tag以列表的样式显示出来,插件主页为:
http://www.vim.org/scripts/script.php?script_id=273
下载插件后,按页面上的install details进行安装,然后在~/.vimrc中添加:

" taglist
let TList_Show_One_File = 1            "只显示当前文件的Tag
let TList_Exit_OnlyWindow = 1          "当只剩下taglist窗口时,退出vim
let TList_Use_Right_Window = 1         "显示在右侧
let TList_GainFocus_On_ToggleOpen = 0  "打开时焦点不放在tl窗口中
nmap tl :TlistToggle<cr>               "绑定打开快捷键为tl

然后用vim打开已经生成过tags的某个项目文件,普通模式下输入tl,即可打开/关闭taglist窗口。
常用操作:

tl         打开/关闭taglist窗口(自定义)
<space>    在状态栏显示光标处tag的定义
<cr>       跳转到光标处tag的定义(也可用鼠标双击)
o          在新窗口中打开光标处的tag
u          更新tl窗口中的tag
s          更改排序方式
x          tl窗口放大和缩小
+/zo       打开一个折叠
-/zc       将tag折叠
*/zr       打开所有折叠
=/zm       将所有tag折叠

Cscope

Cscope算是一个增强版的ctags。ctags可以跳转到函数的定义,却无法查看此函数的所有调用,而Cscope可以做到这一点。
用apt安装Cscope:

# apt-get install cscope

然后在源码根目录下,执行

$ cscope -Rbkq

这会在源码目录中生成三个文件:cscope.out,cscope.in.out,cscope.po.out,其中cscope.out是我们需要的,其他两个是参数q的副产品。
方便起见,将添加索引文件的命令直接放到~/.vimrc中:

" cscope
set cscopequickfix=s-,c-,d-,i-,t-,e-
if filereable("cscope.out")
    cs add cscope.out
elseif $CSCOPE_DB != ""
    cs add $CSCOPE_DB
endif

这样vim就会在当前目录自动寻找cscope.out文件并引用了。
上面第一个配置是设置cscope可以使用quickfix窗口。当我们要查找函数的调用时,只会跳转到第一个结果,这时候,输入:cw打开quickfix窗口即可在新的quickfix窗口中查看其余的结果,用回车或双击跳转。
使用Cscope时,通常用下面这个命令:

:cs find c|d|e|f|g|i|s|t name

find可以简写成f。下面是选项的含义:

s         查找本 C 符号(可以跳过注释)
g         查找本定义
d         查找本函数调用的函数
c         查找调用本函数的函数
t         查找本字符串
e         查找本 egrep 模式
f         查找本文件
i         查找包含本文件的文件

使用速查

基本

%         跳转到配对的括号去
[[        跳转到代码块的开头去(但要求代码块中'{'必须单独占一行)
gD        跳转到局部变量的定义处
''        跳转到光标上次停靠的地方, 是两个', 而不是一个"
mx        设置书签,x只能是a-z的26个字母
`x        跳转到书签处("`"是1左边的键)

特定窗口

mm        打开/关闭winmanager窗口
tl        打开/关闭taglist窗口
:cw       打开quickfix窗口

多窗口操作

:split          水平分割当前窗口
:vsplit         垂直分割当前窗口
:split file     水平分割当前窗口,并打开文件file
:vsplit file    垂直分割当前窗口,并打开文件file
:close          关闭当前窗口
:qa             关闭所有窗口
<C-w> h|j|k|l   移动光标到左/下/上/右边窗口

生成索引命令

$ ctags -R
$ cscope -Rbkq

Ctags

<C-]>     跳转到光标所在函数的定义处
<C-T>     跳回调用处

taglist

<space>   在状态栏显示光标处tag的定义
<cr>      跳转到光标处tag的定义(也可用鼠标双击)
o         在新窗口中打开光标处的tag
u         更新tl窗口中的tag
s         更改排序方式
x         tl窗口放大和缩小
+/zo      打开一个折叠
-/zc      将tag折叠
*/zr      打开所有折叠
=/zm      将所有tag折叠

Cscope

:cs f c|d|e|f|g|i|s|t name
s         查找本c符号(可以跳过注释)
g         查找本定义
d         查找本函数调用的函数
c         查找调用本函数的函数
t         查找本字符串
e         查找本egrep模式
f         查找本文件
i         查找包含本文件的文件

参考文章

本文参考了以下几篇文章,算是综合并简化,更详细的配置可以参考它们:
手把手教你把Vim改装成一个IDE编程环境
vi/vim使用进阶: 使用taglist插件
vi/Vim + Cscope/Ctags

不折腾地建立一个清爽的Debian桌面系统

0

为了让一台老笔记本发挥余热,决定在上面装上Debian来当成一个移动开发环境用。原版Debian装好之后,发现乱七八糟带的东西太多,正好因为nv显卡驱动的问题把系统搞坏了,遂决定重新装个清爽的Gnome桌面。

软件绝大部分用apt-get来安装,系统也没有优化(不是主力系统,不打算折腾,够用就行)。

基础系统的安装步骤不再复述,注意安装语言最好选择英文(否则刚装好控制台模式一堆乱码),最后的安装包选择中,去掉Desktop enviroment的选择,只保留Standard system(笔记本则再选上Laptop)。

装好之后,登录进系统,开始安装桌面环境(所有操作均在root下进行):

修改源列表

$ vi /etc/apt/sources.list

国内现在163的源很不错(非服务器可以放心的用testing):

deb http://mirrors.163.com/debian testing main non-free contrib
deb http://mirrors.163.com/debian testing-proposed-updates main non-free contrib
deb http://mirrors.163.com/debian-security testing/updates main non-free contrib

deb-src http://mirrors.163.com/debian testing main non-free contrib
deb-src http://mirrors.163.com/debian testing-proposed-updates main non-free contrib
deb-src http://mirrors.163.com/debian-security testing/updates main non-free contrib

后面可以再添加一组官方源备用:

deb http://ftp.debian.org/debian testing main non-free contrib
deb http://ftp.debian.org/debian testing-proposed-updates main non-free contrib
deb http://security.debian.org/ testing/updates main non-free contrib

deb-src http://ftp.debian.org/debian testing main non-free contrib
deb-src http://ftp.debian.org/debian testing-proposed-updates main non-free contrib
deb-src http://security.debian.org/ testing/updates main non-free contrib

更新源列表

$ apt-get update

更新软件时可以普通更新:

$ apt-get upgrade

或深度更新(把内核更新到3.0吧~):

$ apt-get dist-upgrade

添加语言支持

$ dpkg-reconfigure locales

选择上en_US.UTF-8zh_CN.UTF-8,并将en_US.UTF-8作为默认。
然后安装中文字体:

$ apt-get install ttf-wqy-zenhei ttf-arphic-ukai ttf-arphic-uming

依次为黑体,楷体,宋体

安装Gnome

Debian默认的桌面管理器是gdm

$ apt-get install gdm3

安装控制台Gui:

$ apt-get install gnome-terminal

启动Gnome:

$ /etc/init.d/gdm3 start

这样子一个非常清爽的Gnome桌面就被安装上来了。不过看看Application菜单,清爽得过头了吧?
连个主题都没,要自己装:

$ apt-get install gnome-themes gnome-themes-extra

无线网络支持

有些笔记本无线网卡需要iwlwifi模块(参见http://wiki.debian.org/iwlwifi

$ apt-get install firmware-iwlwifi wireless-tools
$ ifconfig wlan0 up

状态栏是找不到网络连接管理器的,要自己装(vpn模块也装了吧,天朝必备):

$ apt-get install network-manager-gnome
$ apt-get install network-manager-pptp

安装输入法

输入法使用ibus,由原scim的作者开发:

$ apt-get install ibus ibus-pinyin

然后在系统菜单中选择Application->System Tools->IBus来启动输入法
在状态栏找到输入法图标,右键选择Preferences,切换到Input Method选项卡,选择Chinese->Pinyin之后点Add,然后就可以通过Ctrl+空格来切换输入法了。

安装浏览器

这样子装上Gnome后是连个浏览器也没有的,可以通过wget下载一个来装。
我这里装的是Chrome Beta:

$ wget http://dl.google.com/linux/direct/google-chrome-beta_current_i386.deb

然后用dpkg来安装:

$ dpkg -i google*.deb

其他常用软件

编辑器gedit和vim:

$ apt-get install gedit
$ apt-get install vim gvim

快速看图工具:

$ apt-get install eog

播放器mplayer:

$ apt-get install mplayer gnome-mplayer

字典(牛津双解为stardict-oxford-gb,搜索下载):

$ apt-get install stardict

至此这个系统已经是可用的了,干干净净,比发行包里的看上去舒服太多了~

使用Git进行小项目代码管理

1

之前在公司使用过SVN(无甚感觉)和ClearCase(把人恶心死的东西)两种版本控制工具,都不满意。后来想自己写点东西玩,就发现了这个在国内人气还不怎么高的Git,这个由Linus实现的灵活小巧的VCS。对它的印象差不多可以这么说:“我被萌到了”。
通过采用不同类型的工作流,Git可以适用于各种大小规模的项目。这里介绍一下针对最简单的集中式工作流的配置方式,适合个人和小型团队使用。
注:本文只是一个快速流程,要详细了解Git使用方法的话,强烈推荐阅读《Pro Git》这本书(见本文末尾的参考)。流程中需要一台服务器或VPS(越来越感受到VPS这东西对程序员真有用啊)。

安装Git

Git是跨平台的,在Linux/Mac/Windows上都可以使用,它的分布式特性也使得个人可以在多种平台下方便地进行开发。
Linux
作为桌面系统用的Linux大多是Debian系的,安装很方便,执行下面命令即可:

$ sudo apt-get install git-core

Mac OS X
如果安装了Xcode 4的,里面就已经包含了Git。也可以从这里单独安装:
http://code.google.com/p/git-osx-installer/downloads/list?can=3
Windows
window平台可以安装msysgit:
http://code.google.com/p/msysgit/downloads/list?can=3
喜欢图形界面的可以再加上TortoiseGit:
http://code.google.com/p/tortoisegit/downloads/list

初次配置

执行下面两条命令来配置用户信息,他们会用于Git提交时的签名:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

建立本地Git仓库

在你的项目目录下执行:

$ git init

这会在你的项目目录下建立一个.git目录,存储所有Git所需的资源。
然后我们该往项目中添加文件了。不过在这之前,最好先建立一个名为.gitignore的文件,来把一些不需要的文件或文件夹排除掉。比如在Mac下有时会在当前目录下产生一个.DS_Store的文件,这对我们的项目是无用的,我们就可以把它排除掉,而一些文本编辑器会使用以~结尾的备份文件,也要排除掉:

.DS_Store
*~

《Pro Git》的2.2节对此规则有更详细的介绍。
然后我们就可以进行文档的添加了,如果是按照上面把忽略规则设定好了的话,可以简单地执行:

$ git add .

这会把忽略规则以外的所有文件都添加进来,也可以这样:

$ git add *.c

来添加部分文件。Git还可能会忽略.gitignore文件,需要手工添加:

$ git add .gitignore

添加好文件后,就进行第一次提交:

$ git commit -m 'initial project version'

Git要求所有地提交都要包含说明文字,-m后面地即为说明,这是一种快捷地做法,也可以只用git commit,然后在切换到的界面中编辑说明文字。

建立服务器端

Git是分布式的版本管理软件,不需要服务器端也可以使用,但若要进行多人/多设备协同开发,还是要架设一个服务器端。
首先把刚才建好的本地仓库导出为裸仓库,在项目的上级目录执行:

$ git clone --bare my_project my_project.git

这会新建一个my_project.git文件夹,差不多和项目目录.git文件夹中的内容一样。
使用scp命令(或其他方式)把它上传到你的服务器上:

$ scp -r my_project.git user@git.example.com:/var/git

服务器上存放的目录可以是任意位置,目录的访问权限其实就和通过Git访问的权限相同(使用ssh协议来访问代码),比如你的项目是私人的,就可以放在你的home目录中。
上传之后本地的my_project.git就可以删掉了。
如果你的服务器端还没有安装git的话,这时是无法通过Git获取代码的,很简单,还是通过

$ sudo apt-get install git-core

命令,在服务器端安装Git。
现在就可以在本地通过Git来获取这个项目了:

$ git clone user@git.example.com:/var/git/my_project.git

这会在当前目录下建立一个my_project文件夹,里面包含项目源码和git仓库。也可以在上面的命令后再添加一个参数,来制定这个文件夹的位置和名称。

本地仓库和服务器端的关联

我们通过git clone命令抓下来的项目会自动和抓取的服务器端关联好,这样如果你确保前面添加到库中的文件没有遗漏,就可以把它删掉,再新clone下来的项目目录下进行开发(这样最简单最懒)。
也可以手工为原项目建立关联,在最初的项目目录中执行:

$ git remote add origin user@git.example.com:/var/git/my_project.git

这条命令就是把刚才做好的服务器端仓库添加为远程仓库,名字叫origin。
这时已经可以通过git fetch origin和git push origin master命令来抓取和推送代码了,但这样会比较麻烦(git fetch不会自动将远端分支合并到当前工作的分支)。
为了之后的使用方便,要设置本地的master分支跟踪远程仓库的master分支:

$ git checkout --track origin/master
$ git checkout --set-upstream master origin/master

这条命令即让本地master分支跟踪远程仓库origin中的master分支。
设置好更总后如果我们需要从远程仓库抓取数据,只需要运行

$ git pull

即可。而本地数据变动后,要提交到远程仓库,则执行:

$ git push

使用git部署网站

以前写好了网页就用ftp工具上传到服务器上,这样子没有版本控制的发布行为可能会导致很多问题。既然现在我们用git来管理项目,那也可以用它来发布网站。
假设刚才我们的my_project是为sojingle.net做的网站,要放在服务器的/var/www/sojingle.net/htdocs/www目录下,则可以在服务器端执行

$ git clone user@git.example.com:/var/git/my_project.git /var/www/sojingle.net/htdocs/www

如果网站和git服务器在同一个主机的话,也可以使用本地文件协议来抓取:

$ git clone /var/git/my_project.git /var/www/sojingle.net/htdocs/www

不止是网站,有些软件也是通过这种方式来发布。比如HomebrewRVM,在更新本地软件时,就是利用git来更新。

新建develop分支

Git除了分布式这一大特性外,还大大强化了分支的使用。我们日常的开发工作一般不在master分支上进行,而是最好建立一个develop分支:

$ git checkout -b develop

开发时,最好基于develop分支再新建一个特性分支,比如我们要为网站添加一个新功能“标签支持”,就为其新建一个分支tag_support,新功能开发完成之后,将其合并到develop分支上:

$ git checkout develop
$ git merge tag_support

这就将新功能的代码合并到了开发主分支上,合并过程没有冲突的话,就可以删掉这个分支:

$ git branch -d tag_support

当做好了一组新功能,决定要发版本了,就用可以把develop分支合并到master分支上,git push推送到远程仓库。在服务器端的www目录中,再来执行git pull,即可把网站更新到最新版本。

推荐及参考

《Pro Git》 http://progit.org/book/zh/
这本书的作者是GitHub的员工,写得非常棒,大量的配图把Git的分支管理讲得非常清楚。而且非纸质书是免费的,已经有了中文版翻译,可以直接在线阅读。
《Git开发管理之道》 http://blog.leezhong.com/translate/2010/10/30/a-successful-git-branch.html
这篇文章主要讲的是软件开发中的分支管理模型,很值得一读。

Debian上Apache的单IP多主机配置

0

现在租VPS或者主机的人挺多,这比起租虚拟主机最大的好处就是灵活(麻烦)。VPS和主机一般也比较贵,多人合租比较普遍,而Apache服务器通过很简单的配置,就能支持多个网站的架设,下面介绍一种最简单花费最小的方案:基于域名的多主机配置(只需要一个IP即可)。

假设我们要绑定两个域名:sojingle.net和example.com,Apache版本为2.2,服务器IP为111.111.111.111

设置DNS指向

在你域名的DNS管理器中,设置A记录指向:

sojingle.net:
  @ -- 111.111.111.111
  blog -- 111.111.111.111
example.com:
  @ -- 111.111.111.111

CNAME记录:

sojingle.net:
  www -- @
example.com:
  www -- @

这样我们预备建立三个站点的访问:http://sojingle.net和http://www.sojingle.net访问主页,http://blog.sojingle.net访问博客,http://example.com和http://www.example.com访问另一个主页。为xxx.com和www.xxx.com都提供对主页的访问是一个好习惯(使用跳转也行)!

建立目录

首先要为虚拟主机建立文件目录,我们放在Debian系的标准目录/var/www下面,当然也可以使用其他位置。

root@vps:~# mkdir /var/www

root@vps:~# mkdir /var/www/sojingle.net
root@vps:~# mkdir /var/www/sojingle.net/htdocs
root@vps:~# mkdir /var/www/sojingle.net/logs

root@vps:~# mkdir /var/www/example.com
root@vps:~# mkdir /var/www/example.com/htdocs
root@vps:~# mkdir /var/www/example.com/logs

以上这一段就准备好了两个最基本的网站目录结构,htdocs目录用于放置网站内容,logs目录放置网站日志。

设置监听IP和端口

Debian下Apache的配置文件结构和RedHat系的不太一样(网上的资料以RedHat为基础的居多),主要的配置放在/etc/apache2/apache2.conf中。目录下的httpd.conf文件初始是空的,主要用于放置一些对所有用户生效的配置。

编辑/etc/apache2/ports.conf文件:

NameVirtualHost vps111:80
Listen 80

为了之后配置升级的便利,这里指定监听vps111的80端口。vps111也可以直接写成服务器的IP,不过为了在IP地址发生变更时更方便改动(我的VPS就迁了好几次机房了),这里用主机名来代替,IP发生改变时,只需要改hosts文件即可。当然,现在也要把它添进去。
修改/etc/hosts文件:

111.111.111.111 vps111

如果你之后需要设置ssl,要监听443端口,只需在ports.conf中添加类似的两条记录,将80改为443即可,原配置无需改动。如果添加了一个IP地址,将新加配置的vps111替换为新的主机名即可。

添加虚拟主机配置

Debian将虚拟主机的配置放置在/etc/apache2/sites-available目录下面,这个目录下为可用的虚拟主机。还有一个目录是/etc/apache2/sites-enabled,这里为已启用的虚拟主机。实际上这个目录中的文件就是sites-available下相应文件的软链接。
sites-available目录下已经有了两个默认的配置:default和default-ssl。我们使用a2dissite命令把它们停用掉:

root@vps:~# a2dissite default
root@vps:~# a2dissite default-ssl

会提示你重新加载配置来生效,可以先不管它,最后一起来。

在sites-avaliable目录下新建文件sojingle.net

<VirtualHost vps111:80>
  ServerAdmin sojingle@sojingle.net
  ServerName sojingle.net
  ServerAlias www.sojingle.net
  DocumentRoot /var/www/sojingle.net/htdocs/www
  ErrorLog /var/www/sojingle.net/logs/error.log
  CustomLog /var/www/sojingle.net/logs/access.log combined
</VirtualHost>

在/var/www/sojingle.net/htdocs下创建www目录,用于放置通过http://sojingle.net和http://www.sojingle.net访问的内容。
然后为example.com做类似的配置(把上面的sojingle.net替换掉即可)。

启动虚拟主机

好了,执行命令:

root@vps:~# a2ensite sojingle.net
root@vps:~# a2ensite example.com
root@vps:~# /etc/init.d/apache2 reload

通过你的域名访问一下,是不是可以看到一个目录列表啦?当然,我们要把显示目录列表这个不安全的功能给禁用掉:
在/etc/apache2/httpd.conf文件中添加:

Options -Indexes

再执行命令使它生效:

root@vps:~# /etc/init.d/apache2 reload

把你的网站放进www目录下吧~

子域名的配置

如果你想使用子域名,比如blog.sojingle.net来架设博客,也很简单,子域名的DNS指向只要配置到这个IP,为其新建个虚拟主机即可。
在/etc/apache2/sites-avaliable/sojingle.net文件中添加:

<VirtualHost vps111:80>
  ServerAdmin sojingle@sojingle.net
  ServerName blog.sojingle.net
  DocumentRoot /var/www/sojingle.net/htdocs/blog
  ErrorLog /var/www/sojingle.net/logs/blog_error.log
  CustomLog /var/www/sojingle.net/logs/blog_access.log combined
</VirtualHost>

这段加在sojingle.net配置的上面或下面都可以,但放在上面的话,在解决泛域名解析问题时会更方便,见后面的内容。
建立/var/www/sojingle.net/htdocs/blog目录,重载apache配置之后,就可以把wordpress上传解压到这个目录架设博客了。

解决泛域名解析问题

如果你在DNS指向中,使用了泛域名解析(即将*.sojingle.net指向了本服务器IP:111.111.111.111),那么在这种基于域名的设置中,可能会产生这样一个问题:我访问了一个未设置的子域名a.sojingle.net,可能会跳转到example.com(也可能是反过来)。这是因为当apache拿这个子域名去匹配时,发现没有这样的一个ServerName或ServerAlias,就会返回此IP的默认网站(可能是首字母顺序排列的第一个吧)。要避免这种情况的发生,为*.sojingle.net设置ServerAlias即可。修改/etc/apache2/sites-avaliable/sojingle.net文件,在sojingle.net配置的ServerAlias下添加一行,变为:

ServerName sojingle.net
ServerAlias www.sojingle.net
ServerAlias *.sojingle.net

这样访问所有为设置的子域名时,就会打开sojingle.net。不过这样就要求配置文件中,子域名的配置要放在域名的前面,否则你设置的子域名也会被跳转到域名下。
为example.com也做相应的设置。

参考

Hosting multiple websites with Apache2 http://www.debian-administration.org/articles/412
Name-based Virtual Host Support http://httpd.apache.org/docs/2.2/en/vhosts/name-based.html
参考文档中有更详细的设置或解释,推荐读一读。

Chrome插件: EasyJump

0

EasyJump是一个Chrome插件,也算是我的练手作。

以前看每次看bilibili周刊排行榜的时候,遇到还没有看的视频,想打开的时候总是要自己在地址栏里面输网址,总是会打断视频,很不爽,于是就想着做这样一个插件:匹配一个输入的字符串,然后在后台打开相对应的网站。现在插件做出来了,但bilibili也已经改得可以在搜索框里面输入编号跳转了。不过因为这插件支持自定义,应该还是有不少用处的,比如经常放出下载的时候都是一个115网盘的编号,直接在插件里输入“115+编号”就可以跳转到下载页,像我这种懒人应该还是会喜欢滴~

气泡窗口:

设置界面:

总之,功能极其简单,界面极其简陋 -_-||

今天又给插件弄了个页面,加了些简单的说明:

EasyJump

代码放在了GitHub上:

EasyJump Source Code

因为是第一次写Chrome插件,直接跑去翻了翻Samabox的iReaderProxy Switchy!的代码(也是我很喜欢的两个插件),从组织结构上学了不少,这里要表示感谢~

VitrualBox虚拟机上用Debian做LFS

0

这周和元元同学一起在Debian上做了一遍LFS 6.8,由于没有用LFS的Live CD,中间出了点小麻烦,但总归顺利搞定。这次做得有点走马观花,有时间还要把文档再读一读。
下面是这次遇到的一些小经验,用LFS Live CD的话,遇到的问题应该会少些:

  1. 将系统中的mawk卸载掉,换成gawk,否则再Glibc的编译过程中会出错。
  2. host系统装好后,先装上build-essential,很方便的架起初次编译环境。
  3. 安装bzip2包,以解压bz2文件。
  4. 安装zip包,否在在gcc的第二次编译时会出错。
  5. 如果是手工录入命令的话,要注意在用sed命令修改文件时,一定要仔细检查(在编译perl前修改文件时,就因为少了“=”后面的一个空格导致编译错误,费了很大劲才找出原因)。
  6. 第三章要下载的包里面,Shadow的ftp链接已经失效,可以换用http下载链接:http://pkg-shadow.alioth.debian.org/releases/shadow-4.1.4.3.tar.bz2
  7. 在8.4.3节要对Grub的配置进行测试,可能是因为我用的是Debian,版本上有些不兼容,无法使用kernel命令进行测试。因此在写入MBR之前,要做好引导盘,用虚拟机的话,要做好快照。
  8. 每次重启后要记得检查一下环境变量是否设置好了,进入chroot阶段后若再重启了,要注意重新执行6.2.2和6.2.3节。
  9. 虚拟机是个好东西,在虚拟机上做LFS可以用“快速休眠”来保存当前工作状态,免得再开机后还要在设置环境变量和挂载。在最后写入MBR之前,如果能做个系统快照,万一出现错误时会方便很多(深有体会- -+)。
总之,若足够认真的话,这一路下来会很顺利,关键还是在阅读LFS时好好的把文档理解掉,这才是最有用的东西~

JavaScript的正则表达式用法整理

0

最近在写一个Chrome插件作为对JavaScript的练手,其中用到了一些关于正大表达式的东西,整理一下:

JavaScript中使用正则表达式一般会涉及到的两个对象为:RegExpString。一个RegExp对象表示一个正则表达式,而String对象则包含一些支持正则表达式的方法。

创建正则表达式对象

直接量语法:

/pattern/attributes
var regexp = /\w+/m

构造函数法:

new RegExp(pattern, attributes);
var regexp = new RegExp("\\w+", "m")

字符串是不能直接当作正则表达式使用的,需要先用构造函数创建对象。注意\w在字符串中要对\进行转义。

检查是否匹配

RegExp方法:

RegExpObject.test(string)
if(regexp.test(sourceString))
RegExpObject.exec(string)
if(regexp.exec(sourceString) != null)

String方法:

stringObject.search(regexp)
if(sourceString.search(regexp) != -1)
stringObject.match(regexp)
if(sourceString.match(regexp) != null)

获取匹配的字符串

RegExp方法:

RegExpObject.exec(string)
document.write(regexp.exec(sourceString))

String方法:

stringObject.match(regexp)
document.write(sourceString.match(regexp))

字符串替换

stringObject.replace(regexp/substr,replacement)
ducument.write(sourceString.replace(regexp, "http://sojingle.net/$&"))

replacement中,”$&”代表表达式匹配到的字符串。

子表达式替换

如果替换的内容为匹配字符串的一部分,比如要在一组字符串中找到”symbol1234″并替换为”http://sojingle.net/1234″,则可以使用子表达式特性。即在正则表达式中使用“()”来创建子表达式。
此例即为

var regexp = /symbol([0-9]+)/

这样的话,

document.write("url: symbol1234".replace(regexp, "http://sojingle.net/$&"))

输出为”url: http://sojingle.net/symbol1234″。

ducument.write("url: symbol1234".replace(regexp, "http://sojingle.net/$1"))

输出为”url: http://sojingle.net/1234″。
子表达式匹配到的文本范围是$1~$99。


更详细的内容,参见W3school的文档:RegExp & String

给Linode VPS配置自签名SSL和VPN (Debian)

0

为了防止我天朝功夫网的侵害,要给twitter的代理添上SSL,因为是自己用,就省得花钱去买SSL证书了,来弄个自签名的:

SSL的配置是参照 http://www.debian-administration.org/articles/284 ,下面把主要步骤简化一下,翻译过来:

1. 安装openssl

> apt-get install openssl

2. 创建工作文件夹,home目录就好。之后的操作都在此文件夹中进行

mkdir CA
cd CA
mkdir newcerts private

3. 创建证书数据库

echo '01' > serial
touch index.txt

4. 自定义openssl配置文件

创建openssl.conf,内容如下(黑体部分自己要修改一下):

#
# OpenSSL configuration file.
# 

# Establish working directory. 

dir = . 

[ ca ]
default_ca = CA_default 

[ CA_default ]
serial = $dir/serial
database = $dir/index.txt
new_certs_dir = $dir/newcerts
certificate = $dir/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 365
default_md = md5
preserve = no
email_in_dn = no
nameopt = default_ca
certopt = default_ca
policy = policy_match 

[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional 

[ req ]
default_bits = 1024 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = md5 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req 

[ req_distinguished_name ]
# Variable name   Prompt string
#----------------------   ----------------------------------
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64 

# Default values for the above, for consistency and less typing.
# Variable name   Value
#------------------------------   ------------------------------
0.organizationName_default = The Sample Company
localityName_default = Metropolis
stateOrProvinceName_default = New York
countryName_default = US 

[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always 

[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash

5. 创建CA证书和私钥

#openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem \
-out cacert.pem -days 3650 -config ./openssl.cnf

需要创建验证密码,把这个记下来

writing new private key to 'private/cakey.pem'
Enter PEM pass phrase:demo 
Verifying password - Enter PEM pass phrase:demo

创建过程中会要求输入一些信息,这里的这个Common Name不是很重要。

Organization Name (company) [The Sample Company]:
Organizational Unit Name (department, division) []:CA Division
Email Address []:ca@sample.com 
Locality Name (city, district) [Metropolis]:
State or Province Name (full name) [New York]:
Country Name (2 letter code) [US]:
Common Name (hostname, IP, or your name) []:TSC Root CA 

6.创建认证请求

openssl req -new -nodes -out req.pem -config ./openssl.cnf

此步骤中Common Name一定要填上要认证的网址

Organizational Unit Name (department, division) :Mail Server 
Email Address :postmaster@sample.com 
Common Name (hostname, IP, or your name) :mail.sample.com

7. 给证书签名

openssl ca -out cert.pem -config ./openssl.cnf -infiles req.pem

输入刚才的CA密码

Enter PEM pass phrase:demo 

然后两次 ‘y’ 确认之后,签名成功

8. 给证书加密

mv cert.pem tmp.pem
openssl x509 -in tmp.pem -out cert.pem

9. 有些程序需要将key和证书在一个文件中,可以这样合并

cat key.pem cert.pem >key-cert.pem

10. 把key.pem和cert.pem移动到合适的地方,然后在Apache中配置虚拟主机(/etc/apache2/sites-available/)

<VirtualHost xxx.xxx.xxx.xxx:443>
    ServerAdmin xxxxx@gmail.com
    ServerName mail.sample.com
    DocumentRoot /var/www/sample.com/public_html/mail
    ErrorLog /var/www/sample.com/logs/mail_ssl_error.log
    CustomLog /var/www/sample.com/logs/mail_ssl_access.log combined
    SSLEngine On
    SSLCertificateFile /var/www/sample.com/ssl/cert.pem
    SSLCertificateKeyFile /var/www/sample.com/ssl/key.pem
</VirtualHost>

11. 若是多个主机共用一个IP,则可在ports.conf中添加上

NameVirtualHost xxx.xxx.xxx.xxx:443

12. 重新加载Apache配置即可

/etc/init.d/apache2 reload

13. Stunnel的配置为:

stunnel -p /etc/ssl/certs/key-cert.pem

通过这个简要的步骤,自签名的SSL就配置成功了,如果需要更详细的内容,还是看原文吧~ http://www.debian-administration.org/articles/284

更新:强制使用https访问的方法

如果要强制使用https方式来访问网站,则可以在虚拟主机的配置中(/etc/apache2/sites-available/),找到网站的http访问配置,在其中添加这么一段:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

这样就将所有http访问转向了https。
———————————
VPN也是个必需品,联通3G和小区宽带都不支持PPTP,所以要配一个L2TP的,http://www.vpsyou.com/l2tp-vpn/ 这里有个一键安装脚本,很方便:

wget http://mirror.zeddicus.com/auto-l2tp/1.2/ubuntu/l2tp.sh
chmod +x l2tp.sh
./l2tp.sh
回到顶部