配置 squid_ldap_group

以前我们已经采用 LDAP 来对使用 squid 代理服务的用户进行认证,但由于 LDAP 服务器中有很多的用户,而我们只想允许一小部分人使用代理服务器,于是就需要让 squid 去验证某个用户是否属于特定的用户组。Ubuntu/Debian 的 squid 服务器软件包中已经带有相关的程序,只需要配置即可。


auth_param basic children 5
auth_param basic realm Private Proxy
auth_param basic program /usr/lib/squid/ldap_auth -h ldap.server -b "ou=People,o=bit,c=cn" -u cn -v 3
external_acl_type ldapgroup %LOGIN /usr/lib/squid/squid_ldap_group -b "o=bit,c=cn" \
-f "(&(objectclass=groupOfUniqueNames)(cn=%g)(uniqueMember=cn=%u,ou=People,o=bit,c=cn))" \
-h ldap.server
acl ldapgroup-basic external ldapgroup ccproxy
http_access deny !ldapgroup-basic
http_access allow ldap
http_access deny all

其中前 3 行让 squid 通过 LDAP 进行认证;第 4 行,让 squid 去判断用户是否在某个组中,其中 %g 表示组名,而 %u 表示用户名;第 7 行定义了一个用户组 ldapgroup-basic,它在 LDAP 服务器中的名字为 ccproxy;第 8 行禁止非 ccproxy 的用户访问,第 9 行允许 ldap 认证通过的用户访问。

以上只是配置中与 LDAP 相关的部分。

没有评论

Jetty 的基本使用

0. 安装

直接解压即可

1. 启动

bin/jetty.sh start

2. 增加应用

在 contents 目录中创建文件 webapp.xml,至少添加如下内容:

<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!DOCTYPE Configure PUBLIC “-//Mort Bay Consulting//DTD Configure//EN” “http://jetty.mortbay.org/configure.dtd”>
<Configure class=”org.mortbay.jetty.webapp.WebAppContext”>
<Set name=”contextPath”>/webapp</Set>
<Set name=”resourceBase”>/path/of/webapp</Set>
</Configure>

当 contexts 中的文件更新时,系统会自动重启相应的 Web 应用程序。

没有评论

PHP 编写 SOAP 客户端时日期(Date)的处理

SOAP 客户端要处理日期信息,刚开始的时候不知道怎么处理,原来只要用 strtotime() 生成参数传递过去就可以了,SOAP/Ext 会自动处理后面的情况。

(2) 条评论

mlterm 的配置

main:

fontsize=20
use_anti_alias = false
not_use_unicode_font=true
ENCODING=utf8

font:

ISO8859_1=-*-terminus-medium-r-normal–20-*-*-*-*-*-*-*
GB2312_80=20,-*-fangsong ti-medium-r-normal–16-*-*-*-*-*-*-*

需要安装 terminus 字体。

没有评论

Apache + Jetty 架设 CAS 单点登录

最近一段时间一直在断断续续地尝试 CAS 单点登录的问题,一般的文章,都是直接使用 Tomcat 或者 Jetty 等 Java 应用服务器直接配置 SSL 并安装 CAS 的,但我不太想让 Java 服务器直接 binding 到 443 端口,因此就想仍然用 Apache 处理 SSL 请求,并转发给 Jetty。在这个过程中,主要尝试了以下个问题:

  1. 如何生成自签名的证书
  2. 如何配置 Apache
  3. 如何配置 Jetty
  4. 安装、测试 CAS
  5. 把自己的 CA 证书导入到 Java 的 cacerts 文件中并测试 CAS Proxy

整个过程在 Ubuntu 7.10 上完成,现记录如下。

1. 生成自签名的证书

通常要配置 https 的服务器,都需要一个由正式的 CA 机构认证的 X509 证书。当客户端连接 https 服务器时,会通过 CA 的共钥来检查这个证书的正确性。但要获得 CA 的证书是一件很麻烦的事情,而且还要花费一定的费用。因此通常一些小的机构会是使用自签名的证书。也就是自己做 CA,给自己的服务器证书签名。

这个过程有两个主要的步骤,首先是生成自己的 CA 证书,然后再生成各个服务器的证书并为它们签名。 我是用 OpenSSL 来生成自签名证书的。

第一步是制作 CA 的证书:

openssl genrsa -des3 -out my-ca.key 2048

openssl req -new -x509 -days 3650 -key my-ca.key -out my-ca.crt

这会生成 my-ca.key 和 my-ca.crt 文件,前者存放着使用 my-ca.crt 制作签名时必须的密钥,应当妥善保管。而后者是可以公开的。上面的命令为 my-ca.key 设定的有效期为 10 年。

用命令

openssl x509 -in my-ca.crt -text -noout

可以查看 my-ca.crt 文件的内容。

有了 CA 证书之后,就可以为自己的服务器生成证书了:

openssl genrsa -des3 -out mars-server.key 1024

openssl req -new -key mars-server.key -out mars-server.csr

