Debian里编译内核

以Debian 2.6.8版本为例:

1、Debian.org上关于编译内核的说明;另一篇看起来不错的文章:Creating custom kernels with Debian's kernel-package system

2、下载内核源代码apt-get install kernel-source-2.6.8,在/usr/src下得到kernel-source-2.6.8.tar.bz2文件,用tar xfj命令展开;

3、下载需要的patch,比如休眠功能的patch是kernel-patch-suspend2,注意目前在experimental里才有,所以要在/etc/apt/sources.list里加上必要的源;

4、执行以下操作,如果当前语言是中文,执行前最好执行zhcon进入中文环境:

# cd /usr/src/kernel-source-2.6.8
# cp /boot/config* .
# make-kpkg clean
# make-kpkg --append_to_version -2 --added_patches suspend2 --config menuconfig
# make-kpkg --append_to_version -2 --initrd kernel_image
# cd ..
# dpkg -i kernel-image-2.6.8-2.i386.deb

注意在menuconfig的时候先载入原来的配置文件,即上面第二行复制过来的/usr/source/config-xxx文件,然后在这个配置上进行修改;另外,我如果不加--initrd参数,则新内核无法启动。

5、重启电脑用新内核启动。

Update(2005/12/23):不加--initrd参数可以启动了,关键是在menuconfig的时候要把ext2,ext3等文件类型加入内核,同时要把对ide设备的支持直接加入内核,我以前只注意了前者。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2005/10/13/254213.html

Debian安装备忘

对linux的兴趣时断时续,以前用的都是redhat,这次换用Debian吧,希望能坚持一直用下去,直到完全替代windows。这是安装Debian的过程,遇到的问题和解决方法,备忘。

1、用分区工具如PQMagic划出一块空闲分区,我给的大小是4G;

2、下载debian当前版本的第一张光盘映像,刻成光盘;

3、用这张光盘启动,在boot时输入linux26用2.6内核启动,选择语言为中文,其余按提示操作,注意分区时选择最大空闲空间,自动分区即 可。安装时曾遇到过无法dhcp连接的问题,后来把网线插在无线路由器上就解决了,原来一直是插在歌华有线送的cable-modem上,很奇怪在 win2000下这样是可以得到IP地址的;

4、无线网卡的配置。我用的是Netgear WG511网卡,方法是在 http://prism54.org/%7Emcgrof/firmware/ 下 载最新的firmware版本,更名为isl3890isl3877各一份放在/usr/lib/hotplug/firmware下面(用grep FIRMWARE_DIR /etc/hotplug/firmware.agent命令找到),对于2.6版本的内核需要mount sysfs,方法如下:

mkdir /sys
Add "none /sys sysfs defaults 0 0" to /etc/fstab
mount /sys

再在/etc/network/interfaces里添加这样两句(假设无线网卡的代号是eth1),

auto eth1
iface eth1 inet dhcp

这样用ifup就可以启动无线网卡并通过dhcp获取ip地址了:

ifup eth1

这个是关于prism(WG511所使用的芯片)驱动的wiki网站http://prism54.org/phpwiki

4、apt-get install gdm gnome-core x-window-system-core ttf-arphic-uming,其中ttf-arphic-uming字体是为了让gnome显示中文(虽然不是非常好看);安装小企鹅输入法, apt-get install fcitx,完成后要做一些设置:把下面的内容保存为/etc/X11/Xsessin.d/25chinput-start,然后重新启动X或重新启动 系统:

export XMODIFIERS="@im=fcitx"
export XIM=fcitx
export XIM_PROGRAM=fcitx
fcitx&

如果需要配置fcitx的参数,可以修改/root/.fticx/config文件;

5、因为屏幕1400x1050算非标准分辨率,所以在/etc/X11/XF86Config-4里添加这个值,然后在gnome里就可以把桌面设置为这个分辨率了;

6、(从现在开始是在Debian里写了;)要在面板上显示电池电量,先要安装acpid,然后在面板上添加电池电量监视器即可;

7、这时的声音不正常,用mpg123播放mp3发出刺耳的噪音,apt-get install alsa后,执行alsaconf检测声卡,然后重新启动就好了;

8、安装应用软件:msn用gaim,画图用gimp,收信用evolution,浏览器mozilla firefox,听歌xmms,媒体播放器totem,等等;

9、用优盘mount /mnt/sda1,同时用第二个优盘mount /mnt/sdb1,用pcmcia的读卡器mount /mnt/sde1。写到/etc/fstab里可以简化命令,iocharset=cp936选项可以显示中文文件名。

