Main

March 3, 2011

可能很多人不知道,Emacs 里包含了一组对 GNU 网络工具包的包装。

多数的工具只是简单的包装,与直接执行命令差不多,但是增加了高亮。但是有一些增加了完整的 Emacs comint 的支持,比如 nslookup。补充一下,Comint 是 Emacs 的一个包,用于与外部程序进行交互。

另一个有用的特性是内建了 ffap(Find File At Point) 支持,也就是说如果使用的是下面列出的交互式网络工具,会判断当前的光标所在位置是主机名还是 IP 地址或者是自己默认的什么东西。

这些网络工具包是用 GNU 开发包编写的,所以 Windows 的用户还得自己去下载 for Win32 的版本。这里附上两个地址 GnuWinGNU Utils for Win32,大家各取所需。

下面列出了 Emacs 支持的工具,直接用 M-x 来调用。你也可以配置成自己喜欢的程序或者调整一下参数,配置的方法是 M-x customize-group RET net-utils RET

命令描述
ifconfig 和 ipconfig运行 ifconfig 或者 ipconfig
iwconfig运行 iwconfig 工具
netstat运行 netstat 工具
arp运行 arp 工具
route运行 route 工具
traceroute运行 traceroute 工具
ping运行 ping,但是在多数系统中,这个命令会无限制的执行下去; 可以去配置一下 ping-program-options
nslookup-host以非交互模式运行 nslookup 。
nslookup以交互模式运行 nslookup 。
dns-lookup-host用 host 命令查询 IP 或者主机名的 DNS 信息。
run-dig and dig以交互模式运行 dig 。
ftp对 ftp 命令行工具的非常简单的包装。
smbclient andsmbclient-list-shares运行 smbclient 或者列出主机的所有共享。
finger运行 finger 工具
whois and whois-reverse-lookup运行 whois 工具,但是会去尝试猜测正确的 WHOIS 服务器,你可以去调整一下 whois-server-tldwhois-server-list 或者把 whois-guess-server 设置为 nil


原文:http://www.masteringemacs.org/articles/2011/03/02/network-utilities-emacs/

November 21, 2010

最近发现把 MBP 的屏幕合上以后需要至少 30 秒才可以进入待机状态,以前就记得速度很快。Google 了一下,发现遇到类似问题的人也不少,基本上可以用以下几种办法来解决:
  • 打开 http://127.0.0.1:631/jobs/ 看看是不是有没完成或挂起的打印任务,清空。
  • 拔除外部设备,比如移动硬盘、闪存盘之类的。
  • 运行  Activity Monitor,看看是不是有程序耗费了比较多的资源,退出大程序。
  • 关闭 Safari 或其他Web浏览器
  • 退出正在观看的视频或正在播放音乐的 iTunes
我的情况就是第一种,有个没有完成的打印任务,删除之后待机速度就正常了。

July 29, 2010

本文是 http://www.omgubuntu.co.uk/2010/01/how-to-install-adobe-air-ubuntu-64bit.html 的简单翻译。

前面不用多说,因为 Adobe 只提供了 32bit 版本的 Air,在 64bit 的 Ubuntu 上是不能直接安装的。

第一步:下载
前往 http://get.adobe.com/air/ 下载 Adobe Air,在今天(2010年7月29日)的最新版本是 2.0.2。我们要下载 .bin 格式的安装程序,下载完毕之后记住修改一下文件的可执行属性。
命令:
wget http://airdownload.adobe.com/air/lin/download/latest/AdobeAIRInstaller.bin
chmod +x AdobeAIRInstaller.bin


第二步:获取并安装 Adobe Air 的依赖文件,首先是要安装一个名叫 "Getlibs" 的程序包,这个就是用来帮助我们获得在 64 位环境下运行 32 位程序所需要的 lib 文件。

下载地址: http://frozenfox.freehostia.com/cappy/getlibs-all.deb

命令:
wget http://frozenfox.freehostia.com/cappy/getlibs-all.deb
sudo dpkg -i getlibs-all.deb


然后运行下列的命令,安装 Air 所依赖的 lib 文件

yes | sudo getlibs -l libnss3.so.1d
yes | sudo getlibs -l libnssutil3.so.1d
yes | sudo getlibs -l libsmime3.so.1d
yes | sudo getlibs -l libssl3.so.1d
yes | sudo getlibs -l libnspr4.so.0d
yes | sudo getlibs -l libplc4.so.0d
yes | sudo getlibs -l libplds4.so.0d
yes | sudo getlibs -l libgnome-keyring.so
yes | sudo getlibs -l libgnome-keyring.so.0
yes | sudo getlibs -l libgnome-keyring.so.0.1.1

第三步:安装
运行命令后会出现安装界面,然后点击再点击完成安装

sudo ./AdobeAIRInstaller.bin


Enhanced by Zemanta

July 28, 2010

今天才第一次注意到这个不算新的许可证,官方地址:http://sam.zoy.org/wtfpl/。首次发布已经是2004年了,甚至现在已经到了第二版。不过好像没有引起更多人的注意,或许这个许可证看上去不那么正式,更像是个愚人节笑话。