openssl x509 -req -in mars-server.csr -out mars-server.crt -sha1 -CA my-ca.crt -CAkey my-ca.key -CAcreateserial -days 3650

前两个命令会生成 key、csr 文件,最后一个命令则通过 my-ca.crt 为 mars-server.csr 制作了 x509 的签名证书。

需要注意的是,在执行上述第二个命令时,Common Name 选项应当输入的是服务器的域名,否则在用户通过 https 协议访问时每次都会有额外的提示信息。

用命令

openssl x509 -in mars-server.crt -text -noout

可以查看 mars-server.crt 文件的内容。

2. 配置 Apache 服务器

首先,创建 /etc/apache2/ssl 目录,将刚刚制作的 my-ca.crt、mars-server.key 和 mars-server.crt 文件拷贝到这个目录中。

接着执行命令

a2emod ssl

激活 Apache 的 SSL 模块,然后在 /etc/apache2/sites-enable/ 中添加虚拟主机,这个过程与添加普通的虚拟主机类似,不同点在于该主机的端口应为 443。配置如下:

NameVirtualHost *:443
<VirtualHost *:443>
  ServerName localhost

  DocumentRoot /var/www

SSLEngine On

  SSLCipherSuite HIGH:MEDIUM

  SSLProtocol all -SSLv2

  SSLCertificateFile /etc/apache2/ssl/mars-server.crt

  SSLCertificateKeyFile /etc/apache2/ssl/mars-server.key

  SSLCACertificateFile /etc/apache2/ssl/my-ca.crt
  <Directory /var/www>
    Order deny,allow
    Allow from localhost

</Directory>

</VirtualHost>

<VirtualHost *:80>

ServerName localhost

  DocumentRoot /var/www

<Directory /var/www>    Order deny,allow

    Allow from localhost

</Directory>

</VirtualHost>

以上配置保证了用户在访问 443 和 80 端口时可以看到相同的内容,而仅仅是使用的协议不同。修改好配置后,便可以重启 Apache 服务器,这时需要输入 mars-server.key 的密码。用浏览器访问

https://localhost/

这时应当看到一个弹出对话框,让你确认是否信任该站点的证书,选择信任后,便可以查看该站点的内容了。

由于大多数 Apache 服务器都是在服务器启动时自动启动,为了避免在启动 Apache 时输入密码,可以用以下命令生成不加密的 mars-server.key 文件:

openssl rsa -in mars-server.key -out mars-server.key.insecure

用新生成的 mars-server.key.insecure 代替原有的 key 文件即可。

3. 配置 Jetty

Jetty 是一个很容易配置的 Java Servlet/JSP 服务器,下载解压后,用命令

java -jar start.jar

即可执行。

由于我们希望通过 Apache 来访问 Jetty,就要激活 Jetty 对 AJP 的支持。可以用如下命令来启动服务器:

java -jar start.jar etc/jetty.xml etc/jetty-ajp.xml

在 Apache 这一端,首先要安装 mod-jk 模块并激活它

apt-get install libapache2-mod-jk

a2emod jk

其次要编写一个 /etc/apache2/worker.properties 文件,描述一下刚刚配置好的 jetty 服务器,文件内容如下:

worker.list=jetty

worker.jetty.port=8009

worker.jetty.host=127.0.0.1

worker.jetty.type=ajp13

worker.jetty.lbfactor=1

接着要编写一个 /etc/apache2/mods-enabled/jk.conf 文件,内容如下:

<IfModule mod_jk.c>
  JkWorkersFile "/etc/apache2/worker.properties"

  JkLogFile "/var/log/apache2/mod_jk.log"

  JkLogLevel info

  JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

  JkOptions +ForwardKeySize +ForwardURICompat
</IfModule>