10、网卡如果要使用静态ip地址(在实验室就是这种情况),/etc/network/interfaces里这样写:

iface eth1 inet static
        address 162.105.131.205
        netmask 255.255.255.128
        broadcast 162.105.131.255
        gateway 162.105.131.129
        dns-nameservers 162.105.129.27

要转换为dhcp时运行$dhclient eth1即可。

11、让cpu支持降频,装cpufreqd,在/etc/modules里添加speedstep-ich;可用的模块列表在这里 /lib/modules/[你的内核版本]/kernel/arch/i386/kernel/cpu/cpufreq;重启服务sudo /etc/init.d/cpufreqd restart。

12、若usb设备不能停止,用这个命令杀掉使用它的所有进程:sync && fuser -m /dev/sda1 -k

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2005/09/26/244596.html

在Win2000里快速切换TCP/IP设置

自己的笔记本要在多个地方上网,但家里是自动获取IP的,实验室有自己的子网,宿舍又有另一个子网,每次换地方都得手动换TCP/IP设置,很麻烦。今天在网上看到一篇文章,原来要解决这个问题是非常简单的,不需要安装任何软件,下面是我的做法。

首先,在网络属性里把TCP/IP配置为实验室用。然后,运行cmd打开命令行窗口,输入如下命令:

netsh -c interface dump > lab.txt

这样就在C:\Documents and Settings\Administrator下得到一个lab.txt文件,当然你也可以在上面的命令里使用绝对路径改变它的存放位置。

接下来,把TCP/IP分别设为其他各处的正确配置,并使用同样命令生成不同的文件,对我来说就是home.txtdorm.txt了。

需要改变TCP/IP设置的时候,例如我要切换到家里上网了,只要执行下面的命令:

netsh -f home.txt

切换就完成了,很方便吧。总结一下就是两条:netsh dump导出设置,netsh -f导入设置。

还要提醒一点,如果是切换到自动获得IP的方式,最好用ipconfig /renew命令强制获得一下,否则要等一段时间才能上网。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2004/11/04/60551.html

[测试]使用Mantis跟踪bug

file

在PPP项目中我们组使用PVCS Tracker来跟踪bug,感觉项目组的确是需要这样一套系统的,PVCS虽然功能比较强,但首先不是免费的,另外也比较大,对于示范中心这样的小项目来说有些不够灵活。因此我安装了Mantis,一个十分小巧的bug跟踪工具。

Mantis是php写的开源软件(Bugzilla也是开源的,written in perl,但在windows下安装麻烦,所以暂时不考虑)。安装Mantis的步骤很简单,以下总结在Win2000/XP下的安装过程:

1、如果机器上有IIS,确保已经启动;如果希望使用Apache,从 httpd.apache.org 下载apache的windows安装程序,我用的是1.3版本,直接运行这个程序就安装完成了。

2、从 www.php.net 下载php的windows安装程序,我用的是4.3.8版本,也是直接运行下载来的程序。我用IIS时安装程序会自动对IIS进行设置,但在另一台没有IIS而使用Apache的时候,即使在安装过程中选择了正确的服务器类型,也会提示自动设置出错。不过手动设置也很简单,只要在apache安装目录下的conf目录里的httpd.conf里增加这样一段:

ScriptAlias /php/ "c:/php/"
AddType application/x-httpd-php .php
Action application/x-httpd-php "/php/php.exe"

这样就可以了。不过按照PHP的安装说明,这种方式是很危险的,我对PHP不熟,说不出到底危险在哪,可能是容易给Web服务器带来一些安全漏洞吧。

3、从 www.mantisbt.org 下载mantis的0.8.3版本(原来写成1.8.3是笔误,谢谢wfifi指出。mantis目前已有1.0.0rc版本),它很小只有几百K。如果是IIS,把mantis解压缩到Inetpub下(我一开始解到c:下总是不行,可能是权限问题),然后增加一个虚拟路径指向mantis目录;如果是Apache,把mantis解压缩到apache的安装目录下,并在httpd.conf里把主目录改为指向这个目录,或者增加一个Alias,但权限要设够才能正常运行。为了方便,可以在Web服务器里增加index.php为缺省文件名。

4、从 www.mysql.net 下载mysql,我用的是4.0版本。在mysql里为mantis建立一个帐户,然后建立一个名为bugtracker的数据库,这是mantis配置文件里的缺省名字,在mantis安装路径下的sql目录里有一个db_generate.sql文件,这里面是建表的语句,执行它。