不过还是有一些开源的项目采用了这个许可证 http://freshmeat.net/tags/wtfpl,而且不仅仅可以用于计算机代码,还可以用于其他领域,比如艺术创作、文章等等。

许可证的全文内容也非常的短,正文也就一句话,我就把全文都列在这里:

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004

Copyright (C) 2004 Sam Hocevar <[email protected]>

Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. You just DO WHAT THE FUCK YOU WANT TO.

哦哦,你没有看错,就这么多。

FAQ 比正文内容多的多了,我列出最后三条:
Q: 顺便问一下,用这个 WTFPL,我还可以......
A: 哦,没问题,当然你可以

Q: 但是我能......
A: 是的,你能

Q: 能......
A: 能!
(本文以 WTFPL 许可发布,你他妈的想干什么都可以,许可证全文可以从 http://sam.zoy.org/wtfpl/COPYING 下载获得)

July 25, 2010

刚才运行 emacs 时发现终端上显示了错误:
<pre>
** (emacs:6396): CRITICAL **: murrine_style_draw_box: assertion `height >= -1' failed
</pre>
以前也没见过这个提示,今天第一次出现,google了一下,在http://thehacklist.blogspot.com/发现了解决办法,非常简单:
编辑 /usr/share/themes/Ambiance/gtk-2.0/gtkrc 这个文件
把 GtkRange::trough-under-steppers = 0 修改为 GtkRange::trough-under-steppers = 1
然后就好了。

July 21, 2010

不知道有没有人遇到过,现象就是用鼠标左键点浏览器中的flash没有任何效果,但是用右键会出来菜单。如果要点某个按钮,还得用 tab 键移动焦点然后按下回车。
问题简单,解决办法也简单:
编辑文件 /usr/lib/nspluginwrapper/i386/linux/npviewer
在第二行加上下面的语句
export GDK_NATIVE_WINDOWS=1
保存,然后重启 Firefox 就 OK 了。

December 18, 2009

今天安装 bootchart 的时候,发现 update-initramfs 把我自安装 Ubuntu 以来的所有内核 initramfs 文件都生成了一遍,足有十几个,可怜的 /boot 才 100M,瞬间就一点没有了。

虽然每次更新内核,我都会手工把旧内核删除,但旧内核在系统中还是有记录的。

除了删除 /boot 下的相关文件之外,还要用如下命令删除内核对应的 initramfs:

sudo update-initramfs -k 2.6.28-16-generic -d -v
参数 k 指定了内核的版本,参数 d 是要删除,参数 v 是啰嗦。

删除完毕之后,重新 sudo dpkg-reconfigure bootchart 就搞定了。

June 16, 2009

奇怪的是我用 keychain (http://www.gentoo.org/proj/en/keychain/) 一直都有问题,直接运行 keychain ~/.ssh/id_rsa 就不会提示密钥口令,只有一次提示了,还不知道是怎么弄的 :-S 。

如果登录主机时启用 ForwardAgent 的话,不需要用 keychain 直接就可以免输入口令登录其他设置了自己公钥的主机。

如果没有启用 ForwardAgent,或者运行在 screen 之内时,必须在每一个 shell 里面用下面的命令才可以免输入口令,只要当前的 shell 没有退出,一直就可以用


keychain \
&& source $HOME/.keychain/$(hostname -s)-sh \
&& ssh-add

October 4, 2008

Step 1: Download EnvyNG
sudo aptitude install envyng-core envyng-gtk

Step 2: Use EnvyNG, from Applications -> System Tools -> EnvyNG, then download appropriate drivers, this may take a while. restart gdm once installed.

Step 3: from System -> Administration -> NVIDIA X Server Settings
Enable TwinView, and click "Save the X Configuration File" , and click save.
Reboot

done!

August 19, 2008

在一台机器上运行多个 Tomcat 的时候,需要修改 server.xml 中的好几个端口。
vim $CATALINA_HOME/conf/server.xml

在 VIM 中用下面的替换可以迅速的给每个端口加1,也就是把 8080 变成了 8081,等等

:%s/\([pP]ort\)="\([0-9]\+\)"/\=printf("%s=\"%d\"",submatch(1),submatch(2)+1)/g

或者用下面的替换可以迅速的给每个端口前增加一个数字,下面的例子是增加 4,也就是把 8080 变成了 48080,等等

:%s/\([pP]ort\)="\([0-9]\+\)"/\1="4\2"/g

January 3, 2008

默认情况下 Apache Solr 是不支持中文检索的,如果文档中包含中文,必须用完整的一句中文才能检索出内容。
下面以 Apache Solr 的演示程序为例,注意:粗体部分是需要修改的地方。
找到如下三行:
     <fieldType name="text" class="solr.TextField" positionIncrementGap="100">
       <analyzer type="index">
         <tokenizer class="solr.WhitespaceTokenizerFactory"/>
修改为:
     <fieldType name="text" class="solr.TextField">
       <analyzer type="index" class="org.apache.lucene.analysis.cjk.CJKAnalyzer">
         <tokenizer class="org.apache.lucene.analysis.cjk.CJKTokenizer"/>
找到如下两行:
       <analyzer type="query">
         <tokenizer class="solr.WhitespaceTokenizerFactory"/>
修改为:
       <analyzer type="query" class="org.apache.lucene.analysis.cjk.CJKAnalyzer">
         <tokenizer class="org.apache.lucene.analysis.cjk.CJKTokenizer"/>
修改完毕,重新运行 Apache Solr 就可以对中文进行检索了,原先已经导入的文档需要重新导入。
记住原先的配置中有个 positionIncrementGap="100" 一定要删除了,否则会有异常。

April 13, 2007

%(百分号)在 crontab 中是一个特殊字符,相当于回车,如果命令中包含 %,那么 % 之后的内容将作为标准输入赋值给前面的命令。

如果命令行中需要 %,那就得在 % 前面加一个反斜线“\”来转义,就变成了“\%”, 当然了,如果要用反斜线的话,那就是“\\”这样子啦。

不过,我要在计划任务中添加一个任务,是要每天分析前一天的 apache 日志。日志的文件名,是用命令行参数来指定的。昨天的日志文件名就写成这样子

$(date --date 'yesterday' '/%Y-%m/access_log_%Y_%m_%d.log')

比如今天是2007年4月13日,那这条命令的结果就是:

/2007-04/access_log_2007_04_12.log

因为我这是在命令行中指定日志文件的,所以在添加到 crontab 中以后,需要在 % 之前添加反斜线。但是却出现了意外,因为 crontab 把上面的那个命令结果变成了

/\2007-\04/access_log_\2007_\04_\12.log

反斜线竟然还在!

服了他了,我只好把命令写到一个文件里,然后在 crontab 里面调用那个文件了。

April 12, 2007

用过 Linux 都知道,添加 DNS 服务器是在 /etc/resolv.conf 文件中,格式类似如下的样子:

nameserver 208.67.222.222
nameserver 208.67.220.220

BTW:这个两个 DNS 服务器是 OpenDNS (website: http://www.opendns.com)的,建议大家使用。

平时,我们只要添加了DNS服务器就可以正常解析域名了。但是 Solaris 中却不是这样,也不知道是安装时的问题还是本来就是这样,正常添加了DNS服务器,却还是不能解析域名,除非在 /etc/hosts 中添加了要解析的域名。

原因呢,就是在 /etc/nsswitch.conf 这个文件中,有那么两行:

hosts: files

...
networks: files

指明了解析域名时,用的是文件,而不用 DNS,所以只需要在这两行后面分别再添加一个 dns,变成如下这样就行了

hosts: files dns
...
networks: files dns

在 Solaris 5.8 中添加了 DNS 后,却不能解析 www.sunfreeware.com 之后的记录

April 9, 2007

一般来说,只要是从 Freeware for solaris 上下载的软件,只要用gunzip解压后,再用 pkgadd -d <filename> 就可以安装成功。

比如我们要安装 wget,下载地址是 ftp://ftp.sunfreeware.com/pub/freeware/sparc/8/wget-1.10.2-sol8-sparc-local.gz ,下载到本地后,用

gunzip wget-1.10.2-sol8-sparc-local.gz

解压得到文件 wget-1.10.2-sol8-sparc-local,然后用命令

pkgadd -d wget-1.10.2-sol8-sparc-local

即可安装成功。不过有的软件包可不是这么简单了,每次运行pkgadd -d <filename> 提示总是

pkgadd: ERROR: no packages were found in </var/tmp/aEzreACb41kZYZ>

类似这样的提示,用 cksum 检查文件,也都没有任何问题。用pkginfo -d <filename> 也会得到类似的错误。

说真的,这个问题困扰了我一天。直到我在 http://au.sunsolve.sun.com/pub-cgi/show.pl?target=patchpage 这里,用 pkgadd 作为关键字搜索后,才恍然大悟,原来这是 pkgadd 的bug。解决这个问题需要安装两个补丁,分别是

http://au.sunsolve.sun.com/search/document.do?assetkey=1-21-110380-04-1

http://au.sunsolve.sun.com/search/document.do?assetkey=1-21-110934-26-1

记住,先安装第一个,然后再第二个。

在安装 openssh-4.6p1-sol8-sparc-local 失败后的一次记录

February 27, 2007

方法很简单,只需要增加环境变量 LESS=-isMrf

vim /etc/profile

在最后一行添加如下内容

export LESS=-isMrf

然后重新登录即可

February 9, 2007

我一般都是在Linux的机器上使用Apache,也没发现这个问题。今天在Windows上装了一个Apache 2,结果运行起来就发现 CPU 的资源很快就上升到100%,打开浏览器访问 http://localhost/ 也没有响应。查看了一下 Apache 的运行日志,发现错误日志不停的增加,内容大致就是:


[Fri Feb 09 09:34:10 2007] [error] (OS 10038)An operation was attempted on something that is not a socket. : Child 1764: Encountered too many errors accepting client connections. Possible causes: dynamic address renewal, or incompatible VPN or firewall software. Try using the Win32DisableAcceptEx directive.


就是这个错误,不停的出现。
看日志上提示说尝试使用 Win32DisableAcceptEx 指令,当然要照着办了,打开 conf/httpd.conf,在最后一行添加了这条指令,就光秃秃的写了一个

Win32DisableAcceptEx

什么参数也不需要,就这样重新运行 Apache ,出现了这样一个提示:[Fri Feb 09 09:34:31 2007] [notice] Disabled use of AcceptEx() WinSock2 API。啊哈,正常了。
上 Google 找了一下,发现这个问题的原因原来是 Apache 的新版本中对 Winsock2 的支持有问题,原因不明,只是在部分的Windows上会有这样的问题,已经很长时间了 ^_^。

December 11, 2006

看来 JDK 6 在 Sun 的心目中还是非常重要的,一发布者就连 JDK1.4和JDK5的链接都没了。
http://java.sun.com/
看看 JDK 6 有哪些新特性了:
首先不得不提的是脚本语言的支持,新增了 javax.script 包,看看 https://scripting.dev.java.net/ 这里
还有就是 gif 的版权过期了。
对了,编译器也从 com.sun.tools.javac 变成了 javax.tools.JavaCompile ,这下我们能够实时生成 Java 源代码,然后实时编译,有点动态语言的感觉了。
……

November 10, 2006

用 grep 匹配文件时,显示结果黑压压的一片

执行一下这条命令,重新 grep 试试看
export GREP_OPTIONS='--color=auto'
好看多了,不是吗?

你可以把 export GREP_OPTIONS='--color=auto' 这条命令添加到 ~/.bash_profile 的最后,重新登录一下就能生效了。

October 26, 2006

摘自: Fifteen Exercises for Learning a new Programming Language

1、无穷循环显示数字数列(1、2、3、4、5、6、……、等等),按指定键退出程序(比如 Esc 键)
2、斐波纳契数列,交换两个变量,在一个数字列表中查找最大/最小的数字
3、键盘输入一些数字,然后递增/递减排序输出
4、用公式 (D*V*rho)/mu 来计算雷诺数,其中 D=直径、V=加速度、rho=密度、mu=粘稠度。输入给程序一些数据(先不要管单位转换)
如果结果小于2100,就显示 Laminar flow
如果结果介于 2100 和 4000 之间,就显示 Transient flow
如果大于4000就显示 Turbulent Flow
(if..else..then 条件判断)
5、修改前面的程序,最后增加一个提示“是不是再来一次?(y/n)”,如果回答 y,程序就重新要求输入这些参数。如果是“n”就退出程序
(do while 循环)
在程序运行时,给 mu 变量赋值为 0,看看会发生什么,是不是出现了“DIVID BY ZERO”错误?或者是不是出现了”Segmentation fault..coredump"?怎样处理这种情形?程序有没有内建了什么处理机制么?(异常处理)
6、科学计算,要求支持加、减、乘、除、开方、平方、立方、sin、cos、tan、阶乘、取反、取模
7、用不同的格式打印输出,四舍五入保留4位小数,左右补0对齐(输入/输出操作)
8、打开一个文本文件,转换成 HTML 文件(文件操作/字符串处理)
9、时间和日期:获取操作系统时间,再转换成不同的格式输出,比如: 'DD-MON-YYYY', 'mm-dd-yyyy', 'dd/mm/yy' 等等
10、建立一个文件,把文件的创建日期和时间戳附在文件名后面
11、输入一个 HTML 表格,删除所有的标签,把数据用逗号/制表符分割保存到文件中
12、找出文件中的所有大写单词,去除重复的
13、实现自动换行功能(注意观察在 Windows 的记事本中的自动换行是怎样工作的)
14、在数组的开头、中间和结尾添加/删除数据
15、正在学习的这个程序设计语言是不是还有一些其他特性:操作符重载,虚函数、引用、指针等等。这个语言是不是还支持一些叫做“namespace/package/module”的东西?多看看

October 19, 2006

6、7年前高中刚毕业时写过一个,原先写的早就找不到,不过算法还是记得很清楚,凭印象又写出来了。

源文件 http://blog.chaifeng.com/upload/full_array.c.utf-8.html

C 源文件 http://blog.chaifeng.com/upload/full_array.c

源代码用 Vim 编辑
语法高亮文件用 Vim 生成,大家可以参考一下
:TOhtml

执行效率测试:

OS : RedHat AS3 update 6

CPU : P3 1G

内存: 512M

GCC : gcc (GCC) 3.2.3 20030502

编译时没加优化 : gcc -o full_array full_array.c



全排列 10 个元素,耗时约 1.72 秒

time ./full_array "0192837465" > /dev/null



real 0m1.718s

user 0m1.720s

sys 0m0.000s



全排列 11 个元素,耗时约 18.9 秒

time ./full_array "0192837465a" > /dev/null



real 0m18.949s

user 0m18.920s

sys 0m0.020s



全排列 12 个元素,耗时约 3分55 秒

time ./full_array "0192837465ab" > /dev/null



real 3m55.335s

user 3m51.020s

sys 0m0.240s



基本上比用递归快一个数量级



如果有问题,欢迎一起讨论

August 29, 2006

System.getProperty("line.separator");

August 28, 2006

这两天测试的时候,一个机器上同时运行了3、4个Tomcat,只好修改 $CATALINA_HOME/conf/server.xml 里的端口。
在 VIM 中用以下替换命令
:%s/\([pP]ort\)="\(\d\{4\}\)"/\1="3\2"/gc
全局替换端口数字长度为4的,在前面加上3。
最后面的 gc 是全局替换并且确认,去掉c就不用每次确认替换了。

July 10, 2006

发信人: cathayan (连接被重置), 信区: VIM
标 题: Re: 怎样导出语法加亮的代码
发信站: 水木社区 (Fri Jul 7 09:46:48 2006), 站内

:let html_use_css = 1
:let html_no_pre=1
:let use_xhtml = 1
html_use_encoding

June 15, 2006

进行远程调试简单来说:只需要在java 命令后面添加上如下的参数:
-Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=y
例如:原先是这样启动程序的
java -cp . HelloWorld,
现在就改成这样了
java -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=y -cp . HelloWorld
然后一运行就会出现如下的文字:
Listening for transport dt_socket at address: 8000
这就OK了。打开 Eclipse, 在调试里面新增一个 Remote Java Application,Host 填写上启动 Java 程序的那台服务器的地址,Port填写 8000,也就是参数中 address 后面指定的数字。剩下就跟平常一样了,断点该设就设,程序动态运行时也可以修改,不用重新拷贝,立刻生效,跟本地运行一样。当然了并不是所有的修改都可以立即生效的,有时还是需要我们把程序重新拷贝一下。
上面各个参数的含义分别是:transport=dt_socket指明了使用网络来传输,所有的平台都支持,server=y指明了启动VM的以调试服务器来执行,address=8000就是端口了,也能指定服务器IP,suspend=y则指定了VM开始的时候暂停,等待与客户端连接,连接上以后才继续执行。

更详细的内容看BEA上的《充分利用 J2EE 调试工具》一文



May 17, 2006

发现应用不能用了,反复测试发现页面中不能包含 taglib,否则会出现以下提示:

HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

org.apache.jasper.JasperException: /index.jsp(1,1) Unable to read TLD "META-INF/tlds/struts-bean.tld" from JAR file "file:/C:/home/chaifeng/eclipse_workspace/cnlife365_tracker/web/WEB-INF/lib/struts.jar": org.apache.jasper.JasperException: Failed to load or instantiate TagExtraInfo class: org.apache.struts.taglib.bean.CookieTei
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:510)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:375)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118)
com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:75)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)

root cause

org.apache.jasper.JasperException: /index.jsp(1,1) Unable to read TLD "META-INF/tlds/struts-bean.tld" from JAR file "file:/C:/home/chaifeng/eclipse_workspace/cnlife365_tracker/web/WEB-INF/lib/struts.jar": org.apache.jasper.JasperException: Failed to load or instantiate TagExtraInfo class: org.apache.struts.taglib.bean.CookieTei
org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:39)
org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:405)
org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:86)
org.apache.jasper.compiler.Parser.processIncludeDirective(Parser.java:339)
org.apache.jasper.compiler.Parser.parseIncludeDirective(Parser.java:372)
org.apache.jasper.compiler.Parser.parseDirective(Parser.java:484)
org.apache.jasper.compiler.Parser.parseElements(Parser.java:1552)
org.apache.jasper.compiler.Parser.parse(Parser.java:126)
org.apache.jasper.compiler.ParserController.doParse(ParserController.java:211)
org.apache.jasper.compiler.ParserController.parse(ParserController.java:100)
org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:155)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:295)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:276)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:264)
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:563)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:303)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118)
com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:75)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)

note The full stack trace of the root cause is available in the Apache Tomcat/5.5.17 logs.
Apache Tomcat/5.5.17

想了半天,刚才没有改动代码。折腾了半天才想起来,只是更新了一下lib下的jar,一时图方便就把另外一个目录下的jar全都复制过来了,包括 jsp-api.jar。
把它删除就ok了,记录一下。

February 11, 2006

Google Talk 升级了能在Gmail里面聊天了, 都说这个服务只有在英文界面下才能看到,可是我的Gmail一直就是英文的,怎么从来没见到过能聊天的那个界面,还差点以为自己人品有问题。
刚才发现原来这个服务还必须得在 http://mail.google.com 里才能看到,如果你也象我一样用 https://mail.google.com 来使用 Gmail,也是看不到这个选项的,只能设置是否把聊天记录保存到 Gmail 中。


Technorati Tags: , ,

January 20, 2006

我在 LiveJournal 也注册了账户, 其实就是冲着他的 openid。原先在 LiveJournal 的免费用户的访问地址是类似这样子的:http://www.livejournal.com/users/******/ ,现在继续访问这个链接就会自动跳转到 http://******.livejournal.com/ 这个二级域名上。

嗯,要是 MSN Spaces 也能提供二级域名就好了。

January 19, 2006

1、打开 HyperSnap,打开“捕捉设置”选项对话框。
2、在“捕捉”标签页,取消“在捕捉图像后播放声音”和“捕捉后恢复HyperSnap窗口,并将其显示到最前面”两个复选框。
3、在“快速保存”标签页,选中“自动将每次捕捉的图像保存到文件中”和“文件名依次增序”;选择好“自动保存的路径”,找一个剩余空间比较大的分区,免得还没保存多长时间就没空间了;设置好“终止值”,最好设置大一些,比如“9999999”;然后在下面的“重复第一次捕捉,间隔时间”那里输入你期望的间隔时间(单位是秒),比如“30”
4、在“任务栏”属性对话框的“任务栏”标签页下有个隐藏不活动的图标,点击“自定义”按钮,找到 HyperSnap 的图标,修改为“总是隐藏”;以前见过什么软件可以隐藏其他软件在任务栏的现实,用那个也不错的。
5、最后用 HyperSnap 抓一个全屏,剩下的就是过段时间来看看记录了,看看别人在电脑上干了些什么。

优点:这还用说?杀毒软件根本发现不了。哈哈,HyperSnap 怎么会是病毒、木马或者间谍软件?
缺点:容易被人发现,不过大多数情况下都会被忽略掉的,哈哈。


最后来说说这份 HowTo 的起因:

前几天有台 Web 服务器的 WebLogic 总是出问题,昨天上午发现两次异常增大的流量,所以干脆不停的察看 WebLogic 的流量状态。到了中午吃饭时,担心误过一些异常的流量,于是打开了 HyperSnap,然后设置了每隔 1 分钟就保存当前屏幕。然后就放心的出去吃饭了,1个多小时后回来后看了看截图发现都挺正常。不过我忘记再把 HyperSnap 定时截图给取消了,结果 HyperSnap 老老实实的给我截了一个下午的图,就这样完完整整地记录了我一下午的活动,包括跟MM聊天,玩游戏,上网找好玩的东西。呵呵,当然了,基本上还是都在工作的。

被记录了

January 8, 2006

好多人都有这样的困惑,系统越用越慢,打开任务管理器一看发现一大堆的进程,有的占用资源还挺高,内存也被耗掉不少。有的看上去那么面生,担心会不会是木马程序或病毒。不知道是不是正常的进程,不知道该不该杀掉,有的还是系统的正常进程,只不过所提供的服务我们平时用不着,每次开机都自动运行白白耗费资源。

ProcessLibrary (http://www.processlibrary.com/) 就是这样一个进程库的大全,在这里能搜索到绝大部分的进程信息。比如我看到这么一个进程 wdfmgr.exe,不知道是个什么进程,每次都能看见,好像刚装完系统是没有的。一搜索wdfmgr.exe才知道,wdfmgr.exe 是 Microsoft Windows media player 10 及其以上版本的一部分。刚装完XP,系统里面是 Windows media player 9,难怪没有。下面还有一些其他信息:比如系统危害程度是0,不是间谍软件、广告软件、病毒或木马程序。

嗯,又看见一个 gmt.exe,一看搜索结果原来是个间谍软件,赶快删掉吧。

在 ProcessLibrary 首页上还能看到危害最高的5个进程:


1. lsas.exe
Security Risk

2. msbb.exe
Security Risk

3. scvhost.exe
Security Risk

4. gmt.exe
Security Risk

5. rundll.exe
Security Risk

你还可以把这些添加你的网站上提醒大家。不过我们平时用电脑还是以预防为主,什么杀毒软件、防火墙都尽早装上。要是厌烦了这些,就用 Linux吧,个人推荐 Ubuntu,还能免费获得正版光盘,平时上网、聊天、写文档、写程序、看电影、听音乐、玩些休闲游戏绰绰有余了,还不用担心病毒、木马的,也不会越用越慢是不是就去重装系统。毕竟电脑是为我们服务的,而不是要我们去伺候它的,你说呢?

January 7, 2006

发信人: thinelephant (光吃不长), 信区: VIM
标  题: VIM 测试题(给用 VIM 做数据处理的初学者)
发信站: 水木社区 (Thu Oct 27 20:21:50 2005), 站内

以前写的,主要是针对数据处理的,虽然写得不好,不过也发到版上留个备份啦。:-)

VIM 测试题(给用 VIM 做数据处理的初学者)

请回答以下操作所需的步骤或命令:

01. (4) 光标移到最后一行
02. (4) 设置跳格(Tab)宽度为 4
03. (4) 忽略大小写查找字符串 elephant(本题不得使用 GUI)
04. (4) 将所有 elephant 替换为 pig(本题不得使用 GUI)
05. (4) 打开 VIM 关于正则表达式的帮助文档
06. (4) 在阅读 VIM 帮助时遇到链接如何跳转?如何返回?

07. (6) 比较编辑两个内容相近的文件
08. (6) 借助外部命令 sort 将文件的行按字母顺序进行排序
09. (6) 将每一行的第一个字符与第二个字符交换
10. (6) 将当前目录中所有文件的文件名插入到当前文本中

假设文件 data.txt 内容如下:

ACDSee             000001   499.95  ACD Systems, Ltd.
Internet Explorer  000004  1999.50  Microsoft Corp.
Vi IMproved        000015     0.00  Bram Moolenaar
FlashFXP           000204   199.00  CEDsoft

请回答以下操作所需的正则表达式(可查阅帮助,反复尝试):

11. (4) 匹配每行的软件名字段
12. (4) 匹配每行的编号字段
13. (4) 匹配每行的价格字段
14. (4) 匹配每行的开发者字段

请回答以下操作所需的步骤或命令:

15. (6) 交换每行的编号和价格字段
16. (8) 借助外部命令 sort 将文件的行按软件价格进行排序
17. (8) 将连续两个或以上的空格替换为一个跳格字符
18. (6) 删除每行的开发者字段

送分题,写得越多越好:

19. (8) 请写出任何难以用 notepad 完成的并且你会的 VIM 功能。

============================================================================

参考答案

01. G
    在 Normal 模式下按 G 快速跳到最后一行,按 gg 跳到第一行,当然,也可以按
    Ctrl-Home 和 Ctrl-End。
02. :set tabstop=4
    将 Tab 设成大一点的宽度,比如 16,查看数据文件的时候比较有用,对齐清晰。
03. 方法一,先设置忽略大小写,然后查找
    :set ignorecase
    /elephant
    :set noignorecase
    方法二,在前面加入 \c 表示忽略大小写
    /\celephant
04. :%s/elephant/pig/g
    g 表示如果一行有多个 elephant 将全部替换,没有 g 表示只替换每行第一个。
    另外还有 i 标志,有 i 表示忽略大小写。i g 这两个标志非常基础!
05. :help pattern
    用 :help xxx 看一个东西帮助,提示:在 :help 后面可以尝试按 tab 补全,
    比如输入 :help search 然后按 tab(一次或多次),你就可以看到
    search-pattern 正是你想要看的。
06. Ctrl-] Ctrl-T
    帮助里面用两个 | 括起来高亮的,比如 |pattern| 都是可以跳转的链接,按
    Ctrl-](按住 Ctrl 按右中括号)跳进去,再按 Ctrl-T 跳回来。

07. 在命令行下 vim -d file1.txt file2.txt 可以用比较模式查看编辑两个文件,
    或者如果在 Windows 下面,可以先选中两个文件,然后鼠标右点菜单,选
    “Diff with Vim”。一般在比较某个文件的两个版本(即是一个是以前的,
    一个是修改后的)时很有用。
08. :%!sort
    表示将整个文件的行用外部命令 sort 过滤一遍,不过要当心 Windows 的 sort
    命令在某些条件下会产生错误的排序结果。
09. 方法一,用正则表达式匹配替换每行的前两个字符
    :%s/^\(.\)\(.\)/\2\1/
    方法二,用块选择
    Normal 模式下,先把光标移到第一行第一个字符上,按 Ctrl-V 进入块选择模式,
    移动光标到最后一行第一个字符上,这时选中的是每一行的第一列字符,按 d
    删除,然后移动光标到第一行第二个字符,按 P(注意是大写)粘贴,刚才删除的
    第一列就被粘到第二列上了。
10. :split .
    打开当前目录(. 表示当前目录,当然也可以是比如 C:\ ),然后就可以将目录
    中的文件名复制粘贴过来了。

请把 :help pattern 那一页帮助内容仔仔细细阅读 99 遍!:-)

11. 软件名字段的特征是:位于行首;由若干个单词组成,单词之间用一个空格分开。
    ^\S\+\( \S\+\)*
12. 编号字段的特征是:恰好六个数字。
    \<\d\{6}\>
13. 价格字段的特征是:若干个数字,一个点,若干个数字。
    \d\+\.\d\+
14. 开发者字段的特征跟软件名字段的特征类似,但是位于行末。
    \S\+\( \S\+\)*$

15. 同 09 题方法二,用块选择。
16. 用块选择将价格字段换到前面,然后用 :%!sort 排序,然后换回来。
17. :%s/  \+/\t/g (注意这里是两个空格)或者
    :%s/ \{2,}/\t/g
18. 用块选择,按 D(大写)删除。块选择后按 d 跟 D 的区别是:d 删除选中的块,
    D 删除选中的块以及后面一直到行末的内容。

19. 略。

January 4, 2006

JavaScript 的 base64 编码/解码的源代码
摘自:www.aardwulf.com
作者:aardwulf systems


var keyStr = "ABCDEFGHIJKLMNOP" +
"QRSTUVWXYZabcdef" +
"ghijklmnopqrstuv" +
"wxyz0123456789+/" +
"=";

function encode64(input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;

do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);

enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;

if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}

output = output +
keyStr.charAt(enc1) +
keyStr.charAt(enc2) +
keyStr.charAt(enc3) +
keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);

return output;
}

function decode64(input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;

// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
var base64test = /[^A-Za-z0-9\+\/\=]/g;
if (base64test.exec(input)) {
alert("There were invalid base64 characters in the input text.\n" +
"Valid base64 characters are A-Z, a-z, 0-9, '+', '/', and '='\n" +
"Expect errors in decoding.");
}
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

do {
enc1 = keyStr.indexOf(input.charAt(i++));
enc2 = keyStr.indexOf(input.charAt(i++));
enc3 = keyStr.indexOf(input.charAt(i++));
enc4 = keyStr.indexOf(input.charAt(i++));

chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;

output = output + String.fromCharCode(chr1);

if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}

chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";

} while (i < input.length);

return output;
}

December 28, 2005

虽然挺老的文章,虽然挺小的错误

当年,国际巨星成龙的「龙种」曝光,众人指责他对不起娇妻林凤娇,逼得他出面召开记者会,向世人自白他犯了「全世界所有男人都会犯的错误」。从来没犯过这种错误的我,也因此常常认为自己不是个男人。

虽然没犯过「全世界所有男人都会犯的错误」,但是我倒是曾经犯了「全世界所有程序员都会犯的错误」。不管使用何种语言,全世界所有程序员都一定犯过这种错误,那就是:太依赖编译器,却不知道编译器做了哪些事。

一般来说,越高阶的程序语言,会提供越多语法上的便利,以方便程序撰写,这就俗称为syntactic sugar,我称其为「语法上的甜头」。虽说是甜头,但是如果你未能了解该语法的实质内涵,很可能会未尝甜头,却吃尽苦头。

不久前,我收到一个电子邮件,读者列出下面的Java程序,向我求救。看过这个程序之后,我确定这又是一个「全世界所有程序员都会犯的错误」。

// 程序1
class Singleton {
private static Singleton obj = new Singleton();
public static int counter1;
public static int counter2 = 0;
private Singleton() {
counter1++;
counter2++;
}
public static Singleton getInstance() {
return obj;
}
}

// 程序2
public class MyMain {
public static void main(String[] args) {
Singleton obj = Singleton.getInstance();
System.out.println("obj.counter1=="+obj.counter1);
System.out.println("obj.counter2=="+obj.counter2);
}
}

执行结果是:
obj.counter1==1
obj.counter2==0

你有没有被此结果吓一跳?乍看程序代码,你很可能会认为counter1和counter2的值一定会相等,但执行结果显然不是如此。其实,程序1被编译后的程序应该等同于下面的程序3:

// 程序3
class Singleton {
private static Singleton obj;
public static int counter1;
public static int counter2;
static { // 这就是class constructor
// 在进入此class constructor之前,class已经被JVM
// 配置好内存,所有的static field都会被先设定为0,
// 所以此时counter1和counter2都已经是0,且singleton为null
obj = new Singleton(); // 问题皆由此行程序产生
// counter1不会在此被设定为0
counter2 = 0; // counter2再被设定一次0(其实是多此一举)
}
private Singleton() { // 这是instance constructor
counter1++;
counter2++;
}
public static Singleton getInstance() {
return obj;
}
}


是因为:当class具有static field,且直接在宣告处透过「=...」的方式设定其值时,编译器会自动将这些叙述依序搬到
class constructor内。同样地,当class具有instance field,且直接在宣告处透过「=...」的
方式设定其值时,编译器会自动将这些叙述依序搬到instance constructor内。

此程序在
class constructor内,还未将static field初始化时(这时候,counter1和counter2都是
0),就呼叫instance constructor,而instance constructor竟然还会去更动
static field的值,使得counter1和counter2都变成1。然后instance constructor执
行完,回到class constructor,再把counter2的值设为0(但是
counter1维持不变)。最后的结果:counter1等于1,counter2等于0。

欲改正程序1,方法有三:

-方法一:将singleton field的宣告调到counter1与counter2 field之后。
这是最好的作法。
-方法二:将counter2=0的宣告中,「=0」的部分删除。这种作法只有在希望
-方法三:将初始化的动作搬到class constructors内,自行撰写,而不依赖
编译器产生。这是最保险的作法。

如何避免犯下「全世界所有程序员都会犯的错误」,我给各位Java程序员
的建议是:
-熟读Java Language Specification
-在有疑问时,使用J2SDK所提供的javap来反组译Java Bytecode,直接观察
编译后的结果。

下面是我用javap来反组译程序1的示范:

C:\>javap -c -classpath . Singleton

Compiled from MyMain.java
class Singleton extends java.lang.Object {
public static int counter1;
public static int counter2;
public static Singleton getInstance();
static {};
}

Method Singleton()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 getstatic #2 <Field int counter1>
7 iconst_1
8 iadd
9 putstatic #2 <Field int counter1>
12 getstatic #3 <Field int counter2>
15 iconst_1
16 iadd
17 putstatic #3 <Field int counter2>
20 return

Method Singleton getInstance()
0 getstatic #4 <Field Singleton obj>
3 areturn

Method static {}
0 new #5 <Class Singleton>
3 dup
4 invokespecial #6 <Method Singleton()>
7 putstatic #4 <Field Singleton obj>
10 iconst_0
11 putstatic #3 <Field int counter2>
14 return

其实Java的syntactic sugar并不算多,C#的syntactic sugar才真的是无所不在,
也因此C#的初学者更容易犯了「全世界所有程序员都会犯的错误」。许多C#的书都会一边介绍C#语法,一边介绍编译之后MSIL(.NET的中间语言,类似Java的Bytecode)的结果,然而Java的书却鲜少这么做。

虽说是「全世界所有程序员都会犯的错误」,但是这不代表你犯了此错误之后,仍可以同爱借钱的曹启泰一般地「抬头挺胸、理直气壮」。只要有心,其实这一类的错误仍是可以避免的。


本文作者:蔡学镛
文章出处:Sleepless 2.0
发表日期:03/10/2003