SVN Hook造成SVN提交速度慢的问题

单就个人感情来说,我其实喜欢git。但显然subversion才是更普遍的版本控制管理工具,适合用在团队开发中。

那么,有一个很常见的需求就是把工程师提交的代码,更新到htdocs目录,这时候需要用svn hook,简单做法就是写一个post-commit hook:

svn update /var/htdocs/

但当svn目录越来越大,文件越来越多的时候,svn提交也会越来越慢。因为每一次的提交都会造成整个svn的更新。

Read the rest of this entry »

SSH免密码认证进阶使用

大家都知道,SSH可以通过证书进行免密码认证(see)。不过长期以来,我对SSH证书认证都不太感冒,主要是安全方面的考虑:

当要管理多台服务器时,假定PC机是Local,分别有服务器:s1和s2。私钥放在Local,公钥分别放在两台服务器,那Local登录到两台服务器都可以不再需要密码认证。

但是从两台服务器之间呢?

由于两台服务器上都只有公钥,没有私钥,当从s1->s2,或者相反的时候,依然要输入密码认证。

除非你在s1和s2上都放私钥就可以解决这个问题,如果服务器数量再多的话,私钥管理起来就成问题,容易被窃取。

风险很大的说!有木有?有木有??(回答木有的那位:同学,你好,请点我

Read the rest of this entry »

匹配URL的正则表达式

如果你认为简单,你就错了

看大牛们的讨论:

Read the rest of this entry »

App Engine程序无法发布问题

一段时间以来,Google的HTTPS都很难连接。由于App Engine的程序发布需要透过HTTPS进行,HTTPS的连接问题造成的直接后果就是程序发布时卡住,死活发布不上去。

解法就是先建立一个tunnel,然后在appcfg.py文件增加:

import socks
import socket
socket.socket = socks.socksocket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 7070)

广告:欢迎Like Hacker News on Facebook

July 1st, 2011 update:

如果有HTTP代理的话,也可以依据官方的文档进行设置

支持自动重连的ssh tunnel脚本

在内网服务器架了一个SSH Tunnel服务供同事使用,但是经常由于网络原因造成中断,需要不断登录上去重连。

网上找到的方案主要分两种:

  • autossh – 这种必须通过ssh key的方式登录。由于买的shell帐号只能用于做Tunnel,并不能真正的登入进去,无法在服务器端生成公钥,所以这种方案不行;
  • 通过expect发送密码 – 方案是可行的,但是LinuxToy上的这个脚本也是通过执行远程命令来监测SSH连接,同上面的原因,我们买的shell帐号只能做Tunnel,不能执行命令;

没办法,又是自己写了一个脚本,通过nc来监测:

#!/bin/sh

if [ "$1x" != "connectx" ]; then

    if [ -z $1 ]; then
        echo "Usage: $0 [username@]host[:port]" 2>&1
        exit 0
    fi

    echo -n "Password: "

    stty -echo; read pass; stty echo; echo ""

    expect -- << EOF
        spawn $0 connect $1

        while 1 {
            expect {
                "password:" {
                    send "$pass\r"
                }
                "yes/no" {
                    send "yes\r"
                }
                "Permission denied" {
                    puts "Password error."
                    break
                }
            }
        }
EOF
else
    shift
    port=`echo $1 | perl -nle 'print /\:(\d+)$/ ? $1 : "22"'`
    while [ 1 ]
        do ssh -p $port -CN -D 0.0.0.0:7070 $1 target "while nc -zv localhost 7070; do sleep 20; done"
        sleep 20
    done
fi

登录内网服务器,将这个脚本保存为autossh.sh,打开screen,然后执行:authssh.sh [user@]remote[:port],再输入ssh密码。

正常情况下运行脚本,成功连接服务器之后会监听内网服务器的7070端口。

注意需要安装 expect 以及screen。

Vim+XDebug调试PHP

感谢老黑鸟哥发布的《PHP调试指南》(via)。本文是对指南中的《Vim + Xdebug + DBGp》一章的一些补充。

原理上,这种调试方式主要依靠Vim的插件“remote PHP debugger”来实现,该插件实现了一个DBGP服务端。调试的时候Xdebug将会与服务端建立一个连接进行通信,接收服务端的调试指令并返回调试结果。 Read the rest of this entry »

Windows系统上MySQLdb for Python 2.6