5、把mantis安装路径下的config_inc.php.sample改名为config_inc.php,打开并修改里面的内容。主要是和数据库连接的信息,例如数据库名、用户名等等。我在最后加了这样两句:

$g_default_language = 'chinese_simplified';
$g_enable_email_notification = OFF;

这样缺省界面就是简体中文的,并且不发送邮件通知。要发送邮件还要对PHP进行另外的配置,我还没有试过,好象挺麻烦的,所以干脆禁掉。另外mantis提供的简体中文语言包里好象很多“删除”都写成了“.h除”,我对lang目录中的strings_chinese_simplified.txt文件做了一个替换(.h除->删除)就好了。

6、最后,重启一下Web服务器,就可以访问了,地址是 http://localhost/mantis 这样的。按照mantis的建议,应该新建至少一个administrator级别的用户,然后把admin目录删除,并删除administrator这个帐号。

我们的项目不复杂,而且成员少,所以mantis的安装能用就行,对安全和报表、邮件的配置都没有关心,以后需要用到的时候再研究吧。

Update(2012/11/12): 今天再次看了一下Mantis网站,这个bug跟踪系统又有很多改进,而且增加了手机客户端,下次有机会还要继续使用。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2004/08/18/34380.html

[测试]将TestCase整合

上一篇贴子里,我简单介绍了如何写一个TestCase(MockStrutsTestCase是TestCase的一个子类),可以看到是十分简单的,基本上只要写一些testXXX方法就可以运行了。当我们选择运行这个TestCase的时候,实际上运行的是一个Test,Test是TestCase的接口,实现这个接口的还有TestSuite类,使用这个类可以把多个TestCase一起运行,从而更加自动化。

要写一个TestSuite更加简单,看一下下面的代码就明白了:

package edu.pku.cc.democenter.test;

import junit.framework.Test;
import junit.framework.TestSuite;

public class AllTests {

    public static Test suite() {
        TestSuite suite = new TestSuite("Test for democenter");
        //$JUnit-BEGIN$
        suite.addTest(TestTeacherAction.suite());
        suite.addTest(TestHibernateDAO.suite());
        //$JUnit-END$
        return suite;
    }
}

当运行这个TestSuite的时候,就会自动对这两个TestCase进行测试。你可能已经看出来了,我们前文中写的TestTeacherAction类中并没有声明suite方法,是的,因此这里就要增加这个静态方法,如下所示:

public static Test suite() {
    return new TestSuite(TestTeacherAction.class);
}

我们在这个方法里只是简单的返回一个TestSuite对象,JUnit会根据传递的参数(TestTeacherAction.class)找到这个TestCase中全部的testXXX()方法并运行。

上面这种suite()方法的写法被称为动态方式,即利用了java的反射机制。还可以写成静态方式,这就需要在TestCase里写两个方法了,如下:

public static Test suite() {
    TestSuite suite=new TestSuite();
    suite.addTest(new TestTeacherAction());
    return suite;    
}

protected void runTest() throws Throwable {
    testListTeacherAction();
    testEditTeacherAction();
    testSaveTeacherAction();
}

这种方式允许用户选择执行某些testXXX()方法,而且这些方法也不一定以test开头,反正只要在runTest()里指定的都给执行。而suite()方法与动态方式比也有变化。要注意的是,如果按动态方式写suite()就不要再覆盖runTest()方法了,我实验后发现,这样会造成runTest()中指定的方法被反复执行n次,其中n等于textXXX()方法的数目。

另外一点,关于JUnite对Test的计数,在动态方式下,JUnit是按照testXXX()的数目计数的;而在静态方式下,是按照TestCase的数目计数的。

还有一点很重要,动态方式下,setUp()和tearDown()这两个方法是在每个testXXX()方法的前后执行;而静态方式下,是在每个TestCase的前后执行,也就是说,同一个TestCase中两个测试方法之间可能不会经过tearDown()和setUp()的过程。

至于动态方式和静态方式的选择,可以根据上面所说的进行参考。不过先声明,以上都是我自己测试得到的结论,存在出现错误的可能性(欢迎告知),以及没有涉及到的方面。

我本人比较prefer动态方式,毕竟代码量小一些

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2004/07/29/28309.html

[Struts]使用StrutsTestCase对Action进行单元测试简介

