Mar 16, 2009 at 6:44am
Tags: ksh
用 TETware 做自动化测试框架,越来越觉得这玩意很差,至少是 ksh API 这部分,用我同事的话说,已经“out”了,在我手上改了不少,仍然不够好用。今天竟然发现一个记 log 的接口里面竟然会死循环,调查下去竟然是个 ksh93 的 bug,要不是这个接口写得这么烂,也许这个 bug 永远都见不到天日了。
废话扯完了,看看是什么 bug。
${parameter%pattern} 用来从 parameter 字符串中去掉 pattern 后缀,${parameter#pattern} 用来从 parameter 字符串中去掉 pattern 前缀,这两个经常用来取路径名中的目录和文件名。但是当 parameter 是个多行字符串并且 pattern 符合 “\n.*(.*).*” 模式时它们不干了:
$ cat ksh93bug
NL=$'\n'
PAT="$1"
A="Hello $NL$PAT"
echo "${A%$NL$PAT}"
A="$PAT$NL world"
echo "${A#$PAT$NL}"
$ ksh ksh93bug '()'
Hello
()
()
world
$ ksh ksh93bug 'a(b)c'
Hello
a(b)c
a(b)c
world
仅仅是 AT&T ksh93,包括最新版本都有这个问题,在 bash 和 public domain ksh 中没有问题:
$ bash ksh93bug '()'
Hello
world
$ bash ksh93bug 'a(b)c'
Hello
world
我们的例子是 out=$(mount) 接着 tet_infoline "$out"它就歇菜了,TETware 的 tetapi.ksh 在 tet_output 函数里面用 %% 在循环里面去处理多行文本,哪里想到后缀永远删除不掉,在我试图加 set -x 调试的时候迅速的将硬盘写满了:P
本想报告这个 bug,在 ksh93 主页 上没找到给谁报,懒得伺候了,先改 TETware 再说了。
Feb 13, 2009 at 6:39pm
获悉 Sun 公司 Kernel Networking 北京开发组全组被裁,当年我在这个组实习,转正后虽然去了别的组,无论工作还是私人关系都比较紧密,虽然知道是迟早的事,心里还是非常不好受。又悉其中三人转移到其他组,技术都很牛的三人,其中两个还是我最为佩服的,稍感欣慰。现下行业不景气,和尚多庙少,被裁的兄弟恐怕不太容易找到满意的工作,祝他们好运。
Jan 8, 2009 at 6:43am
Tags: domain
忍不住还是把 joyus.net 注册了,过期半年了也没人要,怪可惜的。GoDaddy 还涨价了,还好汇率低。用这个 coupon 码 gdr0110m 可打 9 折,截至日期到这个月 22 号。
Jan 6, 2009 at 1:50am
Tags: python
Python 里 optparse 是一个很不错的命令行参数处理模块,不过当我想把 -h 用作指定 hostname 时发现默认的 -h 参数非常恼人,模块报告一个冲突,但是文档却没有记录如何解决这种问题。翻了源代码,找到解决办法:
方法一,初始化 OptionParser 的实例时指定 add_help_option=False,再自己添加一个 --help 选项:
parser = optparse.OptionParser(usage=usage, add_help_option=False)
parser.add_option('', '--help', action='help')
这样 -h 就空出来啦。
方法二,初始化 OptionParser 实例时指定 conflict_handler="resolve",然后就不用理会默认的 -h/--help 直接加自己的选项就行了,冲突时会只取用最后指定的选项。
parser = optparse.OptionParser(usage=usage, conflict_handler="resolve")
Jan 4, 2009 at 4:14am
Tags: shell
这天同事问了一个问题,shell 中如何重复显示指定数目的字符?例如显示 72 个等号(=)作为一个分界线。脑子里马上想到 perl 和 python 中这个实在是太容易了:
$ perl -e "print '=' x 72"
$ python -c "print '=' * 72"
但是 shell 中可没有这样的语法,想了半天,只想到一个利用 printf 命令结合 sed 的做法:
$ printf "%*s" 72 '' | sed 's/ /=/g'
"%*s" 这个 format string 后面的第一个参数是字符串显示宽度,第二个参数才是真正要显示的字符串(这里是空串),与 C 语言中的 printf 类似。
虽然这个 printf 有点妙,不过后面跟了个 sed 才算解决问题,作为一种脚本语言,Shell 有时让人觉得实在是太弱了。应该有更好的解法……
Dec 14, 2008 at 12:58am
Tags: life and vps
一晃已经在新公司 uptime 满 1 年了,甘苦自知。最近特别忙,一是新一版本发布在即,二是忙着给人擦屁股。让别人听自己的意见来干活,比埋头只干自己的可难多了。好在鄙人的意见都是具有建设性的,都有眼见的好处,目前没人找碴。难受的就是自己眼里很轻松的修改,别人那里成了累活,站在一旁看着强大的 vim 活生生被当成 notepad 用,要不是现在涵养有进步,一定会七窍生烟。
稍微闲一点,才发现 VPS 的 uptime 已经 96 天了,从上次迁移主机之后没有再出现任何问题。这个在 vpsvillage 购买的玩具般的 vps,已经使用了近半年啦。除了个 blog 和 wiki 外,最主要的用途乃是在公司使用 ssh 隧道做 socks5 代理,连接 MSN、Gtalk 和公司安全政策禁止访问的各类站点 :cool:,慢虽慢点,但是自由的感觉更重要。做个广告,还在用 bluehost,dreamhost 虚拟主机的、别再受那种鸟气了,玩玩 VPS 吧。
Nov 24, 2008 at 9:50pm
Tags: script and shell
用 iozone 跑出来的文件系统性能数据,格式示例:
# file-size initial-read
1k 3029.832
2k 3010.015
4k 3223.711
8k 3303.412
16k 3488.440
简单任务:将 Nk 替换成 N*1024 的结果,m 和 g 依此类推。目的是要对处理之后的结果用 gnuplot 作图。
用正则表达式很容易匹配目标文本,但可惜不能直接计算。我的解法是先将整个文本替换成一个可执行的 shell 脚本 - 第一行插入 "cat << EOF",最后一行添 "EOF",中间的 k, m, g 替换成 "$((..))",然后用 shell 解释执行,利用 shell 进行计算。有点土,不过至少可以方便批量处理。
sed -e '1i\cat << EOF' \
-e 's/\b\([0-9]\+\)k\b/$((\1*1024))/g' \
-e 's/\b\([0-9]\+\)m\b/$((\1*1024*1024))/g' \
-e 's/\b\([0-9]\+\)g\b/$((\1*1024*1024*1024))/g' \
-e '$i\EOF' \
iozone-out.txt | bash
将 sed 表达式写到一个单独的 .sed 文件,可方便批量处理。再完善一点就先把 $ 和 ` 转个义。
for f in *.txt; do sed -f x.sed $f | bash > $f.new; done
谁有更好的解法?
Nov 23, 2008 at 9:12pm
Tags: script and shell
简单任务 - 将多个连续的空行合并成一个空行。来自一个实际问题:打印一个很长的 RFC 文档,希望能省一些纸张。
很久以前就遇到过这个问题,因为发现 sed 不能匹配 '\n',当时的解法是写了个 shell 脚本处理。Vim 可以用 '\n' 匹配换行符,解决方案是:
vim '+%s/^\n\+/\r/g' +x rfc.txt
考虑空行上可以有空白字符的话,还能再完善一点:
vim '+%s/^\(\s*\n\)\+/\r/g' +x rfc.txt
这是目前的“最佳应法”,欢迎提供更佳的解法。
特别鸣谢:刚开始缺少 '^' 怎么都不能成功,经老婆指正方才解决。你怎么也想不到,我老婆作为一个文科生,竟然能把 vim 使得出神入化,还在她们公司内部做了一个四十分钟的讲座!
Oct 30, 2008 at 1:37am
Tags: firefox and imacros
iMacros 简单的说就是一个基于浏览器的录宏回放插件,利用它可以模拟任何人工的点击,除了手工录制,它还提供一套简单的脚本,还有 javascript,vbscript 等接口方便进行复杂的逻辑控制。听说了这个插件后我就在琢磨怎么用来自动网上约车。
我报的是东方时尚驾校预约计时班,网上约车每天从早 9 点开放到晚 9 点,只能约 7 天以内的。一般周末约的人非常多,我这次因为周末外出不能上网,错过了约车的时机,只能等人退订了我再抢,这个机会非常小,但还是有可能。
断断续续研究了几个小时,终于写出了一个 javascript 脚本调用 iMacros 的接口,并且大约半小时就成功抢到了退票,呵呵。
大概总结一下:
- Firefox 版本的插件安装地址
- 录制很简单,点击 record 然后鼠标键盘正常操作,结束后按 stop,然后查看脚本源码,获得第一手感性认识,然后可以对照手册自己添加一些代码
- SET !REPLAYSPEED FAST 用来设定回放速度为最快,即执行语句中间不等待
- SET !ERRORIGNORE YES 用来忽略错误
- REFRESH 用来刷新页面
- WAIT SECONDES=3 等待 3 秒
- ONDIALOG POS=1 BUTTON=CANCEL CONTENT= 看到弹出窗口后点 Cancel
写 js 用到的接口:
- iimPlay("CODE:...")执行 iMacros 的脚本语句,语句可以是一段,必须以 CODE: 开始,行间要用 "\n" 分隔,返回值为负数代表执行有错
- iimGetLastError() 返回最近错误对应的错误信息(字符串)
- iimDisplay(msg) 以独立对话框形式显示一个消息
- SET 语句只在一个 CODE: 块中有效
- Tag 未找到时会默认会等待 !TIMEOUT /10 这么常时间,默认值就是 6 秒
- 不支持使用 document.getElementById() 来判断 tag 是否存在
有了这些就可以用 js 来处理复杂的逻辑控制,我是在先在一个循环中登录,直到登录成功,然后点击预约按钮转到约车界面,然后点击相应的表格,表格对应的 id 可以直接查看源码得到,或者用 Web Developer,Colorzilla 等插件查看,判断返回值可知是不是约成功了,成功之后再点会变成取消,所以要增加 ONDIALOG 语句来点击 Cancel 按钮。