最后,要修改刚刚的那个配置文件,让 mod_jk 来处理发送给 /cas/* 的请求,在虚拟主机的配置中加入如下命令:

JkMount /cas/* jetty

4. 安装、测试 CAS

下载 CAS 3.x,并将 /modules/cas-server-webapp-*.war 文件复制到 jetty 的 webapps 目录下,改名为 cas.war。

此时通过浏览器访问 https://localhost/cas/ 便可看到 CAS 的界面了。我们是使用 LDAP 服务器来存储用户信息的,关于 CAS 的定制问题,稍后在其它的文章中再阐述。

我是通过 phpCAS 来对 CAS 服务器进行测试的,首先下载 phpCAS-0.6*、解压到 /var/www/phpcas 目录中。

安装 php-curl 和 php-pear,并通过 pear 安装 PEAR::DB。

pear install DB

将 phpcas/docs/examples/ 中的文件复制到 phpcas/sources/ 目录中,修改这些文件中相关的 URL 信息,并用浏览器访问 example_simple.php,便可看到 CAS 的登录界面了。输入用户名密码后,应当可以看到登录成功的信息。

5. 将 my-ca.crt 导入到 Java 的 cacerts 文件中,并测试 CAS Proxy

CAS Proxy 的作用是让一个 CAS 的应用可以通过 CAS 来访问另一个 CAS 应用,而不需要用户多次提供密码。在这种情况下,CAS 会通过 https 访问每个 CAS 应用。由于我们的 CA 证书是自己制作的,它并不存在于 Java 的根证书列表中,这就导致 CAS 无法正常地连接我们的 https 服务器从而导致 CAS Proxy 功能不可用。要解决这个问题,必须将 my-ca.crt 文件导入到 Java 的根证书列表中。

我尝试了用 Java 提供的 keytool 来处理这个问题,但它总是要求输入 cacerts 文件的密码,而我根本没有这个密码。后来尝试用 IBM 的 keyman 解决了这个问题。keyman 是一个 GUI 程序,下载后用它来编辑 /etc/java-6-sun/security/cacerts 文件即可。注意导入密钥时,应选则 trustcacerts。

导入该密钥后,重启 Jetty 服务器,再访问 example_proxy.php 文件便可得到正确的结果了。

参考文献:

1. Van’s Apache SSL/TLS mini-HOWTO
2. Creating a self-signed SSL certificate
3. How to configure Apache SSL
4. Apache AJP13, mod_jk and mod_proxy_ajp
5. IBM KeyMan

(1) 条评论

关于大学学习,说说我的一些体会

人总有困惑的时候,每到寒假核算工作量发奖金的时候,我都会非常难过,感觉前途无望,今年寒假也是如此。不过无意间读到了史蒂芬·柯维先生的《高效 能人士的七个习惯》,收获非常大,一切烦恼烟消云散。如果同学们对大学还有所困惑,很建议大家读读这本书。下面仅就书中的几个观点,结合大学的学习,说说 我自己的看法。

品德成功论

成功的方法有很多种,但如果不先从自身品德修养做起,不坚持诚信做人,即便通过投机取巧的方式取得了成功,也不会获得真正的快乐,这就是品德成功论所强调的东西。也正是这一点让我很认可老外写的这本书,因为他所讲的恰恰就是儒家的“修身、齐家、治国、平天下”的道理。

举个很简单的例子,有些同学的程序是自己写的,还有一些是拿别人的直接提交了。虽然都可以得到“AC”,但感受就完全不同了。抄袭的人感到的只会是担惊受怕或者麻木到没什么感觉,而自己写的人则会体会到成功的快乐、成长的快乐。

现在的大学中,有一种非常不好的风气──作弊。在我上学的时候,有人作弊也绝对不敢告诉别人,但现在有很多同学甚至以作弊为荣、到处炫耀。表面上 看,作弊水平高超可以帮他拿到文凭,但拿到的仅仅是一张没有含金量的废纸而已,而他为拿到这张废纸,不仅浪费了青春,还出卖了人格。

我第一节课上就跟大家讲 RPWT,希望同学们在今后的学习中也能摆正心态、端正态度、诚信为先,否则要毕业时你会发现自己一无所获。

积极主动

无论是在跟一些同学的交流还是在北理 FTP 联盟的灌水乐园中,我都经常会听到看到一些很悲观的论调、对大学、对教师、对课程,似乎学校欠了大家很多,似乎大学中很多课程都是无用的,尤其是那些晦涩 难懂的基础课。我自己上大学的时候,也经常会有这样的想法,所以虚度了很多时光,也有很多基础课都没有学好,现在后悔莫及。等我工作过再读硕士的时候,我 尝试着去认真听每一门课程,特别是那些看似没有什么用处的课程,结果却有很大的收获。

譬如政治类课程通常都是被认为没用的,我读研的时候也要去学一门关于资本论的课程,其中主要讲的是马克思主义政治经济学。在听课的时候,我突然想到 一个问题:马经说商品的价格应该围绕着因无差别的人类劳动而凝聚在商品中的价值上下波动,按照这种理论,现在的知识类商品,特别是商业软件的定价方式合理 吗?这个问题想了很久,都没有想明白,后来一次无意之中知道原来世界上还有很多不同的经济学理论,有一种理论就认为商品的价格是由它能为客户带来的利益决 定的。用这种经济理论来解释关于软件定价的问题就很合理了。如果当初我没有认真地去听那么课,就不会去思考这个问题,也就不会有什么收获。

同样,在学习“科学技术哲学”、“人工智能”、“软件工程”的时候,我很认真地去完成老师布置的论文作业,到网络上搜索相关的论文,到国图的外文阅 览室去查阅会议期刊,很辛苦但也第一次体会到了做学问的感觉。当时我们有一个学分是要听十次讲座,并且交讲座的笔记,我就认真地去听关于计算机、数学的讲 座、去参加 IBM developerWorks 听大师的演讲然后拼命记笔记,这些讲座让我对计算机科学、软件产业有了更多的了解。

从读研的这些经历中我真切地体会到“虽有佳肴,弗食,不知其味也;虽有至道,弗学,不知其旨也”的道理。在大学中的很多课程都是真金白银,能有时间仔细学习必有收获,而很多同学却傻乎乎的视其为粪土。

也许其中一些课程的授课方式是很死板,是应试教育的继续,也许某些教师的讲解是很无味,让人听了昏昏欲睡,但这并不表明这门课程是没有用的。为什么 不能凭借自己的力量,用自己的学习方法把课程学好呢,课程考试是应试型的,难道我们不能先把考试放在一边去学习它的内容吗,教师或许讲的不好,难道我们不 能不听他讲在教室里仔细的看教科书和相关的参考书吗?

马哲早就告诉我们,内因是主导,对于大学的学习,只要肯积极主动的去想、去做,学好课程,会难吗?

以终为始

昨天看吕秀峰老师班上同学所写的感言时,一个同学说:“虽然课程已经结束了,但对于我来说却是刚刚开始……这也是我很想说的一句话,我们的课程虽然结束了,但对于大家的大学学习而言,大一只是一个开始,对于要融入“终身学习”型社会的人而言,这更是一个开始。

每年都会有很多同学问,为什么我们学院不教 C++,为什么我们不学 Java,为什么我们不教一些新潮的东西?面对这样的问题,我不想去讨论究竟哪个知识更有用,因为等学明白的时候自然也就会明白。我想问一个问题,既然你 想学,为什么不定下一个目标自己去学呢?软件学院 06 级的何骞同学说,上完课之后他就想去把 Java 学会,并且已经开始买书,这就很好的,但这还不够!Java 是一门编程语言,在工业中已经有了广泛的应用,什么叫学会了 Java 呢,所以还应该把这个目标定的更明确一些。究竟是要用 Java 写出十个小程序,还是要用 Java 写一个小软件,还是什么其它?目标定的越细,也就越容易检查自己是否做到了。

我一直觉得,把大学的四年作为一个整体来规定一个培养目标是很笼统的,每个人每年都应该有自己的目标,每个学期、每个季度也应该有自己的明确的目 标。学会一门语言、看完一本书、做出几个竞赛题、编写一个小软件、把自己的电脑变成服务器等等,都是同学们完全可以做得到的。定下目标然后努力地完成,就 会进步。

更多的指引

李开复先生在《给中国学生的第四封信──大学四年应该这么度过》中对于大学生活有很多精辟的论述,他的《做最好的自己》和《与未来同行》强烈建议同学们找来读读。

(6) 条评论

关于程序设计方法与实践课程,说说我的想法

学这个东西有用吗?

大概两年前的这个时候,我正在做 C 语言程序设计的辅导教师,到了时间就呆在机房里面等着回答学生的问题。那个工作真的是挺轻松的,因为几乎没有人问我问题,很多同学都在拿学校发的上课用的 机票在机房里面打游戏,我的工作就成了去一个一个地提醒。但是,有一天,一个学生命科学的同学拿着课本跑来,问了我一个至今都印象深刻的问题,她说:“我 每一次上课都去了,上课时老师说的每一句话我都听懂了,可我还是感觉什么都不会,而且根本不知道学这个东西干嘛。学这个东西有用吗?

做老师的人,经常会埋怨讲课之后学生不认真听,或者说学生下课后不认真看书,不认真写作业,但当一个学生认真听课、认真看书、认真写作业之后,却依然学不明白,甚至还不知道学一门课程干嘛,那就真的值得做老师的人反思了。

“学这个东西有用吗?”当时我想了很久,都回答不上来。后来仔细想想,这个问题我自己读本科的时候也问过,现在也有很多很多的同学都在问。今天,我 依然没法直接回答这个问题,但我已经知道了这个问题产生的原因:我们的观念错了!过去人们常说“知识就是力量”,但这句话是错的!什么是正确的呢?“运用 知识才是力量!”如果上课、看书、作业都只是把知识记下来、背下来,为的就是通过考试,那有什么用呢?

黑色星期五的开始

这件事情之后,我写了一封邮件给我的恩师加领导陈朔鹰老师,说了一些对 C 语言教学的认识,然后就得到一个任务:开一门 C 语言的后续实践课,课程在机房进行、以上机为主。

我认为自己如果去做软件工程师的话,还是可以及格的,而在自己成长的过程中,除了各位恩师的教诲和给予的实践机会之外,有两样东西对我帮助最大:一 是高中时参加信息学奥赛(那时的比赛并没有现在这么功利),二是通过互联网接触到了开源软件。前者让我学会了如何使用计算机,后者让我接触到了一个无边的 计算机技术世界。我相信,如果这两者可以帮助我的话,也一定可以帮助其他的人。

在 C 语言的后续实践课中引入信息学奥赛的教学方法刚好是合适的,于是在和陈老师商量过之后,程序设计方法与实践这门课程诞生了。这门课第一次是给软件学院 2003 级的同学开的,在暑假的小学期,他们当时刚刚上完大二。

开一门新课是很痛苦的,因为完全没有经验,也没有软件可以用,而时间又很紧张。于是在课程开始前花了几个星期的时间去给 Moodle 开发“编程练习”这个模块,又在 Linux 上用 Python + C 写了个超级简单的 OJ。当时做这些东西完全是为了赶时间,只要可以工作就好,所以功能很简单而 Bug 却很多。而且因为设计时一些问题没有考虑好,以至于今年它还经常坏。现在虽然知道该如何修正这些问题,却没有太多时间去修改以及测试了。

这一次开课是非常累的,三周的时间几乎天天跑学校,经常下午要上课了,而中午还在办公室出题,也有时课上到一半 OJ 坏了就要做下来调试修改。不过这种辛苦还是非常值得的,因为我让软院 03 级的很多同学跟着我一起辛苦了一把。记得当时有同学说他们每天熬夜编程到凌晨,但却很高兴,因为对编程有兴趣了。

从此开始的两年,这门课占去了我大多数的时间和精力,而之后由于每周五上课,此课程也有了“黑色星期五”这个别名。通过课程,我认识了很多出色的同学,也听到了关于课程的各种各样的问题,下面就说说我对这些问题的看法。

我没有学到知识!

很多次在同学们写给我们的意见中都提到过一个问题:上这门课,什么知识都没有学到!我很高兴同学们会提出这个问题,因为提出这样的问题说明同学们有很强的求知欲。同时我想说,程序设计实践课的教学目的并不是为了告诉大家一些具体的知识。

中国科技大学校长朱清时先生在《什么样的基础课教材是最好的?》 一文中提到:“20世纪知识大爆炸,人类积累的知识越来越多,以至于让学生上了很多课程,但还是到不了知识的前沿,同时还增加了学生负担,使学生感觉到上 课就像填鸭式的灌输式教育。”他认为这是教学思想的问题,因为“不放弃知识的连贯、完整和全面,因此造成了学生负担非常重,而且培养学生创新能力的训练非 常少,学生的精力非常多地花在规定的课程上去了。”而在现代的西方大学,他们“只强调,某一个系、某一个专业毕业的学生,必须有哪些基本训练,这些基本训 练就是一些知识点,学生掌握了这些知识点,就可以毕业了。这个学生毕业之后一生都在自学,一生都在学习新的东西,但学习的新东西,不是靠老师消化传授给 他,而是自己学习。自己学习恰好就逼出学生的创新能力和自学能力。”

我不知道在计算机学科,一个学生究竟应该有多少基本训练,但我相信,编程能力训练一定是其中之一。因此,让同学们具备基本的编程能力,懂得如何通过编程去解决问题,才是我们这门课程的教学目标。

当然,我并不是说学习具体的知识没有用,相信大家在“动态规划”的相关练习中应该能够体会到具体的知识是非常有用的。但有用的知识太多了,时间却是有限的,因此,利用有限的时间努力地培养自己的学习能力要比用有限的时间去学习无限的知识划算一些。

问题求解的基本素质,你具备了吗?

以前我通常都会在第一节课问同学们一个问题,编程是为了什么?人们发明计算机又是为了什么?答案很简单:解决实际问题。我们要学习编程,就必须要努力培养解决问题所必须的基本素质。那么你是否已经具备了这些素质呢?

哈尔滨工业大学的孙志岗老师在他的《高级语言程序设计课程如何培养学生的问题求解能力》一文中讨论了“问题求解的必备素质”,这一段写的很精彩:

自学

12年的初等、中等教育也培养了学生强烈的依赖心理。尤其在学习上,他们习惯于 跟随着教师,亦步亦趋地学习,这样既不符合个性化、精英式的教育准则,对问题求解能力的锻炼亦无甚帮助。在问题求解过程中,自学相关知识是一个不可回避的 环节。只有不断地自学,不断地进步,才能保持住先进性,所以必须打破学生的依赖心理,培养学生的自学能力。

自学能力是阅读、检索、分析和综合等能力的具体体现。自学决不是让学生自己干啃教科书,而是广泛阅读书籍、论文和互联网等信息源,并动手实验。通过自学,学生的视野会变得更宽,思考得更深入,不会单纯地受到一个教师、一本书或一个作者的思想和能力的束缚。

自主

有一个笑话:

老师对小朋友们提问:“请对其他国家的粮食短缺问题谈谈自己的想法。”
非洲小朋友:“什么是粮食?”
欧洲小朋友:“什么是短缺?”
美国小朋友:“什么是其他国家?”
中国小朋友:“什么是自己的想法?”

也是依赖心理的作祟,使中国学生很少有自己的想法。大学以前的教育意图是让学生无条件接受课本和大纲,大学以后的教育就应该鼓励学生无条件地质疑一切。朱熹曾说:“读书无疑者,须教疑。”亚里士多德也曾说:“人的思维是从质疑开始的。”

当 学生不盲目崇拜权威,而是敢提出并实践自己的观点时,他才开始步入真正的科学殿堂。学生应有自主决定干什么、怎么干的热情和愿望,这样才能引发创新,促进 问题求解。在自主探索的过程中不可避免地会犯各种错误,甚至会面对失败,但失败的经验是年轻人成长道路上最宝贵的财富。

自信

通过与学生的交流发现,绝大部分学生并非不懂得自立的重要,也并非没有自立的愿望,而是 没有自立的信心。因为缺乏自信,他们不相信自学的结果,也不相信自己的想法,从而使他们继续失去自我,成为庸俗的附庸。也许在教师的指导下他们能是解决旧 问题的能手,但决不会变为解决新问题的能人。

自信可以让人坦然地面对失败和阻力,积累经验,也能让人更加大胆地去尝试自己的想法,向解决问题的目标更进一步。通过自学与自主解决问题后,自信心获得大幅的增强,从而更有力地支撑今后的自学与自主,形成一个良性循环。

自乐

快乐是人类行动的最佳原动力。在快乐的驱使下,人可以主动、投入地做任何事情,所以体会到问题求解的快乐是进行求解活动的必要因素。

问 题求解带来的快乐与相声、小品带来的快乐不同。这种快乐是一种很难用语言表达,很难与他人共享的快乐,所以为“自乐”。它的主要源泉有三个,一是成功解决 问题的快乐,二是解题过程中收获颇多的快乐,三是成果为他人所用的快乐。总的来说,就是各种形式的成就感带来的快乐。它对问题求解也是一个良性循环的推动 力。

老师总说“不会自己回去看,别总问老师”,那还要老师干嘛?

这是一个同学在教务处评教系统上的留言,这也是很多同学在课程过程中有过的想法。相信大家看了上面关于的论述,应该已经有所体会了。

问题是可以问的,但应该如何问是有学问的,Eric Raymond先生在他的《提问的智慧》 一文中提到:“第一件需要明白的事是黑客喜欢难题和激发思考的好问题。如果你能提出一个有趣的问题让我们咀嚼玩味,我们会感激你。好的问题是种激励与礼 物,帮助我们发展认知,揭示没有注意或想过的问题。在黑客中,‘好问题!’是非常真挚的赞许。”而“我们只是毫无歉意地敌视那些提问前不愿思考、不做自己 该做之事的人。这种人就象时间无底洞──他们只知道获取,不愿意付出,他们浪费了时间,这些时间本可用于其它更值得回答的人和更有趣的问题。我们将这种人 叫做‘失败者 (loser)’”。

教师不是活字典、不是活教科书,对于那些书上写的明明白白的问题,我是不会回答的,因为提问者在问问题之前,并没有完成自己的功课。问一个好问题,被提问者通常都是很乐于回答的。

记得我上本科学习 C 语言函数一部分的时候,问了陈老师一个问题,大意是“通常函数参数的个数都是固定的,但我们最常用到的 printf、scanf 这些函数的参数个数可以是不固定的,这在 C 里面应该如何写呢?”在问这个问题之前,我真是翻了很久教科书都没有找到。当时陈老师说他以前在读操作系统的源码时看到过,但一时想不起来了。后来陈老师 帮我找到了答案,而在这之前,我也从某个 C 开发环境的手册中找到了答案。应该说这个问题,让我收获的不仅仅是知识,也有了更多的机会。

为什么不先上数据结构课?

有不少同学认为应该先上数据结构、算法课,然后再来利用数据结构、算法课程的知识解决问题,也就是要注意知识的连贯性。可为什么我们偏偏要让同学们 先去用一下数据结构、算法的知识呢?假设大家没有认识到数据结构、算法的用处,那么在上数据结构、算法课的时候很有可能糊里糊涂,等到上完了这些课去实践 的时候就会发现自己什么也没学会,那就晚了!所以我们就是要让大家先拿起数据结构、算法的书自学,让大家体会到这些课程的用处,这样在学习数据结构、算法 等课程时效果会好得多。这也正是我们这门课程“承上启下”作用的体现。

另一方面,我们也希望同学们从这个过程中体会一下原来自学是可以学会很多东西的,其实大学课程中的东西并不是那么晦涩难懂,只要有好的参考书,有合 适的学习方法,一定可以学会。我自己有一种感觉:在毕业后工作中用到的技术,没有一点是在大学的课程中学会的,几乎全部是通过自学来获得的。大学课程能够 培养的是理论基础、学习习惯、研究方法和独立思考、独立解决问题的能力,再优秀的大学教育,也很难教会学生四五年后才出现的新知识。

为了两个学分,却占用了我那么多时间

这恐怕是很多同学都有的想法,首先我想说的是学习不是为了学分,上大学不是为了毕业,如果连目标都错了,那一定得不到正确的结果。如果抱着这样的想法来学 习,那就不要怪学校、怪老师给你应试教育。我在课程里面加过一个小测验,希望大家能够对处理输入结束有多一点了解。结果有一个同学又问我一个关于输入结束 的问题,我就问他做没做那个测验,如果做了,怎么还是不会呢?他告诉我他是用“排除法”做的,我无语……

05 级有一位同学留言说,“人们说‘在哈佛,你就好像被马拉着跑’,而在这里,我感觉自己就是在爬,甚至原地不动。”大学原本就应该是紧张感而忙碌的,那种期望在大学享受人生的想法根本就是错误的。

去年给 05 级同学上课的时候,很多同学都抱怨说编程占用了大量的时间,搞的他们没有时间看别的书了。于是有一次上课前,我就在教室里面转,一个一个地数究竟有几个人在看书,结果上百人的教室只有七八个同学在拿着书看。这样的状况也好意思说自己没时间?

时间不是一个小时一个小时放在你面前让你用的,琐碎的时间加在一起可以做很多的事情!我上大学的时候,每次上课书包里面都至少会有两本书,一本教科 书、一本自己喜欢的书。上课了就看教科书,下课休息的时候就看自己喜欢的书。工作后,我在某次出差的火车上看完了《Essential C++》,而在上班的公交车上,我看完了半本《论语别裁》。鲁迅先生说过:“时间,就象海绵里的水,只要愿挤,总还是有的。”

实践推动理论学习

“发现看书真的有用,只看书真的没用,边看边实践还真起作用。”这是 05 级陈俊强同学给我们的留言,这也正是我们希望同学们能够体会到的。

计算机是一个需要实践的学科,即便是对于科学研究而言,如果最终没有硬件、软件或算法的话,也只能算是数学家,看看图灵奖早期的获奖者的故事就会发现他们个个都理论精湛而又技艺超群。

因此实践是学好计算机所必须的,在每一门理论课的学习中,也都需要加强实践。当去学习一个科目的时候,如果授课老师没有提出一个有趣的问题,那作为 学习者能不能想一个有趣的问题?如果老师没给实践的机会,能不能为自己创造一个运用所学知识的机会?05 级有很多同学就尝试着写一组类来完成线性代数中复杂的矩阵运算,04 级的王伟同学就把计算机组成原理课程中碰到的很多有趣的问题编成可以直接用编程来解决的小问题。

在今后学习离散数学、数据结构、算法、组合数学、人工智能、计算机组成原理、汇编语言、操作系统、数据库原理、计算机网络、编译原理等等专业课和其它基础课的过程中,如果同学们尝试着多做一些实践,那么学习效果一定会超过只背书本。

评分方法

除了做题之外,还可以通过其它的内容得分。譬如在论坛上发言可以得分,很多同学觉得这不合理。我想,课程的评分方法体现着教师的价值观,因为我认为在学会在论坛上与人讨论是非常重要的,所以我会给它加分。

“学而无友,则固陋而寡闻”是千年前先哲对我们的教诲,而网络时代最好的以学会友的地方就是网络论坛,可居然就有很多学生读了研还不会在论坛上与人 沟通。我有一种观点,在北理工读四年书,如果在校内的三大论坛上还没有注册账号,那就是白读了。也许有点偏激,但我就是这么想的。

两极分化

我个人在上课的过程中有一个很不好的感觉,就是在学生中两极分化是非常严重的,不过我一直都没有想到什么太好的解决方法。同时我也认为大学教育和中 学教育是不一样的,如果上了大学还指望老师把内容一点一点仔细地讲直到懂了为止,还希望老师能为学的不太好的同学开小灶,那在大学必然会失败。

在课程的第一天我就说:“我会给你一本武功秘笈,但不能保证你成为武林高手。”在这门课的学习过程中,有很多基础不好的同学通过自己的努力有了跨越 式的进步,也有很多基础不好的同学在抱怨我们为什么不多讲讲基础。其实内因的作用比外因的作用大得多,寄希望于别人,不如在自己身上挖掘潜力。

道德是心中有人,能力是眼中有事

经常有人在向我抱怨“现在的学生越来越没礼貌了”,而我对此也有那么一点担忧。我记得在读本科的时候,下课之后,我们每个班都会有人主动去帮助老师 擦黑板;工作两年读研究生的时候,如果我去听课,我都会帮老师擦黑板,但似乎每次都是我擦;现在我走上讲台,却很少有学生帮我擦黑板。台湾著名的教育家高 震东先生说“道德是心中有人,能力是眼中有事”,那么没人帮老师擦黑板所体现出来的是什么呢?我觉得这是一个非常值得同学们思考的问题。
你请别人帮忙,得到的结果往往取决于你说话的态度。经常有同学程序错了给我发短消息让我帮着调,可言语之中却是命令的口吻,似乎这件事情我必须得 做,还得抓紧时间做。在联盟上,我经常看到有人在抱怨食堂的服务差、抱怨学校里办公人员态度恶劣;可有一次我就亲眼目睹一个学生仅仅因为米饭看上去少了一 点而对卖饭的师傅污言秽语指责了很久;还有很多同学在学校里面办事的时候,门也不敲、见了老师也不叫,办完了连谢谢都没有。以这样的态度对待他人,又怎能 得到别人的微笑呢?

痛并快乐着

“又爱又恨”、“痛并快乐着”,很多同学在课后给了程序设计实践课如此的评价,这也正是我自己在讲课过程中的感受。爱、恨、痛苦、快乐这些感受都是相对的,没有恨如何体现爱,没有痛苦过又怎能体会到真正的快乐?

应该感谢的人

程序设计实践课至今已经面对不同的同学开了七次,每一次的前三四周,我们都要面对同学们的各种各样的质疑,这些质疑的声音不仅会在课程中,还会随着 班主任和辅 导员一点一点往外传播,直至学院领导那里。也正是因为如此,我们这些开课的教师都特别感谢各级辅导员、班主任以及学院领导对我们工作的支持,能够帮我们给 同学们做思想工作,没有他们作为我们这些教师的后盾,我们肯定是顶不住的。

两年来,程序设计方法与实践的课程组不断发展壮大,课程组的教师们除了这门课程的教学之外,都还承担着其它繁重的教学、科研或行政工作,对于他们在备课、授课过程中所表现出的认真负责和对此课程一如既往的关注与支持,我个人真是非常感激的!

每次课程结束后,我们都会收到同学们各种各样的意见,无论是支持我们的也好,批评我们的也好,我都很高兴,因为“爱的反面不是恨,而是漠不关心”。这些正是我们讲授此课程所获得的最大一笔财富,因此非常感谢上课的同学们对此课程的关注,谢谢!

(6) 条评论

永中Office在Linux环境下安装问题的总结

1. 安装

通常 Linux 都会自带 JRE,因此不一定要使用永中带的 JRE。在解压后,直接运行 java -jar dispose.jar 就可以安装了。注意要用 Java 1.5,不能用 Java 6。

2. 从桌面双击文件启动编辑

修改 /usr/share/applications/eio.desktop,将其中的 %u 替换成 %f

3. Beryl 下启动后看不到内容

此为 Java 的 Bug,在 /usr/bin/eio 中添加 export AWT_TOOLKIT=”MToolkit”,或者通过其它的方式设置这个环境变量。

以后再遇到问题慢慢补充了。

(1) 条评论

Mozilla XEmbed plugin 和 GTK Socket/Plug

今天抽空看了一下 Mozilla XEmbed plugins 应该如何实现,顺便给 Antler 做了个补丁。

XEmbed 的作用是把应用 A 创建的一个窗口交给应用 B 来使用,应用 A 和应用 B 可以是一个进程,也可以是不同的进程。在 GTK2 中,通过 GtkSocket 和 GtkPlug 来对这种机制进行支持。通过这个机制,可以让多个进程同时对一个窗口的显示内容进行操作。

在比较新 (1.0以后) 的 Mozilla 中,Gecko Plugin (也就是我们说的插件)就可以通过这种机制来实现。Gecko 会先通过 NPP_GetValue 来问插件是否支持 XEmbed,如果插件支持,则它会创建一个 GtkSocket,并将其 XID 通过 NPP_SetWindow 的第二个参数的 ->window 域传递过来,在插件中则可以通过这个 XID 直接创建一个 GtkPlug 并使用它了。这比使用传统的 Xt 接口要方便很多。

据说这个机制能够解决插件的一些问题,但在 Antler 中一个比较大的问题是当焦点在 scintilla 中时,它会把所有的键盘事件都吃掉,不管对它有没有用。这应当是 Netscape  Plugins API 的问题。因为在这里,来自 Macromedia 和 IBM 的开发人员指出了这个问题。

(1) 条评论

Async Web Server

Web 2.0 中一个很重要的技术是 AJAX,而 AJAX 对于 Web 服务器也有了不同的要求。在传统的 Web 中,优秀的 Web 服务器最重要的是其响应速度,因为处理完一个请求马上就可以去处理另外一个。然而在 Web 2.0 的一些应用中(如 Chat),发给服务器的请求要被故意延迟,从而保证用户有更好的体验。譬如:

  1. C –> S 请求
  2. S 在一段时间如10秒内不断循环,查看是否有数据可以传递给 C,若有则发送,但一定要到10秒后才关闭请求
  3. C 接到数据后立刻显示,若请求关闭,则跳转到 1。

在这种情况下,Web 服务器不仅要有良好的响应速度,还要能够在同一时刻处理更多的请求。传统的 Web 服务器如 Apache 1.x,是用进程来处理多个请求的,每个请求都在尽可能短的时间内处理完毕,即便有很多请求也能用一个进程完成处理。但如果 Web 2.0 的服务器端程序有意延迟每个请求的处理时间,则访问人数越多,需要创建的进程也越多,每个进程都要占用内存,这无疑会给 Web 服务器的性能带来巨大的影响。

在这种情况下 Web 服务器和 Web 应用程序都必须采用不同的技术来处理并发的请求,尽可能地降低处理每个请求的成本。这通常有两种方法,一个是采用线程技术,另一个是 select/poll 等系统调用来设计 Web 服务器及应用。对于 Web 服务器,目前大都已经能够很好地支持线程,但对于服务器端的编程语言如 PHP,还不能很好地支持线程,而传统 CGI 的执行方式是不能用于线程的。

当然这种需求并不是所有的 Web 应用都有,但随着 Web 2.0 的进一步普及,会有越来越多的应用有类似的需求。

没有评论

« 下一页