目前,测试驱动开发正变得越来越流行,由于“存在的就是合理的”,这种开发方式必然有其优越之处。作为一个小小程序员,对新鲜技术的追求是工作的重要动力,相信大家都有同感吧。

测试驱动开发是极限编程(XP)的重要组成部分,从字面上就可以看出,它是先有测试再有代码的。这听起来似乎有点奇怪,实际上,可以把测试用例当作需求,程序员的工作就是写出满足这种需求的代码,即让这些测试都能够通过。在刚刚写好测试用例的时候,由于还没有实际代码,因此这时运行测试的结果一定不会通过,随着代码的增加,越来越多的测试得以通过,最后全部通过。这时,基本上可以说系统的每个功能单元都是正确的,剩下的工作就是集成测试了。而这些测试用例的使命并未结束,因为代码会不断修改,我们需要经常(例如每天)运行测试来检验目前的代码是否能够通过测试。很明显,这种检验是完全自动化的,既快速有保证质量。

在使用Struts构件的系统里,的每一个Action都可以看作一个功能单元,它们构成了系统的主体。(当然,你的业务逻辑并不一定都直接写在Action的execute方法中,但在该方法中会以一定方式调用这些逻辑。)StrutsTestCase 是JUnit的一个包装,它提供了非常方便的测试这些Action的方法。它提供两种测试方式:Mock(模拟对象)和Cactus(真实环境),目前我只试验了前者,发现效果很好。

由于我已经写了一些代码,因此我进行的不能算是真正的测试“驱动”开发,我主要是把StrutsTestCase作为一种自动化的测试工具来用,起到保证代码质量的作用。

举例来说,我有一个类名为SaveTeacherAction的Action,其所在模块名为teacher,访问路径为/save,与他相关联的是名为TeacherForm的ActionForm,(struts-config-teacher.xml)配置如下所示:

<action
    attribute="teacherForm"
    input="/form/teacher.jsp"
    name="teacherForm"
    path="/save"
    scope="request"
    type="edu.pku.cc.democenter.teacher.action.SaveTeacherAction">
    <forward name="success" path="/list.do" redirect="true" />
</action>

SaveTeacherAction类中的execute方法如下,其中HibernateDAO是我自己写的用来进行持久化操作的包装类,BeauUtils是Jakarta commons包中的一个实用工具,可以在两个Bean类型对象的相同属性之间进行复制:

public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws Exception {

    HibernateDAO dao=HibernateDAO.getInstance(getServlet().getServletContext());
    TeacherForm teacherForm = (TeacherForm) form;
    Teacher t=null;

    if("Create".equals(teacherForm.getAction())){
        t=new Teacher();
    }
    if("Edit".equals(teacherForm.getAction())){
        t=(Teacher)dao.findByCode(Teacher.class,teacherForm.getCode());
    }

    BeanUtils.copyProperties(t,teacherForm);

    dao.saveOrUpdate(t);
    return mapping.findForward("success");
}

下面,我要写一个测试用例来对这个Action进行测试。在Eclipse里使用StrutsTestCase非常简单,只需要在工程的classpath里包含strutstest-2.1.2.jar这个包以及junit的包就可以开始编写了。我为这个类起名为TestSaveTeacherAction,即Action类名前加上Test字样,所在包也与实际代码分开,使用edu.pku.cc.democenter.test的名称(与之对比,SaveTeacherAction的包名为edu.pku.cc.democenter.teacher.action,democenter是我们这个项目的名称)。

现在来看一下TestSaveTeacherAction的内容:

package edu.pku.cc.democenter.test;

import servletunit.struts.MockStrutsTestCase;
import edu.pku.cc.democenter.teacher.form.TeacherForm;

public class TestTeacherAction extends MockStrutsTestCase{

    protected void setUp() throws Exception {
        super.setUp();
        setConfigFile("teacher","/WEB-INF/struts-config-teacher.xml");
    }

    protected void tearDown() throws Exception {
        super.tearDown();
    }

    public void testSaveTeacherAction_Create(){
        setRequestPathInfo("/teacher","/save");
        TeacherForm form=makeForm();
        form.setAction("Create");
        form.setCode("test.create");
        setActionForm(form);
        actionPerform();
        verifyForward("success");
    }

    public void testSaveTeacherAction_Edit(){
        setRequestPathInfo("/teacher","/save");
        TeacherForm form=makeForm();
        form.setAction("Create");
        form.setCode("test.edit");
        setActionForm(form);
        actionPerform();

        form.setAction("Edit");
        form.setBirthDate("1979-1-10");
        setActionForm(form);
        actionPerform();
        verifyForward("success");
    }