Windows平台 上,MySQLdb官方编译的二进制包貌似最高只支持Python 2.5,按照论坛里的帖子下载了一个非官方编译的版本,但是有两个问题:

  1. 要另外下载两个动态连接库文件:libguide40.dll和libmmd.dll;
  2. 会有一个警告信息:
    >>> import MySQLdb
    C:\Python26\lib\site-packages\MySQLdb\__init__.py:34: DeprecationWarning: the sets module is deprecated
      from sets import ImmutableSet

发现个不错的版本,不会有上面的问题:http://www.thescotties.com/mysql-python/test/

12.31更新: 发现一个更全Python Windows扩展收集 - http://www.lfd.uci.edu/~gohlke/pythonlibs/

[PHP]Base32编码/解码

一时兴起研究起BASE32,其实编码解码都还算简单,按照RFC 4648

编码:

  1. 将输入字符串的每个字符转成ASCII码;
  2. 以5个bit为一组进行二进制分割,最后一个字符如果不足5位的话就补零;
  3. 补高位转回十进制作为码表索引,参照码表就得到最终编码的字串;
         +--first octet--+-second octet--+--third octet--+
         |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
         +-----------+---+-------+-------+---+-----------+
         |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|
         +--1.index--+--2.index--+--3.index--+--4.index--+

解码:

  1. 参见码表,将输入字符串取得码表索引(8位);
  2. 将索引去掉前面3位,转成5位;
  3. 组合5位,再按8位一组进行分割,就取得了字符的ASCII码;
                        1          2          3
          01234567 89012345 67890123 45678901 23456789
         +--------+--------+--------+--------+--------+
         |< 1 >< 2| >< 3 ><|.4 >< 5.|>< 6 ><.|7 >< 8 >|
         +--------+--------+--------+--------+--------+
                                                 <===> 8th character
                                           <====> 7th character
                                      <===> 6th character
                                <====> 5th character
                          <====> 4th character
                     <===> 3rd character
               <====> 2nd character
          <===> 1st character

Read the rest of this entry »

批量文件编码转换

脚本文件 convert.sh:

#!/bin/sh
convert() {
    echo -ne "convert $1 ...\n"
    file -i $1 | awk -F = '$2 != "utf-8" && $2 != "unknown" {\
        print "iconv -f gb2312 -t utf-8 -o '$1'.tmp '$1'"\
    }' | sh
    [ -f ""$1.tmp"" ] && mv "$1.tmp" $1
}

run() {
    for file in `find $1 -type f -name "*.php" | grep -v bbs`
    do
        convert $file
    done
}

run $1

./convert.sh uchome/

Python通过正则表达式选取callback

最近在瞎想怎么通过xpath去精确抓取文章的正文,跟parselets类似的想法,只不过更简单。

代码设计上采用正则表达式匹配URL,再选择callback handler的方式,主要参考web.py的分发器(Dispatcher)。

#!/bin/env python

import re, sys

# Define parser first.
def baidu(username):
    # Business logic
    return "Using parser Baidu. and the user's name is: %s." % username

def qzone(uin):
    # Business logic
    return "Using parser Qzone, and the user's QQ is: %s." % uin

# From web.py
def group(seq, size):#{{{
    """
    Returns an iterator over a series of lists of length size from iterable.

        >>> list(group([1,2,3,4], 2))
        [[1, 2], [3, 4]]
        >>> list(group([1,2,3,4,5], 2))
        [[1, 2], [3, 4], [5]]
    """
    def take(seq, n):
        for i in xrange(n):
            yield seq.next()

    if not hasattr(seq, 'next'):
        seq = iter(seq)
    while True:
        x = list(take(seq, size))
        if x:
            yield x
        else:
            break
#}}}

def parser_init(url,mapping):
    for pat, what in group(mapping,2):
        result = re.compile('^' + pat + '$').match(url)
        if result:
            return what, [x for x in result.groups()]
    return None, None

if __name__ == '__main__':
    mapping = (
            'http://(?:hi|space).baidu.com/([^/]+)(?:/.*)?','baidu',
            'http://(\d+).qzone.qq.com(?:/.*)?','qzone',
            )

    (func, args) = parser_init(sys.argv[1],mapping)
    if func:
        callback = func

        if func in globals():
            callback = globals()[func]

        if callable(callback):
            print callback(*args)
    else:
        print 'No parser found.';

当然,这个实现比较老土一些,全部用function的方式回调,没有用类,可以参考web.py去做适当的修改。