    private TeacherForm makeForm(){
        TeacherForm form=new TeacherForm();
        form.setAction("Create");
        form.setBirthDate("1979-1-1");
        form.setCode("test.001");
        form.setEmail("test@test.com");
        form.setName("test");
        form.setShortName("CS");
        form.setTel("62760000");
        return form;
    }
}

使用Mock方式的测试用例都继承servletunit.struts.MockStrutsTestCase这个类,setUp和tearDown方法分别是测试前后进行准备和善后工作的地方。要运行的测试方法都以test开头,系统会自动调用这些方法。

由于SaveTeacherAction根据request中的action参数有两种运行方式:Create和Edit,所以我写了两个test方法对它们分别进行测试。这里要注意的是,这些test方法运行的顺序是不确定的,不要认为可以先运行create的测试,再以此为基础对刚刚create的对象进行edit,看testSaveTeacherAction_Edit方法的写法。

我在setUp方法里指定了模块和对应的配置文件名称,如果没有模块可以省去这一步。在实际的testSaveTeacherAction_Create方法里,首先用setRequestPathInfo方法指定要测试的Action的路径和模块,如果没有模块可以用一个参数的同名方法。然后构造一个ActionForm,对于我的例子就是TeacherForm,为了简化代码,我写了一个makeForm方法来生成一个填好值的TeacherForm。用setActionForm将这个TeacherForm连接到Action,actionPerform方法通知执行Action操作。这时按照我们的设想,Action会将请求转发到一个名为success的Forward,所以我们使用verifyForward("success")方法验证是否进行了转发。在这一步如果失败,就表明此单元测试失败,否则为成功。

testSaveTeacherAction_Edit方法与其类似,只是要注意在这个方法里要自己建立对象再修改,而不能使用testSaveTeacherAction_Create方法里建立的对象,因为这两个方法的执行顺序是不确定的。

要在Eclipse里运行这个测试也很简单,先双击打开这个类,然后在Run菜单里选择Run As->JUnit Test就可以了,你会看到一个JUnit视图,里面有一个绿色的进度条,如果走到头还保持绿色表示所有的测试都成功,否则会变成红色,并在下面显示异常的堆栈信息。(成就感哦)

file

好了,今天对StrutsTestCase作了一个很简单的介绍,我也是刚刚开始使用它,今后肯定还会遇到问题的,敬请关注后续报道。

另,相关的一些文章可以在网上找到,作为入门很好,例如:

http://plateau.sicool.com/article/tdd/strutstestcast_junit_tdd.htm

我的感觉,遇到问题最好先找文档,养成习惯后不但解决问题快了,同时在看文档的同时还可以对其加深理解,何乐而不为呢。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2004/07/29/28221.html

[Eclipse]同步CVS时总是提示错误

我在一台机器上使用CVSNT建立了CVS库,并把项目提交到库中没有问题。 回到家修改了一些代码和配置文件,再同步项目的时候,处理到struts-config.xml时提示:

Error fetching file revisions

不明白为什么,然后上google查了一下,找到两个相关问题的地址。 一个是eclipse cvs的faq,上面关于这个问题的解释如下:

This error, or an error stating that "An error has occurred processing file", occur when the CVSNT server has been configured to use a repository prefix (also referred to as a repository alias). CVSNT provides this mechanism to allow compatibility with the Unix/Linux based command line tools. However, the CVSNT server does not properly map the repository paths that are communicated in text messages. The Eclipse CVS client relies on these text messages to provide advanced features such as synchronization and compare. In order for these features to work properly, the CVSNT server must not be configured to use a repository prefix. Instead, the full path name (i.e. D:cvsroot) must be used (see related question above). 

但我并未使用prefix这个功能。另一个网站上有人说:

I've had two things that relate to this problem. 1) Window->Preferences->Team->Ignored resources includes a pattern to ignore files called 'tags' 2) the CVS/Root file used a different case to the repository listed in CVS NT. dion ? 3/24/04; 10:50:48 PM

似乎也不是这两条的原因,因为我的eclipse里关于cvs的设置从未修改过;大小写我也改过,不过还要找时间去实验室看看建库的那台机器里到底是什么样的写法(我判断不是这个原因)。 实在没办法,只能找机会在建库的机器上把这两条删掉重新添加了,甚至把库里整个项目删掉重来了。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2004/07/28/28067.html