Monday, 5 November 2007

linux 字符串操作 tr (sed补全)

tr 用来从标准输入中通过替换或删除操作进行字符转换.tr主要用于删除文件中控制字符进行字符转换.使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换.tr刚执行时,字符串1中的字符被映射到字符串2中的字符,然后转换操作开始.


一般格式:tr -c -d -s ["string1_to_translate_from"] ["string2_to_triampsulata_te_to"]

-c:用字符串1中字符集的补集替换此字符,要求字符集为ASCII
-d:删除字符串1中所有输入字符
-s:删除所有重复出现字符序列,只保留一个,即将重复出现字符串压缩为一个字符串

12.1 字符范围:

[a-z]:a-z内的字符组成的字符串
[A-Z]:A-Z内的字符组成的字符串
[0-9]:数字串
/octal:一个三位的八进制数,对应有效的ASCII字符
[O*n]:表示字符O重复出现指定次数n,例[O*2]表示匹配[OO]字符串

12.2 保存输出

要保存输出结果,需将之重定向到一个文件.例:重定向输出到文件results.txt,输入文件是cops.txt:

$tr -s "[a-z]"<cops.txt>results.txt

12.3 去除重复出现的字符

$more cops.txt

And the cowwwwws went homeeeeeeee
Or did theyyyy
如果要去除重复字符或将其压缩在一起,可以使用-s选项,因为都是字母,故使用[a-z]:
$tr -s "[a-z]"<cops.txt
And the cows went home
Or did they

12.4 删除空行

可使用-s来作这项工作.换行的八进制表示位\012,例:
$more plane.txt
and 0500 399999 2773888

or 093999 3766666

data 39


$tr -s "[\012]"<plane.txt

and 0500 399999 2773888
or 093999 3766666
data 39

12.5 大小写转换

除了删除控制字符,转换大小写是tr最常用的功能.为此需指定即将转换的小写字符[a-z]和转换结果[A-Z]

例1:tr从一个包含大小写字母的字符串中接受输入:

$echo "May Day,May Day,Going Down..."|tr "[a-z]" "[A-Z]"

MAY DAY,MAY DAY,GOING DOWN...


同样也可以使用字符类[:lower:]和[:upper:]
$echo "May Day,May Day,Going Down..."|tr "[:lower:]" "[:upper:]"
MAY DAY,MAY DAY,GOING DOWN...

$echo "MAY DAY,MAY DAY,GOING DOWN..."|tr "[A-Z]" "[a-z]"
may day,may day,going down...

或者也可以使用字符类[:upper:]和[:lower:]
$echo "MAY DAY,MAY DAY,GONING DOWN..."|tr "[:upper:]" "[:lower:]"
may day,may day,going down...

12.7 删除指定字符

偶尔会从下载文件中删除之包含字母或数字的列.需要结合使用-c和-s选项来完成此功能.
下面的文件包含一个星期的日程表.任务是从其中删 除所有数字,之保留日期.日期有大写,也有小写格式.因此需指定两个字符范围[a-z]和[A-Z],命令tr -cs "[a-z][A-Z]""[\012*]"将文件每行所有不包含在[a-z]或[A-Z]的字符串放在字符串1中并转换为一新行.-s选项表明压缩所有 新行,-c表明保留所有字母不动:

$more diary.txt

monday 10:50
Tuesday 15:30
wednesday 15:30
thurday 10:30
Friday 09:20

$tr -cs "[a-z][A-Z]" "[\012*]"<diary.txt

monday
Tuesday
wednesday
thurday
Friday

12.8 转换控制字符

tr的第一个功能就是转换控制字符,特别是从dos向UNIX下载文件时,忘记设置FTP关于回车换行转换的选项时更是如此.

下面是估计没有设置转换开关的一个文本文件,使用cat -v 显示控制字符.

$cat stat.tr
Boxes paper^^^^^^12^M
Clips metal^^^^^^50^M
Penciles-meduim^^^^^^10^M
^Z

猜想,'^^^^^^'是tab键,每一行以ctrl-M结尾,文件结尾ctrl-z,以下是改动方法:

使用-s选项,查看ASCII表,^的八进制代码是136,^M是015,tab键是011,^Z是032,下面按步骤完成最终功能.

用tab键替换^^^^^^,命令"\136""[\011*]",并输出到stat.tmp:

$tr -s "[\136]" "[\011*]" < stat.tr > stat.tmp
Boxes paper 12^M
Clips metal 50^M
Pencils-medium 10^M
^Z

用新行替换每行末尾的^M,并用\n去除^Z,输入文件来自stat.tmp:

$tr -s "[\015\032]" "\n" < stat.tmp


12.9 快速转换

如果要删除文件中^M,并代之以换行:
$tr -s "[\015]" "\n" < input_file
或者:
$tr -s "[\r]" "[\n]" < input_file
或者:
$tr -s "\r" "\n" < input_file

要删除所有的tab键,代之以空格:
$tr -s "[\011]" "[\040*]" < intput_file

例:替换/etc/passwd文件中所有冒号,代之以tab键,可以增加可读性:

$tr -s "[:]" "[\011]" < /etc/passwd

或:

$tr "[:]" "[\t]" < /etc/passwd

12.10 匹配多于一个字符

可以使用[character*n]格式匹配多于一个字符.例:
原文件:
$cat hdisk.txt

1293 hdisk3
4512 hdisk12
0000 hdisk5
4993 hdisk12
2994 hdisk7

替换第三行的0为星号:
$tr "[0*4]" "*" < hdisk.txt
1293 hdisk3
4512 hdisk12
**** hdisk5
4993 hdisk12
2994 hdisk7

或替换成百分号:
$tr "[0*4]" "%"<hdisk.txt
1293 hdisk3
4512 hdisk12
%%%% hdisk5
4993 hdisk12
2994 hdisk7

Blogged with Flock

Spice Girls..hoho

Blogged with Flock

Sunday, 4 November 2007

Gnome vs Kde in my mind

The result is GNOME for me.

  1. Gnome uses C, which is much easier for programming newbie as me. But there are a lot of bindings like Gtkmm for C++. When you are confident for high quality Object-oriented programming, you can think about moving away to other platform or X windows. While KDE uses C++, to start learning programming with this platform, in my mind is not good idea.
  2. Gnome if totally free with GPL. KDE's base is QT, which is free on Linux, but not for all the OS, such as MS Windows. So the troubles maybe are not far from you, especially when you want to do some commercial project programming with QT, at that time, maybe it's a little bit late to convert to Gnome. And also this problem make a lot of vendors keep away from it.
  3. Maybe the reason in 2), Gnome has a lot of supports and sponsors like IBM, Redhat, Sun. They can do whatever they like without any worry about legal issues. So with their supports and sponsors Gnome is growing much better and faster. As users and developers working in such a platform will benefit all the time, almost no worries about out of date or using or learning something without future.
  4. KDE is much like Windows, both the appearance and integration with embedded programs. I don't like windows environment in this way. Gnome is much better, almost nothing embedded compared to KDE, that's true that KDE brings a large mount of programs. But what Gnome provides is the stable and highly extensive base platform. I think this is why some many big companies like it, they can develop their own programs to attract users, for instance, Mozilla's Firefox, Sun's OpenOffice. Gnome is working as a free medias to put advertisements on it. This should be the proper way of how the media platform should work in, just like some many free newspapers in London.
  5. For my own favorite, I like Ubuntu, but Kubuntu are not so friendly and bring me a lot of debugging issues, such as gnome-system-monitor, Knetworkmanager and Kwallet always work improperly. So, just to use the default desktop environment is always right.

java Programming in Linux with gcj (basic)

The simple Java source code in Listing 1 can be compiled into Java bytecode with gcj -C HelloWorld.java and interpreted using gij HelloWorld. The same source code can be compiled into a native executable using gcj --main=HelloWorld -o HelloWorld HelloWorld.java and executed using ./HelloWorld. This article avoids including import and other trivial statements in Java code listings; see Resources for the full source files.

####################

## make executable
$ gcj -C HelloWorld.java
$ gij HelloWorld # to test if it works
$ gcj --main=HelloWorld -o HelloWorld HelloWorld.java
$ ./HelloWorld # to run it and test

## make executable jar (same way with in Windows)
$ gcj -c HelloWorld.class # compile Hello.class to Hello.o
$ jar cvf hi.jar HelloWorld.class # create a jar
## You got to include "manefest" file containing the class name of the "main()" method as:Main-class: your.package.Class_NAME.without_dot_class
# modify the "MANIFEST.MF", adding at the end:
Main-class: HelloWorld # Note: 1) there is a space after ':'. 2) there is NO empty line before the 'Main-class' line.


## make executable with jar
$ gcj -c HelloWorld.class # compile Hello.class to Hello.o
$ jar cvf hi.jar HelloWorld.class # create a jar
$ gcj -c hi.jar # compile hi.jar to hi.o
$ gcj --main=HelloWorld -o hi hi.o # link hi.o to hi; gcj accept all reasonable input files, such as .java files, .class files and .o files, even .jar files. Super!!!
$ ./hi # run hi
Hello, World!



Linux桌面两大阵营 GNOME与KDE的今生前世

虽然在商业方面存在竞争,GNOME与KDE两大阵营的开发者关系并没有变得更糟,相反他们都意识到支持对方的重要性—如果KDE和GNOME无法实现应用程序的共享,那不仅是巨大的资源浪费,而且将导致Linux出现根本上的分裂。
KDE 与GNOME是目前Linux/UNIX系统最流行的图形操作环境。从上个世纪九十年代中期至今,KDE和GNOME都经历了将近十年的漫漫历程,两者也 都从最初的设计粗糙、功能简陋发展到相对完善的阶段,可用性逼近Windows系统。图形环境的成熟也为Linux的推广起到至关重要的作用,尽管 Linux以内核健壮、节省资源和高质量代码著称,但缺乏出色的图形环境让它一直难以在桌面领域有所作为,导致Linux桌面应用一直处于低潮。如果大 家还有印象,一定会记得1999-2001年间Linux发展如火如荼,当时国内涌现出大量的Linux发行版厂商,但当用户发现Linux距离实用化还 有十万八千里的时候,Linux热潮迅速冷却。业界也对此一度灰心失望,其中一部分厂商因无法盈利迅速销声匿迹,另一部分厂商则不约而同将重点放在服务器 市场—与桌面市场形成鲜明对比的是,Linux以稳定可靠和低成本的优势在服务器领域获得了巨大的成功。
在一些Linux厂商放弃桌面化 努力的同时,国际开源社群却不断发展壮大,自由的理念吸引越来越多一流的程序员参与。与商业模式不同,自由软件程序员在开始时都只是利用业余时间开发自己 感兴趣的东西,并将其自由公开,这是一种不折不扣的贡献行为。尽管开发进度缓慢,但认同自由软件理念的开发者越来越多,一个个开源项目逐渐发展壮大。
在此期间一个被人忽视的重大事件就是商业巨头也积极参与进来,IBM、RedHat、SuSE、Ximian、 Novell、SUN、HP等商业公司都 直接介入各个开源项目,这些企业或者是将自身的成果免费提供给开源社群,或者直接派遣程序员参与项目的实际开发工作,例如SuSE(现已为Novell收 购)在KDE项目上做了大量的工作,RedHat、Ximian(现已为Novell收购)则全程参与Gnome 项目,IBM为Linux提供了大量的 基础性代码,是推进Linux进入服务器领域的主要贡献者,SUN公司则将StarOffice赠送给开源社群,并资助成立著名的 OpenOffice.org项目。这样,大量的自由软件程序员都可以从各个项目的基金会中领到薪水。在这一阶段,开源项目摆脱了程序员业余开发的模式, 而由高水平的专职程序员主导,这也成为各个自由软件项目的标准协作模式。与商业软件公司不同,自由软件项目的参与者都是首先为个人兴趣而工作,他们的共同 目标都是拿出品质最好的软件,在协作模式稳定成形之后,各个软件就进入到发展的快行道。进入2005年后,这些项目基本上都获得了丰硕的成果,其中最突出 的代表就是Firefox浏览器的成功,而作为两大图形环境,KDE和GNOME分别发展到3.5和2.12版本,两者的可用性完全可以媲美 Windows。更重要的是,开源社群的发展壮大为这些项目的未来发展奠定了坚实的基础:KDE项目将超越Windows作为自己的目标,力量更强大的 GNOME项目更是将开发目标定在超越Mac OS X的Aqua图形环境;Firefox则计划运用GPU的硬件资源来渲染图像,达到大幅度提高速度 的目的;OpenOffice.org在努力提升品质的同时奠定了开放文档格式标准。除了上述主要项目之外,我们也看到如Mplayer播放器、Xine 播放器、Thunderbird邮件客户端、SCIM输入平台等其他开源项目也在快速发展成熟之中,且几乎每一天都有新的项目在诞生。有意思的是,除了涉 及到软件开发外,还出现了为Linux设计视觉界面的开放协作项目,全球各地有着共同目标的艺术家通过互联网组织到一起,共同为Linux系统设计一流的 视觉界面、系统图标,而所有的自由软件程序员都有一个共同的目标,那就是开发出一流水准的软件提供给大众使用。这种基于挑战自我、带有浓烈精神色彩的软件 开发模式成为商业软件之外的另外一极。现在,微软面对的并不是那些只在业余时间鼓捣代码的程序员,而是分布在全球各地、数量庞大、且拥有一流技术水平的开 发者,这些开发者被有效地组织起来,形成一个个有序的协作团队,大量实力雄厚的商业公司在背后提供支持。虽然今天的Linux系统还无法在桌面领域被广为 接纳,但只需要两、三年时间,高速进化的Linux平台将可达到全面进军桌面的水准,也正是看到其中的机会,Novell、RedHat等重量级 Linux企业都不断在技术和市场推广方面加大投入,Linux 桌面化近在咫尺。
在介绍完必要的背景之后,我们将进入关于KDE与 GNOME的技术专题。如果你是刚刚接触Linux的新手,一定会对KDE和GNOME感到困惑不已—为何会有两个功能重复、操作习惯迥异的图形环境?这 不仅麻烦也耗费开发者精力。通过本文,你将获得清晰的答案。而更重要的是,我们将在本文中向大家介绍KDE与GNOME的实际水平、各自的优点和未来发展 趋势。如果你对Linux桌面应用有些兴趣,那么未来的 KDE/GNOME一定会让你感到震惊不已。
X Window打造桌面环境
在介绍KDE和Gnome之前,我们有必要先来介绍UNIX/Linux图形环境的概念。对一个习惯Windows的用户来说,要正确理解 UNIX/Linux的图形环境可能颇为困难,因为它与纯图形化Windows并没有多少共同点。Linux实际上是以UNIX为模板的,它继承了 UNIX内核设计精简、高度健壮的特点,无论系统结构还是操作方式也都与UNIX无异。简单点说,你可以将Linux看成是UNIX类系统中的一个特殊版 本。我们知道,微软Windows在早期只是一个基于 DOS的应用程序,用户必须首先进入DOS后再启动Windows进程,而从Windows 95 开始,微软将图形界面作为默认,命令行界面只有在需要的情况下才开启,后来的Windows 98/Me实际上也都隶属于该体系。但在 Windows 2000之后,DOS被彻底清除,Windows成为一个完全图形化的操作系统。但UNIX/Linux与之不同,强大的命令行界面始终 是它们的基础,在上个世纪八十年代中期,图形界面风潮席卷操作系统业界,麻省理工学院(MIT)也在1984年与当时的DEC公司合作,致力于在UNIX 系统上开发一个分散式的视窗环境,这便是大名鼎鼎的“X Window System”项目。不过,X Window(请注意不是X Windows)并 不是一个直接的图形操作环境,而是作为图形环境与UNIX系统内核沟通的中间桥梁,任何厂商都可以在X Window基础上开发出不同的GUI图形环境。 MIT和DEC的目的只在于为UNIX系统设计一套简单的图形框架,以使UNIX工作站的屏幕上可显示更多的命令,对于GUI的精美程度和易用程度并不讲 究,毕竟那时候能够熟练操作UNIX的都是些习惯命令行的高手,根本不在乎GUI存在与否。1986年, MIT正式发行X Window,此后它便成为 UNIX的标准视窗环境。紧接着,全力负责发展该项目的X协会成立,X Window进入了新阶段。与此同步,许多UNIX厂商也在X Window原型 上开发适合自己的UNIX GUI视窗环境,其中比较著名的有SUN与AT&T联手开发的“Open Look”、IBM主导下的OSF (Open Software Foundation,开放软件基金会)开发出的“Motif”。而一些爱好者则成立了非营利的XFree86组织,致力 于在X86系统上开发X Window,这套免费且功能完整的X Window很快就进入了商用UNIX系统中,且被移植到多种硬件平台上,后来的 Linux也直接从该项目中获益。当然,这些早期的X Window环境都设计得很简单,许多GUI元素模仿于微软的Windows,但X Window 拥有一个小小的创新:当鼠标指针移动到某个窗口时,该窗口会被自动激活,用户无需点击便能够直接输入,简化了用户操作—这个特性在后来的 KDE和 Gnome中也都得到完整的继承。
由于必须以UNIX系统作为基础,X Window注定只能成为UNIX上的一个应用,而不可能与操作 系统内核高度整合,这就使得基于X Window的图形环境不可能有很高的运行效率,但它的优点在于拥有很强的设计灵活性和可移植性。X Window从 逻辑上分为三层:最底层的X Server(X服务器)主要处理输入/输出信息并维护相关资源,它接受来自键盘、鼠标的操作并将它交给X Client (X客户端)作出反馈,而由X Client传来的输出信息也由它来负责输出;最外层的X Client则提供一个完整的GUI界面,负责与用户的直接交 互(KDE、Gnome都是一个X Client),而衔接X Server与X Client的就是“X Protocol(X通讯协议)”、它的任务 是充当这两者的沟通管道。尽管UNIX厂商采用相同的X Window,但由于终端的X Client并不相同,这就导致不同UNIX产品搭配的GUI界 面看起来非常不一样。

图1
X Window系统架构示意图 KDE项目的发起
MIT 的X Window推出之后就成为UNIX图形界面的标准,但在商业应用上分为两大流派:一派是以Sun公司领导的Open Look阵营,一派是 IBM/HP领导的OSF(Open Software Foundation)的Motif,双方经过多年竞争之后,Motif最终获得领先地位。不 过,Motif只是一个带有窗口管理器(Window- Manager)的图形界面库(Widget-Library),而非一个真正意义上的GUI界 面。经过协商之后IBM/HP与SUN决定将Motif与 Open Look整合,并在此基础上开发出一个名为“CDE (Common Desktop Environment) ”的GUI作为UNIX的标准图形界面。遗憾的是,Motif/CDE和UNIX系统的价格 都非常昂贵,而当时微软的Windows发展速度惊人并率先在桌面市场占据垄断地位,CDE则一直停留在UNIX领域提供给root系统管理员使用,直到 今天情况依然如此。

图2
KDE 1.0尽管设计粗糙,但它奠定了整个KDE项目的基础。
在上个世纪九十年代中期,以开源模式推进的Linux在开发者中已经拥有广泛的影响力。尽管X Window已经非常成熟,也有不少基于X Window 的图形界面程序,但它们不是未具备完整的图形操作功能就是价格高昂(如CDE),根本无法用于Linux系统中。如果Linux要获得真正意义上的突破, 一套完全免费、功能完善的GUI就非常必要。1996年10月,图形排版工具Lyx的开发者、一位名为Matthias Ettrich的德国人发起了 KDE(Kool Desktop Environment)项目,与之前各种基于X Window的图形程序不同的是,KDE并非针对系统管理员,它的 用户群被锁定为普通的终端用户,Matthias Ettrich希望KDE能够包含用户日常应用所需要的所有应用程序组件,例如Web浏览器、电子邮件 客户端、办公套件、图形图像处理软件等等,将 UNIX/Linux彻底带到桌面。当然,KDE符合GPL规范,以免费和开放源代码的方式运行。
KDE 项目发起后,迅速吸引了一大批高水平的自由软件开发者,这些开发者都希望KDE能够将Linux系统的强大能力与舒适直观的图形界面联结起来,创建最优秀 的桌面操作系统。经过艰苦卓绝的共同努力,KDE 1.0终于在1998年的7月12日正式推出。以当时的水平来说,KDE 1.0在技术上可圈可点,它 较好的实现了预期的目标,各项功能初步具备,开发人员已经可以很好地使用它了。当然,对用户来说,KDE 1.0远远比不上同时期的Windows 98 来得平易近人,KDE 1.0中大量的Bug更是让人头疼。但对开发人员来说,KDE 1.0的推出鼓舞人心,它证明了KDE项目开源协作的开发方式完全 可行,开发者对未来充满信心。有必要提到的是,在KDE 1.0版的开发过程中,SuSE、Caldera等Linux商业公司对该项目提供资金上的支 持,在1999年,IBM、Corel、RedHat、富士通-西门子等公司也纷纷对KDE项目提供资金和技术支持,自此KDE项目走上了快速发展阶段并 长期保持着领先地位。但在2004年之后,GNOME不仅开始在技术上超越前者,也获得更多商业公司的广泛支持,KDE丧失主导地位,其原因就在于KDE 选择在Qt平台的基础上开发,而Qt在版权方面的限制让许多商业公司望而却步。
Qt是一个跨平台的C++图形用户界面库,它是挪威 TrollTech公司的产品。基本上,Qt同X Window上的 Motif、Open Look、GTK等图形界面库和Windows平台上的 MFC、OWL、VCL、ATL是同类型的东西,但Qt具有优良的跨平台特性(支持Windows、Linux、各种UNIX、OS390和QNX 等)、面向对象机制以及丰富的API,同时也可支持2D/3D渲染和OpenGL API。在当时的同类图形用户界面库产品中,Qt的功能最为强大, Matthias Ettrich在发起KDE项目时很自然选择了Qt作为开发基础,也正是得益于Qt的完善性,KDE的开发进展颇为顺利,例如 Netscape5.0在从 Motif移植到Qt平台上仅仅花费了5天时间。这样,当KDE 1.0正式发布时,外界看到的便是一个各项功能基本具备的 GUI操作环境,且在后来的发展中,Qt/KDE一直都保持领先优势。有必要提到的是, TrollTech公司实质性参与了KDE项目,如前面提到 Netscape 5.0 的移植工作就是由TrollTech的程序员完成,而KDE工程的发起者、Matthias Ettrich本人也在1998 年离开学术界加入TrollTech,并一直担任该公司的软件开发部主管,因此TrollTech公司对于KDE项目拥有非常强的影响力(当然不能说绝对 掌握,毕竟KDE开发工作仍然是由自由程序员协作完成的)。我们前面提到,KDE采用GPL规范进行发行,但底层的基础 Qt却是一个不遵循GPL的商业 软件,这就给KDE上了一道无形的枷锁并带来可能的法律风险。一大批自由程序员对KDE项目的决定深为不满,它们认为利用非自由软件开发违背了GPL的精 神,于是这些GNU的狂热信徒兵分两路:其中一部分人去制作Harmonny,试图重写出一套兼容Qt的替代品,这个项目虽然技术上相对简单,但却没有获 得KDE项目的支持;另一路人马则决定重新开发一套名为“GNOME(GNU Network Object Environment)”的图形环境来替 代KDE,一场因为思想分歧引发的GUI之战开始了。

图3
Qt是整个KDE的基础,它采用双重授权。GNOME与KDE交替发展
GNOME 项目于1997年8月发起,创始人是当时年仅26岁的墨西哥程序员Miguel De Icaza。关于GNOME的名称有一个非常有趣的典故: Miguel到微软公司应聘时对它的ActiveX/COM model颇有兴趣,GNOME(Network Object Model )的名称便从 此而来。GNOME选择完全遵循GPL的GTK图形界面库为基础,因此我们也一般将GNOME和KDE两大阵营称为GNOME/GTK和 KDE/Qt。 与Qt基于C++语言不同,GTK采用较传统的C语言,虽然C语言不支持面向对象设计,看起来比较落后,但当时熟悉C语言的开发者远远多于熟悉C++的开 发者。加之GNOME/GTK完全遵循GPL版权公约,吸引了更多的自由程序员参与,但由于KDE先行一步,且基础占优势,一直都保持领先地位。1999 年3月,GNOME 1.0在匆忙中推出,稳定性奇差无比,以至于许多人笑称GNOME 1.0还没有KDE 1.0 Alpha稳定,而同期的 KDE 1.1.2无论在稳定性还是功能上都远胜于GNOME,直到10月份推出的GNOME 1.0.55版才较好解决了稳定性问题,给GNOME重新 赢回声誉。由于思想分歧,当时GNOME的开发者与KDE的开发者在网络上吵得天翻地覆,几乎达到相互仇视的地步。但不管怎么说,GNOME都跌跌撞撞迈 出了第一步,尽管那时KDE几乎是所有Linux发行版默认的桌面环境。

图5
KDE2.0拥有丰富的应用软件,实力明显超过GNOME。
GNOME 的转机来自于商业公司的支持。当时Linux业界的老大RedHat很不喜欢KDE/Qt的版权,在GNOME项目发起后RedHat立刻对其提供支持。 为了促进GNOME的成熟,RedHat甚至专门派出几位全职程序员参与GNOME的开发工作,并在1998年1月与GNOME项目成员携手成立了 RedHat高级开发实验室。1999年4月,Miguel与另一名GNOME项目的核心成员共同成立Helix Code公司为GNOME提供商业支 持,这家公司后来更名为Ximian,它事实上就成为GNOME项目的母公司,GNOME平台上的Evolution 邮件套件便出自该公司之手。进入 2000年之后,一系列重大事件接连发生,首先,一批从苹果公司出来的工程师成立Eazel公司,为GNOME设计用户界面和Nautilus(鹦鹉螺) 文件管理器。同年8月,GNOME基金会在Sun 、RedHat、Eazel、Helix Code(Ximian)的共同努力下正式成立,该基金会负 责GNOME项目的开发管理以及提供资金,Miguel本人则担任基金会的总裁。此时, GNOME获得许多重量级商业公司的支持,如惠普公司采用 GNOME作为HP-UX系统的用户环境,SUN则宣布将StarOffice套件与GNOME 环境相整合,而GNOME也将选择 OpenOffice.org作为办公套件,IBM公司则为GNOME共享了SashXB极速开发环境。同时, GNOME基金会也决定采用 Mozilla作为网页浏览器。KDE阵营也毫不示弱,在当年10月份推出万众瞩目的KDE 2.0。KDE 2.0堪称当时最庞大的自由软件,除了 KDE平台自身外,还包括Koffice办公套件、Kdevelop集成开发环境以及Konqueror网页浏览器。尽管这些软件都还比较粗糙,但 KDE 2.0已经很好实现了Matthias Ettrich成立KDE项目的目标。也是在这个月,TrollTech公司决定采用GPL公约来发行 Qt的免费版本,希望能够以此赢得开发者的支持。这样,Qt实际上就拥有双重授权:如果对应的Linux发行版采用免费非商业性的方式进行发放,那么使用 KDE无须向TrollTech交纳授权费用;但如果Linux发行版为盈利性的商业软件,那么使用KDE时必须获得授权。由于TrollTech是商业 公司且一直主导着KDE的方向,双许可方式不失为解决开源与盈利矛盾的好办法。TrollTech宣称,双许可制度彻底解决了KDE在GPL公约方面的问 题,但RedHat并不喜欢,RedHat不断对 GNOME项目提供支持,希望它能够尽快走向成熟,除RedHat之外的其他Linux厂商暂时都站在 KDE这一边,但他们同时也在发行版中捆绑了 GNOME桌面。
在2001-2002年,火热一时的Linux运动开始陷入低潮期,几乎 所有的厂商都发现桌面Linux版本不可能盈利,而易用性的不足也让业界不看好Linux进入桌面的前途。但在服务器市场,Linux发展势头非常迅猛, 直接对UNIX和Windows Server造成威胁。不过,秉承自由软件理念的开发者们并不理会外界的论调,他们一直将Linux桌面化作为目标, GNOME项目和KDE项目都在这期间获得完善发展。2001年4月,GNOME 1.4发布,它修正了之前版本的Bug,功能也较为完善,但在各方面与 KDE依然存在差距;同年8月,KDE发展到2.2版本。2002年4月,KDE跳跃到3.0版本,它以Qt 3.0为基础,各项功能都颇为完备,具备卓 越的使用价值;两个月后,GNOME阵营也推出2.0版本,它基于更完善的GTK 2.0图形库。进入到2003年后,KDE与GNOME进入真正意义上 的技术较量。1月份,KDE 3.1推出,而GNOME 2.4则在随后的2月份推出,两大平台都努力进行自我完善。也是在这一年,Linux商业界出现 一系列重大的并购案:1月份,Novell公司宣布收购德国的SuSE Linux,而SuSE Linux是地位仅次于RedHat的全球第二大 Linux商业企业;8月,Novell接着将GNOME的母公司Ximian收归旗下。这两起并购案让 Novell成为实力与RedHat不相上下的 强大Linux企业,而Novell和RedHat就成为能够影响Linux未来的两家企业。在图形环境上,SuSE一向选择KDE,并在KDE身上投入 相当多的精力,在被Novell并购后,SuSE的桌面发行版尽管还侧重于KDE,但同样不喜欢Qt授权的Novell已经开始向GNOME迁移。

图4
GTK库是GNOME项目的基础,它完全采用GPL授权因此获得广泛支持。GNOME获得商业公司的支持
进入2004年后,KDE与GNOME依然保持快速发展,KDE阵营分别在2月份和8月份推出3.2、3.3版本,GNOME则在3月和9月推出2.6和 2.8,两者的版本升级步幅旗鼓相当。到3.3版本的KDE已经非常成熟,它拥有包括KOffice、Konqueror浏览器、Kmail套件、 KDE 即时消息在内的一大堆应用软件,且多数都达到可用标准,功能上完全不亚于Windows 2000。而GNOME更是在此期间高速发展, GNOME 2.8版本的水准完全不逊于KDE 3.3,而且此时两者的技术特点非常鲜明:GNOME讲究简单、高效,运行速度比KDE更快;KDE则拥 有华丽的界面和丰富的功能,使用习惯也与微软 Windows较类似。商业支持方面,RedHat还是GNOME的铁杆支持者,IBM、SUN、 Novell、HP等重量级企业也都选择GNOME,而 KDE的主要支持者暂时为SuSE、Mandrake以及中科红旗、共创开源在内的国内发行商。 2005年,厚积薄发的GNOME开始全面反超,3月份的 2.10、9月份的2.12让GNOME获得近乎脱胎换骨的变化,加之 OpenOffice.org 2.0、Firefox 1.5等重磅软件的出台让GNOME如虎添翼;KDE方面则分别在3月和11月推出3.4和 3.5,其中KDE 3.5也逼近完美境地,我们认为它的水平与GNOME 2.12不相伯仲。但KDE在商业支持方面每况愈下,Novell在11月宣 布旗下所有的商业性发行版将使用GNOME作为默认桌面(仍会对KDE Libraries提供支持),SuSE Linux桌面版则会对KDE与 GNOME提供同等支持,而社区支持的OpenSuSE仍将使用KDE体系—但谁都明白GNOME将成为Novell的重心,KDE只是活跃在免费的自由 发行版中。

图7
KDE3.5可实现半透明和阴影效果,界面华丽、软件丰富。
到这里,我们发现一个颇富戏剧性的结局:致力于商业化的KDE反而失去了重量级商业企业的支持,尽管一些中小规模的Linux企业因技术能力问题将继续支 持KDE,但它的商业前途有限。而遵循GPL、完全不以商业化为目的的GNOME反而在该领域大获成功。许多Linux发烧友都不明白为什么优秀的 KDE 会受到如此待遇,其实道理非常简单—没有哪一家重量级企业喜欢受制于人,也许KDE的Qt不需要很多授权费,但谁知道TrollTech公司以后 会不会漫天要价?既然有免费的GNOME可以选择,那为什么不呢?基于此种理由,RedHat、Novell两家最大的Linux企业和SUN都采用 GNOME,而它们对GNOME的鼎力支持也让该项目可拥有足够多的技术保证,为今后的高速发展奠定坚实的基础。需要纠正一个可能的误解,虽然 Novell收购了 Ximian,但RedHat并没有受到太大影响,双方对GNOME的贡献都是相互共享的,因为GNOME以GPL自由版权公约发 行,合作即共赢。至于 KDE项目,虽然它失去这些商业巨头的支持,但没有能力转换桌面的中小Linux厂商将继续追随KDE,而且在非商业的社区 Linux发行版中,KDE依然有强大的生命力。

图6
GNOME 1.4解决了稳定性问题,功能初步完善。
虽然在商业方面存在竞争,GNOME与KDE两大阵营的开发者关系并没有变得更糟,相反他们都意识到支持对方的重要性。如果KDE和GNOME无法实现应 用程序的共享,那不仅是巨大的资源浪费,而且将导致Linux出现根本上的分裂。事实上,无论是GNOME的开发者还是KDE的开发者,他们都有着共同的 目标,就是为Linux开发最好的图形环境,只是因为理念之差而分属不同的阵营。KDE与GNOME的商业竞争对开发者们其实没有任何利益影响(只有 TrollTech会受影响),基于共同的目的,KDE与GNOME阵营大约从2003年开始逐渐相互支持对方的程序—只要你在KDE环境中安装 GTK 库,便可以运行GNOME的程序,反之亦然。经过两年多的努力,KDE和GNOME都已经实现高度的互操作性,两大平台的程序都是完全共享的,例 如你可以在GNOME中运行Konqueror浏览器、Koffice套件,也可以在KDE中运行Evolution和OpenOffice.org,只 不过执行本地程序的速度和视觉效果会好一些。在未来一两年内,KDE和GNOME将进行更高等级的融合,但两者大概永远都不会合为一体—GNOME还是 GNOME,KDE也还是KDE。或许你觉得这是浪费开发资源而且很可能让用户无从选择,但我们告诉你这就是Linux,它与Windows和 Mac OS X有着绝然不同的文化。更何况全球有越来越多自由软件开发者(所以不必担心浪费开发资源),Linux用户的使用偏好也不可能总是相同,保 持两个并行发展的图形环境项目没有什么不妥。至于GNOME项目和KDE项目的开发者们,曾经因为理念不同而吵得天翻地覆,但他们现在尽释前嫌,因为所有 人都意识到,他们其实彼此需要,团结在一起可以让他们在硬件厂商面前有更大的发言权,从而促使厂商在推出Windows驱动的同时也提供相应的Linux 版本,而且彼此可以相互借鉴优秀的设计,确保Linux拥有一个最出色的图形桌面环境。

图8
GNOME 2.12保持惯有的简洁和高效 KDE与GNOME走向融合
2006 年,GNOME与KDE都站在一个全新的起点,获得商业公司和更多自由程序员支持的GNOME踌躇满志,将超越的目光放在Mac OS X系统。也许你认 为Windows Vista的半透明和三维界面将Linux远远抛在后面,那么我们告诉你这是绝对的误解,GNOME目前已经可以实现类似的效果, Novell在前几个月就向外界作过详细的演示。当前的KDE也可支持相当不错的半透明和阴影特效,技术上毫不落后于GNOME。现在,GNOME项目朝 向革命性的3.0版本迈进,KDE则致力于开发同样有重大技术变革的4.0,这两个成果大概在2007年可进入现实,届时Linux系统将具备更卓越的可 用性。也就是说, Linux桌面应用的全面铺开指日可待,而除了开发者和厂商的努力外,如何向企业和个人用户推广以及提供培训将是厂商要考虑的主要问 题,我们今天恰好站在这样的一道门槛上。

command-line activate wireless

1.
ndiswrapper -i XXXXX
ndiswrapper -ma
modprobe ndiswrapper
2.
iwconfig
3.
iwlist wlan0 scan
4.
sudo iwconfig wlan0 essid XXXXXXXXXX
sudo iwconfig wlan0 key XXXXXXXXXXX(for normal wep:64bit,open mode security, otherwise s:XXXXX for ansi code)
dhclient [wlan0] (to activate the wireless card)

5.
ifconfig (to check whether get the IP properly or not)
ping somewhere to test
P.S. Note: the networkmanager looks do not change at all. Because it did nothing, and not reflect the status of the network.

Saturday, 3 November 2007

Nokia N810 with Linux

clipped from linux.wordpress.com

Nokia N810 - 3rd Gen Internet Tablet Running Linux

Nokia took another long step today with the N810, the third generation of its ‘Internet tablet’ line which began with the launch of the N770 in November 2005 and was followed by the N800 in January this year.

Like its predecessors, the N810 is powered by Nokia’s own Internet Tablet OS, also known as Maemo. This open source build is based on Debian and is topped by the same ‘Hildon’ user interface layer as will be featured on the Ubuntu Mobile OS used by Intel’s mobile Internet devices around the middle of 2008. The N810 runs the latest Internet Tablet OS 2008 release, aka Maemo 4.0 ‘Chinook’.

  • 2GB internal storage (not including memory cards), ships with maps for use with GPS
  • Has WiFi (802.11b/g), does not have WiMAX
  • 400MHz OMAP 2420 CPU, 128MB RAM, 256MB ROM
  • Runs Nokia’s Linux Maemo interface
  • Friday, 2 November 2007

    Debian repository - sid

    The code names of Debian releases are names of characters from the film Toy Story. The unstable, development distribution is nicknamed sid, after the emotionally unstable next-door neighbour boy who destroyed toys on a regular basis.

    Where do these codenames come from?

    So far they have been characters taken from the movie "Toy Story" by Pixar.

    • buzz (Buzz Lightyear) was the spaceman,

    • rex was the tyrannosaurus,

    • bo (Bo Peep) was the girl who took care of the sheep,

    • hamm was the piggy bank,

    • slink (Slinky Dog (R)) was the toy dog,

    • potato was, of course, Mr. Potato (R),

    • woody was the cowboy,

    • sarge was the sergeant of the Green Plastic Army Men,

    • etch was the toy blackboard (Etch-a-Sketch (R)),

    • lenny was the binoculars.

    • sid was the boy next door who destroyed toys.


    Sid repository is dangerous, but it's really powerful for developers. Almost you can find any lib packages here.
    ####################################
    deb http://ftp.de.debian.org/debian sid main ##
    ####################################
    the gpg key:
    when you run apt-get update, you will be told error about gpg key:A70DAF536070D3A1
    run:
    ####################################
    sudo gpg --keyserver wwwkeys.eu.pgp.net --recv-keys 07DC563D1F41B907
    sudo apt-key add ~/.gnupg/pubring.gpg
    ###################################################




    From here you can find a lot of libs which are really difficult to get from those stable repositories.

    Thursday, 1 November 2007

    Recovery when you remove some packages by mistake

    Sometime when you install some new package, it will remove all its conflict packages, before this, you will be notified. But most of the people like me don't want to read all of the long-winded words every time. So sooner or later you will make such mistake.

    Yes, I did. when I install some package about pulseaudio, which comes with Fedora 8 next week, one of the plugins conflicts with the current system sound server, so it removed the esound server and all relative packages (including all the Gnome and Kde package). I can not log in the X windows environment.

    ########################################

    Here are the solution:
    1.
    a. find the synaptic history log files, which are stored in /root/.synaptic/log/, sorted by date. You can not use 'cd' to browse the folder, so you must use 'ls' and 'cp' to get the file.
    b. remove some contents of the file, just leave the removed packages.
    c-1. using vi, input such command when you click':', '1,$j'. Here j can make all the lines in the file into 1 line.
    c-2. (another method) tr -c "[a-z][A-Z]" " " < thefile
    d. At the beginning of the file, add 'sudo apt-get install -y'. Here 'y' force every installation continue without prompt.
    e. sh+the file. everything start. when it finished. your system recovered.

    2.
    at step 1.c. using 'sed' to add 'sudo apt-get install -y' before each line. it works, but two slow and a lot of repeat work by computer.

    Tuesday, 30 October 2007

    quick luaunch

    Quicksilver for Mac OSX

    Katapult for Linux KDE (alt+space)

    Gnome-launch-box for Linux Gnome

    1. Start gconf-editor from a terminal
    2. Locate /apps/metacity/keybindings_commands in the treeview
    3. Set a command, for example command_1 to gnome-launch-box
    4. Go to /apps/metacity/global_keybindings
    5. Setup the keybinding you want for running GNOME Launch Box as run_command_1

    Friday, 26 October 2007

    nice (Unix)

    From Wikipedia, the free encyclopedia

    Jump to: navigation, search

    nice (IPA pronunciation: /naɪs/) is a command found on UNIX and other POSIX-like operating systems such as Linux. nice directly maps to a kernel call of the same name. For a given process, it changes the priority in the kernel's scheduler. A nice value of −20 is the highest priority and 19 is the lowest priority. The default nice value for processes is inherited by its parent process, usually 0.

    Nice becomes useful when several processes are demanding more resources than the CPU can provide. In this state, a higher priority process will get a larger chunk of the CPU time than a lower priority process. If the CPU can deliver more resources than the processes are requesting, then even the lowest priority process can get up to 99% of the CPU. Only the superuser (root) may set the nice value to a smaller (higher priority) value.

    There is also a renice command, which is used to change the priority of a process that's already running.

    The exact mathematical effect of setting a particular niceness value for a process depends on the details of how the scheduler is designed on that implementation of UNIX. A particular operating system's scheduler will also have various heuristics built into it, e.g., to favor processes that are mostly I/O-bound over processes that are CPU-bound. As a simple example, when two otherwise identical CPU-bound processes are running simultaneously on a single-CPU Linux system, each one's share of the CPU time will be proportional to 20-p, where p is the process's priority. Thus a process run with nice +15 will receive 1/4 of the CPU time allocated to a normal-priority process: (20-15)/(20-0)=1/4. On the BSD 4.x scheduler, on the other hand, the ratio in the same example is more like ten to one.

    Contents

    [hide]

    [edit] Language bindings

    [edit] C

    nice
    getpriority(2)

    [edit] Perl

     use POSIX ();
    POSIX::nice(7); # like the renice shell command; increase niceness level by 7
    my $prio = getpriority(0,0); # like the C function

    [edit] See also

    [edit] External links

    Linux Memory Usage

    A lot of people made good points in the comments section of my last posting (Understanding memory usage on Linux). Here are some of the general ideas that were mentioned:

    (1) Several comments noted that non-x86 hardware has a different approach to shared memory between processes. This is true; some architectures do not handle shared memory in the same way as x86. To be honest, I don't know which platforms those are, so I'm not going to even try to list them. Thus, my previous post should be taken with a big grain of salt if you're working on a non-x86 platform.

    (2) Many people also noted that this shared library feature of Linux isn't some fancy new thing, which is completely true. Microsoft Windows platforms undoubtedly have the same basic sharing feature, just like any full-featured modern operating system. My post only addressed Linux because, to be honest, I'm a Linux-centric kind of person.

    (3) Yes, I did commit the sin of using "it's" instead of "its". To all of the English majors in the audience, I offer my most sincere apology.

    (4) A few comments mentioned the memory size of Firefox. I must admit that I began this article with Firefox instead of KEdit as the primary example, but I was forced to switch to KEdit when I saw how big Firefox's private/writeable size was; KEdit illustrated my point much better. :)

    (5) If the word "marginal" that I used confused anyone, then feel free to just mentally replace it with the word "incremental".

    Thanks to everyone that commented on the posting; part of my reason for writing it was to see what other people thought, as other people usually know more than I do about any given subject.

    Saturday, February 04, 2006

    Understanding memory usage on Linux

    This entry is for those people who have ever wondered, "Why the hell is a simple KDE text editor taking up 25 megabytes of memory?" Many people are led to believe that many Linux applications, especially KDE or Gnome programs, are "bloated" based solely upon what tools like ps report. While this may or may not be true, depending on the program, it is not generally true -- many programs are much more memory efficient than they seem.

    What ps reports
    The ps tool can output various pieces of information about a process, such as its process id, current running state, and resource utilization. Two of the possible outputs are VSZ and RSS, which stand for "virtual set size" and "resident set size", which are commonly used by geeks around the world to see how much memory processes are taking up.

    For example, here is the output of ps aux for KEdit on my computer:

    USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
    dbunker 3468 0.0 2.7 25400 14452 ? S 20:19 0:00 kdeinit: kedit

    According to ps, KEdit has a virtual size of about 25 megabytes and a resident size of about 14 megabytes (both numbers above are reported in kilobytes). It seems that most people like to randomly choose to accept one number or the other as representing the real memory usage of a process. I'm not going to explain the difference between VSZ and RSS right now but, needless to say, this is the wrong approach; neither number is an accurate picture of what the memory cost of running KEdit is.

    Why ps is "wrong"
    Depending on how you look at it, ps is not reporting the real memory usage of processes. What it is really doing is showing how much real memory each process would take up if it were the only process running. Of course, a typical Linux machine has several dozen processes running at any given time, which means that the VSZ and RSS numbers reported by ps are almost definitely "wrong". In order to understand why, it is necessary to learn how Linux handles shared libraries in programs.

    Most major programs on Linux use shared libraries to facilitate certain functionality. For example, a KDE text editing program will use several KDE shared libraries (to allow for interaction with other KDE components), several X libraries (to allow it to display images and copy and pasting), and several general system libraries (to allow it to perform basic operations). Many of these shared libraries, especially commonly used ones like libc, are used by many of the programs running on a Linux system. Due to this sharing, Linux is able to use a great trick: it will load a single copy of the shared libraries into memory and use that one copy for every program that references it.

    For better or worse, many tools don't care very much about this very common trick; they simply report how much memory a process uses, regardless of whether that memory is shared with other processes as well. Two programs could therefore use a large shared library and yet have its size count towards both of their memory usage totals; the library is being double-counted, which can be very misleading if you don't know what is going on.

    Unfortunately, a perfect representation of process memory usage isn't easy to obtain. Not only do you need to understand how the system really works, but you need to decide how you want to deal with some hard questions. Should a shared library that is only needed for one process be counted in that process's memory usage? If a shared library is used my multiple processes, should its memory usage be evenly distributed among the different processes, or just ignored? There isn't a hard and fast rule here; you might have different answers depending on the situation you're facing. It's easy to see why ps doesn't try harder to report "correct" memory usage totals, given the ambiguity.

    Seeing a process's memory map
    Enough talk; let's see what the situation is with that "huge" KEdit process. To see what KEdit's memory looks like, we'll use the pmap program (with the -d flag):

    Address Kbytes Mode Offset Device Mapping
    08048000 40 r-x-- 0000000000000000 0fe:00000 kdeinit
    08052000 4 rw--- 0000000000009000 0fe:00000 kdeinit
    08053000 1164 rw--- 0000000008053000 000:00000 [ anon ]
    40000000 84 r-x-- 0000000000000000 0fe:00000 ld-2.3.5.so
    40015000 8 rw--- 0000000000014000 0fe:00000 ld-2.3.5.so
    40017000 4 rw--- 0000000040017000 000:00000 [ anon ]
    40018000 4 r-x-- 0000000000000000 0fe:00000 kedit.so
    40019000 4 rw--- 0000000000000000 0fe:00000 kedit.so
    40027000 252 r-x-- 0000000000000000 0fe:00000 libkparts.so.2.1.0
    40066000 20 rw--- 000000000003e000 0fe:00000 libkparts.so.2.1.0
    4006b000 3108 r-x-- 0000000000000000 0fe:00000 libkio.so.4.2.0
    40374000 116 rw--- 0000000000309000 0fe:00000 libkio.so.4.2.0
    40391000 8 rw--- 0000000040391000 000:00000 [ anon ]
    40393000 2644 r-x-- 0000000000000000 0fe:00000 libkdeui.so.4.2.0
    40628000 164 rw--- 0000000000295000 0fe:00000 libkdeui.so.4.2.0
    40651000 4 rw--- 0000000040651000 000:00000 [ anon ]
    40652000 100 r-x-- 0000000000000000 0fe:00000 libkdesu.so.4.2.0
    4066b000 4 rw--- 0000000000019000 0fe:00000 libkdesu.so.4.2.0
    4066c000 68 r-x-- 0000000000000000 0fe:00000 libkwalletclient.so.1.0.0
    4067d000 4 rw--- 0000000000011000 0fe:00000 libkwalletclient.so.1.0.0
    4067e000 4 rw--- 000000004067e000 000:00000 [ anon ]
    4067f000 2148 r-x-- 0000000000000000 0fe:00000 libkdecore.so.4.2.0
    40898000 64 rw--- 0000000000219000 0fe:00000 libkdecore.so.4.2.0
    408a8000 8 rw--- 00000000408a8000 000:00000 [ anon ]
    ... (trimmed) ...
    mapped: 25404K writeable/private: 2432K shared: 0K

    I cut out a lot of the output; the rest is similar to what is shown. Even without the complete output, we can see some very interesting things. One important thing to note about the output is that each shared library is listed twice; once for its code segment and once for its data segment. The code segments have a mode of "r-x--", while the data is set to "rw---". The Kbytes, Mode, and Mapping columns are the only ones we will care about, as the rest are unimportant to the discussion.

    If you go through the output, you will find that the lines with the largest Kbytes number are usually the code segments of the included shared libraries (the ones that start with "lib" are the shared libraries). What is great about that is that they are the ones that can be shared between processes. If you factor out all of the parts that are shared between processes, you end up with the "writeable/private" total, which is shown at the bottom of the output. This is what can be considered the incremental cost of this process, factoring out the shared libraries. Therefore, the cost to run this instance of KEdit (assuming that all of the shared libraries were already loaded) is around 2 megabytes. That is quite a different story from the 14 or 25 megabytes that ps reported.

    What does it all mean?
    The moral of this story is that process memory usage on Linux is a complex matter; you can't just run ps and know what is going on. This is especially true when you deal with programs that create a lot of identical children processes, like Apache. ps might report that each Apache process uses 10 megabytes of memory, when the reality might be that the marginal cost of each Apache process is 1 megabyte of memory. This information becomes critial when tuning Apache's MaxClients setting, which determines how many simultaneous requests your server can handle (although see one of my past postings for another way of increasing Apache's performance).

    It also shows that it pays to stick with one desktop's software as much as possible. If you run KDE for your desktop, but mostly use Gnome applications, then you are paying a large price for a lot of redundant (but different) shared libraries. By sticking to just KDE or just Gnome apps as much as possible, you reduce your overall memory usage due to the reduced marginal memory cost of running new KDE or Gnome applications, which allows Linux to use more memory for other interesting things (like the file cache, which speeds up file accesses immensely).

    Wednesday, 24 October 2007

    kde initial decoration - kpersonalizer

    You can decorate your KDE very easily when you first activate it. All this is depending on the command of "kpersonalizer". Namely, when you want to change the look and feel rapidly, while not tweak hundreds of KDE options, just run it in konsole (terminal).

    Stop Gnome Keyring Prompt For A Password

    Keyring in Gnome.
    clipped from www.ossgeeks.co.uk

    What is Gnome Keyring Manager

    GNOME keyring manager stores passwords such as WEP into an encrypted format that can be used over and over again when required by the user.

    Bring on Libpam-Keyring

    There is hope yet! :-) the libpam-keyring library can stop GNOME Keyring-manager prompting for a password when you access your protected wireless network. Install libpam-keyring by doing the following command in the terminal:-

    sudo apt-get install libpam-keyring

    Open the the gdm file:-

    gksudo gedit /etc/pam.d/gdm

    Add the following line to the end:-

    @include common-pamkeyring

    Save the file and exit. I should also point out that your GNOME Keyring-manager password MUST be the same as your log on (root). To ensure this go to the GNOME Keyring-manager at the “System > Administration” menu and delete your keyring, so nothing exists and reboot. You should now see no password prompt for your wireless network ;-).

    Monday, 22 October 2007

    packages needed for Linux

    Wine

    libdvdcss2
    w32codecs

    ubuntu-restricted-extras (this one can solve mp3 and other third party stuff)
    amarok (this will install needed codecs for mp3:libxine,
    gstreamer0.10-ffmpeg)

    xine(totem-xine)

    nautilus-open -terminal

    ndiswrapper

    libpam-gnome-keyring(when the user login, make the keyringmanager unlocked)

    stardict

    vnc

    konquer/opera

    gedit-plugins(a lot of plugins for c/c++/java/latex etc.)

    lyx(for latex and other formal document writing)

    lynx(command-line web browser)
    cmus/music123(command-line music player, sometime the mcop directory is needed to be created manually by ''mkdir -p $HOME/.kde/socket-$HOSTNAME/mcop'')

    #####################
    eclipse(+cdt,pydev)

    texmaker(+texlive-latex)

    build-essential
    gcj

    firestarter(firewall management program)

    Chinese

    envy (for graphical cards installation)

    ######################
    samba(smbpasswd -a user, here this user must exist in the system users database)

    gnome-rdp



    Friday, 19 October 2007

    ndiswrapper in Ubuntu Gutsy

    Ndiswrapper, a windows driver simulation for linux, in Ubuntu Gutsy seems there is a bug about automatically loaded when you did all the commands like this:

    sudo apt-get install ndiswrapper
    sudo ndiswrapper -i XXXXX.inf #installation of the drivers
    sudo modprobe ndiswrapper

    In Ubuntu Feisty 7.04, When you finish these commands, the light on your pcmcia wireless card will be turned on, and restart your computer, the wireless card will be loaded automatically when Ubuntu booting. But Gutsy not.

    Nothing happened, unless you run:

    sudo modprobe ndiswrapper


    No worries, here are two methods to solve it.

    1. put "ndiswrapper" in the /etc/modules.

    P.S., some wireless
    pcmcia card using prism54 will be loaded automatically without ndiswrapper by Ubuntu, you can stop it by this:

    Put "blacklist prism54" in the /etc/modprobe.d/blacklist.

    2. Just run the command "sudo ndiswrapper -ma", which will write the relative module to /etc/modprobe.d/, same effect with above.

    Repositories in Ubuntu 7.10

    # deb cdrom:[Kubuntu 7.10 _Gutsy Gibbon_ - Release i386 (20071016.1)]/ gutsy main restricted
    # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
    # newer versions of the distribution.

    deb http://gb.archive.ubuntu.com/ubuntu/ gutsy main restricted
    deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy main restricted

    ## Major bug fix updates produced after the final release of the
    ## distribution.
    deb http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates main restricted
    deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates main restricted

    ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
    ## team, and may not be under a free licence. Please satisfy yourself as to
    ## your rights to use the software. Also, please note that software in
    ## universe WILL NOT receive any review or updates from the Ubuntu security
    ## team.
    deb http://gb.archive.ubuntu.com/ubuntu/ gutsy universe
    deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy universe
    deb http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates universe
    deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates universe

    ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
    ## team, and may not be under a free licence. Please satisfy yourself as to
    ## your rights to use the software. Also, please note that software in
    ## multiverse WILL NOT receive any review or updates from the Ubuntu
    ## security team.
    deb http://gb.archive.ubuntu.com/ubuntu/ gutsy multiverse
    deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy multiverse
    deb http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates multiverse
    deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy-updates multiverse

    ## Uncomment the following two lines to add software from the 'backports'
    ## repository.
    ## N.B. software from this repository may not have been tested as
    ## extensively as that contained in the main release, although it includes
    ## newer versions of some applications which may provide useful features.
    ## Also, please note that software in backports WILL NOT receive any review
    ## or updates from the Ubuntu security team.
    deb http://gb.archive.ubuntu.com/ubuntu/ gutsy-backports main restricted universe multiverse
    deb-src http://gb.archive.ubuntu.com/ubuntu/ gutsy-backports main restricted universe multiverse

    ## Uncomment the following two lines to add software from Canonical's
    ## 'partner' repository. This software is not part of Ubuntu, but is
    ## offered by Canonical and the respective vendors as a service to Ubuntu
    ## users.
    deb http://archive.canonical.com/ubuntu/ gutsy partner
    deb-src http://archive.canonical.com/ubuntu/ gutsy partner

    deb http://security.ubuntu.com/ubuntu/ gutsy-security main restricted
    deb-src http://security.ubuntu.com/ubuntu/ gutsy-security main restricted
    deb http://security.ubuntu.com/ubuntu/ gutsy-security universe
    deb-src http://security.ubuntu.com/ubuntu/ gutsy-security universe
    deb http://security.ubuntu.com/ubuntu/ gutsy-security multiverse
    deb-src http://security.ubuntu.com/ubuntu/ gutsy-security multiverse
    #################################################
    # http://medibuntu.org/
    # sudo wget http://www.medibuntu.org/sources.list.d/gutsy.list -O /etc/apt/sources.list.d/medibuntu.list
    # the public key:
    # sudo wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- | sudo apt-key add - && sudo apt-get update

    deb http://repository.debuntu.org/ gutsy multiverse
    # deb-src http://repository.debuntu.org/ gutsy multiverse
    # sudo wget http://repository.debuntu.org/GPG-Key-chantra.txt -O- | sudo apt-key add -

    deb http://dl.google.com/linux/deb/ stable non-free
    # sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
    # Or goto http://www.google.com/linuxrepositories/apt.html to download the key, then install by using synaptic

    # deb http://ftp.de.debian.org/debian/ sid main
    ## sudo gpg --keyserver wwwkeys.eu.pgp.net --recv-keys 07DC563D1F41B907
    ## sudo apt-key add ~/.gnupg/pubring.gpg

    Thursday, 18 October 2007

    Nokia unveils latest Linux tablet

    clipped from news.zdnet.co.uk

    The tablet — which includes no cellular connectivity, but does sport Wi-Fi and Bluetooth — is the third such device Nokia has produced in the past two years, as part of its drive to reposition the company's handsets as "multimedia computers" rather than mobile phones.

    Nokia announced the tablet, which runs on the company's Maemo Linux operating system, at the Web 2.0 Summit in San Francisco.

    The N810 will come with Skype and a Mozilla-based browser pre-installed and, unlike Nokia's other tablets, will come with a slide-out keyboard and integrated GPS — a feature Nokia expects will eventually feature on all its phones.

    Feature

    The device will ship from mid-November in some territories, for around US$479 (£234).

    Despite the inclusion of new features, one expected improvement is yet to appear — WiMax connectivity. Nokia has already committed to launching WiMax-enabled products from next year and has previously hinted that the Linux tablet is in line for the connectivity upgrade.

    Wednesday, 17 October 2007

    run System (Shell) command from the program

    1. In C/C++ program
    ----------

    In this short code snippet I will show you how to execute system commands like ping or nslookup or format c: ;-). The function we will use is rather intended to be used in textconsole based applications. But you could also use it in other programs.

    That is our 'magic' function. You have to include stdlib.h to use it.

    int system( const char *command );

    command is a string that holds the app's name with optional arguments. It is used like on the commandline. The good thing is that the text output that the application produces will be shown in your textconsole. You could now use it to program your own shell! Nice, isn't it? The return-value will be same as the the return-value of the system command only if there was an error, then it will be -1. Here's a little example:

    #include .h>
    #include .h>

    int main()
    {
    cout << "Executing ping..." << style="color: rgb(255, 0, 0);">"ping localhost");
    cout << "Ping is done. I am done too. Let's shutdown and go for a drink."
    <<>

    This simple code snippet outputs some text and then starts ping with argument localhost. The ouput of ping will be shown in your textconsole and it will be the same as if you run it on the shell.



    2. In Java program (quoted from:http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1)
    --------------------

    As part of the Java language, the java.lang package is implicitly imported into every Java program. This package's pitfalls surface often, affecting most programmers. This month, I'll discuss the traps lurking in the Runtime.exec() method.

    Pitfall 4: When Runtime.exec() won't

    The class java.lang.Runtime features a static method called getRuntime(), which retrieves the current Java Runtime Environment. That is the only way to obtain a reference to the Runtime object. With that reference, you can run external programs by invoking the Runtime class's exec() method. Developers often call this method to launch a browser for displaying a help page in HTML.

    There are four overloaded versions of the exec() command:

    • public Process exec(String command);
    • public Process exec(String [] cmdArray);
    • public Process exec(String command, String [] envp);
    • public Process exec(String [] cmdArray, String [] envp);


    For each of these methods, a command -- and possibly a set of arguments -- is passed to an operating-system-specific function call. This subsequently creates an operating-system-specific process (a running program) with a reference to a Process class returned to the Java VM. The Process class is an abstract class, because a specific subclass of Process exists for each operating system.

    You can pass three possible input parameters into these methods:

    1. A single string that represents both the program to execute and any arguments to that program
    2. An array of strings that separate the program from its arguments
    3. An array of environment variables


    Pass in the environment variables in the form name=value. If you use the version of exec() with a single string for both the program and its arguments, note that the string is parsed using white space as the delimiter via the StringTokenizer class.

    Stumbling into an IllegalThreadStateException

    The first pitfall relating to Runtime.exec() is the IllegalThreadStateException. The prevalent first test of an API is to code its most obvious methods. For example, to execute a process that is external to the Java VM, we use the exec() method. To see the value that the external process returns, we use the exitValue() method on the Process class. In our first example, we will attempt to execute the Java compiler (javac.exe):

    Listing 4.1 BadExecJavac.java

    import java.util.*;
    import java.io.*;
    public class BadExecJavac
    {
    public static void main(String args[])
    {
    try
    {
    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec("javac");
    int exitVal = proc.exitValue();
    System.out.println("Process exitValue: " + exitVal);
    } catch (Throwable t)
    {
    t.printStackTrace();
    }
    }
    }


    A run of BadExecJavac produces:

    E:\classes\com\javaworld\jpitfalls\article2>java BadExecJavac
    java.lang.IllegalThreadStateException: process has not exited
    at java.lang.Win32Process.exitValue(Native Method)
    at BadExecJavac.main(BadExecJavac.java:13)


    If an external process has not yet completed, the exitValue() method will throw an IllegalThreadStateException; that's why this program failed. While the documentation states this fact, why can't this method wait until it can give a valid answer?

    A more thorough look at the methods available in the Process class reveals a waitFor() method that does precisely that. In fact, waitFor() also returns the exit value, which means that you would not use exitValue() and waitFor() in conjunction with each other, but rather would choose one or the other. The only possible time you would use exitValue() instead of waitFor() would be when you don't want your program to block waiting on an external process that may never complete. Instead of using the waitFor() method, I would prefer passing a boolean parameter called waitFor into the exitValue() method to determine whether or not the current thread should wait. A boolean would be more beneficial because exitValue() is a more appropriate name for this method, and it isn't necessary for two methods to perform the same function under different conditions. Such simple condition discrimination is the domain of an input parameter.

    Therefore, to avoid this trap, either catch the IllegalThreadStateException or wait for the process to complete.

    Now, let's fix the problem in Listing 4.1 and wait for the process to complete. In Listing 4.2, the program again attempts to execute javac.exe and then waits for the external process to complete:

    Listing 4.2 BadExecJavac2.java

    import java.util.*;
    import java.io.*;
    public class BadExecJavac2
    {
    public static void main(String args[])
    {
    try
    {
    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec("javac");
    int exitVal = proc.waitFor();
    System.out.println("Process exitValue: " + exitVal);
    } catch (Throwable t)
    {
    t.printStackTrace();
    }
    }
    }


    Unfortunately, a run of BadExecJavac2 produces no output. The program hangs and never completes. Why does the javac process never complete?

    Why Runtime.exec() hangs

    The JDK's Javadoc documentation provides the answer to this question:



    Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.



    Is this just a case of programmers not reading the documentation, as implied in the oft-quoted advice: read the fine manual (RTFM)? The answer is partially yes. In this case, reading the Javadoc would get you halfway there; it explains that you need to handle the streams to your external process, but it does not tell you how.

    Another variable is at play here, as is evident by the large number of programmer questions and misconceptions concerning this API in the newsgroups: though Runtime.exec() and the Process APIs seem extremely simple, that simplicity is deceiving because the simple, or obvious, use of the API is prone to error. The lesson here for the API designer is to reserve simple APIs for simple operations. Operations prone to complexities and platform-specific dependencies should reflect the domain accurately. It is possible for an abstraction to be carried too far. The JConfig library provides an example of a more complete API to handle file and process operations (see Resources below for more information).

    Now, let's follow the JDK documentation and handle the output of the javac process. When you run javac without any arguments, it produces a set of usage statements that describe how to run the program and the meaning of all the available program options. Knowing that this is going to the stderr stream, you can easily write a program to exhaust that stream before waiting for the process to exit. Listing 4.3 completes that task. While this approach will work, it is not a good general solution. Thus, Listing 4.3's program is named MediocreExecJavac; it provides only a mediocre solution. A better solution would empty both the standard error stream and the standard output stream. And the best solution would empty these streams simultaneously (I'll demonstrate that later).

    Listing 4.3 MediocreExecJavac.java

    import java.util.*;
    import java.io.*;
    public class MediocreExecJavac
    {
    public static void main(String args[])
    {
    try
    {
    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec("javac");
    InputStream stderr = proc.getErrorStream();
    InputStreamReader isr = new InputStreamReader(stderr);
    BufferedReader br = new BufferedReader(isr);
    String line = null;
    System.out.println("");
    while ( (line = br.readLine()) != null)
    System.out.println(line);
    System.out.println("
    ");
    int exitVal = proc.waitFor();
    System.out.println("Process exitValue: " + exitVal);
    } catch (Throwable t)
    {
    t.printStackTrace();
    }
    }
    }


    A run of MediocreExecJavac generates:

    E:\classes\com\javaworld\jpitfalls\article2>java MediocreExecJavac

    Usage: javac
    where includes:
    -g Generate all debugging info
    -g:none Generate no debugging info
    -g:{lines,vars,source} Generate only some debugging info
    -O Optimize; may hinder debugging or enlarge class files
    -nowarn Generate no warnings
    -verbose Output messages about what the compiler is doing
    -deprecation Output source locations where deprecated APIs are used
    -classpath Specify where to find user class files
    -sourcepath Specify where to find input source files
    -bootclasspath Override location of bootstrap class files
    -extdirs Override location of installed extensions
    -d Specify where to place generated class files
    -encoding Specify character encoding used by source files
    -target Generate class files for specific VM version

    Process exitValue: 2


    So, MediocreExecJavac works and produces an exit value of 2. Normally, an exit value of 0 indicates success; any nonzero value indicates an error. The meaning of these exit values depends on the particular operating system. A Win32 error with a value of 2 is a "file not found" error. That makes sense, since javac expects us to follow the program with the source code file to compile.

    Thus, to circumvent the second pitfall -- hanging forever in Runtime.exec() -- if the program you launch produces output or expects input, ensure that you process the input and output streams.

    Assuming a command is an executable program

    Under the Windows operating system, many new programmers stumble upon Runtime.exec() when trying to use it for nonexecutable commands like dir and copy. Subsequently, they run into Runtime.exec()'s third pitfall. Listing 4.4 demonstrates exactly that:

    Listing 4.4 BadExecWinDir.java

    import java.util.*;
    import java.io.*;
    public class BadExecWinDir
    {
    public static void main(String args[])
    {
    try
    {
    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec("dir");
    InputStream stdin = proc.getInputStream();
    InputStreamReader isr = new InputStreamReader(stdin);
    BufferedReader br = new BufferedReader(isr);
    String line = null;
    System.out.println("");
    while ( (line = br.readLine()) != null)
    System.out.println(line);
    System.out.println("
    ");
    int exitVal = proc.waitFor();
    System.out.println("Process exitValue: " + exitVal);
    } catch (Throwable t)
    {
    t.printStackTrace();
    }
    }
    }


    A run of BadExecWinDir produces:

    E:\classes\com\javaworld\jpitfalls\article2>java BadExecWinDir
    java.io.IOException: CreateProcess: dir error=2
    at java.lang.Win32Process.create(Native Method)
    at java.lang.Win32Process.(Unknown Source)
    at java.lang.Runtime.execInternal(Native Method)
    at java.lang.Runtime.exec(Unknown Source)
    at java.lang.Runtime.exec(Unknown Source)
    at java.lang.Runtime.exec(Unknown Source)
    at java.lang.Runtime.exec(Unknown Source)
    at BadExecWinDir.main(BadExecWinDir.java:12)


    As stated earlier, the error value of 2 means "file not found," which, in this case, means that the executable named dir.exe could not be found. That's because the directory command is part of the Windows command interpreter and not a separate executable. To run the Windows command interpreter, execute either command.com or cmd.exe, depending on the Windows operating system you use. Listing 4.5 runs a copy of the Windows command interpreter and then executes the user-supplied command (e.g., dir).

    Listing 4.5 GoodWindowsExec.java

    import java.util.*;
    import java.io.*;
    class StreamGobbler extends Thread
    {
    InputStream is;
    String type;

    StreamGobbler(InputStream is, String type)
    {
    this.is = is;
    this.type = type;
    }

    public void run()
    {
    try
    {
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line=null;
    while ( (line = br.readLine()) != null)
    System.out.println(type + ">" + line);
    } catch (IOException ioe)
    {
    ioe.printStackTrace();
    }
    }
    }
    public class GoodWindowsExec
    {
    public static void main(String args[])
    {
    if (args.length <>");
    System.exit(1);
    }

    try
    {
    String osName = System.getProperty("os.name" );
    String[] cmd = new String[3];
    if( osName.equals( "Windows NT" ) )
    {
    cmd[0] = "cmd.exe" ;
    cmd[1] = "/C" ;
    cmd[2] = args[0];
    }
    else if( osName.equals( "Windows 95" ) )
    {
    cmd[0] = "command.com" ;
    cmd[1] = "/C" ;
    cmd[2] = args[0];
    }

    Runtime rt = Runtime.getRuntime();
    System.out.println("Execing " + cmd[0] + " " + cmd[1]
    + " " + cmd[2]);
    Process proc = rt.exec(cmd);
    // any error message?
    StreamGobbler errorGobbler = new
    StreamGobbler(proc.getErrorStream(), "ERROR");

    // any output?
    StreamGobbler outputGobbler = new
    StreamGobbler(proc.getInputStream(), "OUTPUT");

    // kick them off
    errorGobbler.start();
    outputGobbler.start();

    // any error???
    int exitVal = proc.waitFor();
    System.out.println("ExitValue: " + exitVal);
    } catch (Throwable t)
    {
    t.printStackTrace();
    }
    }
    }


    Running GoodWindowsExec with the dir command generates:

    E:\classes\com\javaworld\jpitfalls\article2>java GoodWindowsExec "dir *.java"
    Execing cmd.exe /C dir *.java
    OUTPUT> Volume in drive E has no label.
    OUTPUT> Volume Serial Number is 5C5F-0CC9
    OUTPUT>
    OUTPUT> Directory of E:\classes\com\javaworld\jpitfalls\article2
    OUTPUT>
    OUTPUT>10/23/00 09:01p 805 BadExecBrowser.java
    OUTPUT>10/22/00 09:35a 770 BadExecBrowser1.java
    OUTPUT>10/24/00 08:45p 488 BadExecJavac.java
    OUTPUT>10/24/00 08:46p 519 BadExecJavac2.java
    OUTPUT>10/24/00 09:13p 930 BadExecWinDir.java
    OUTPUT>10/22/00 09:21a 2,282 BadURLPost.java
    OUTPUT>10/22/00 09:20a 2,273 BadURLPost1.java
    ... (some output omitted for brevity)
    OUTPUT>10/12/00 09:29p 151 SuperFrame.java
    OUTPUT>10/24/00 09:23p 1,814 TestExec.java
    OUTPUT>10/09/00 05:47p 23,543 TestStringReplace.java
    OUTPUT>10/12/00 08:55p 228 TopLevel.java
    OUTPUT> 22 File(s) 46,661 bytes
    OUTPUT> 19,678,420,992 bytes free
    ExitValue: 0


    Running GoodWindowsExec with any associated document type will launch the application associated with that document type. For example, to launch Microsoft Word to display a Word document (i.e., one with a .doc extension), type:

    >java GoodWindowsExec "yourdoc.doc"


    Notice that GoodWindowsExec uses the os.name system property to determine which Windows operating system you are running -- and thus determine the appropriate command interpreter. After executing the command interpreter, handle the standard error and standard input streams with the StreamGobbler class. StreamGobbler empties any stream passed into it in a separate thread. The class uses a simple String type to denote the stream it empties when it prints the line just read to the console.

    Thus, to avoid the third pitfall related to Runtime.exec(), do not assume that a command is an executable program; know whether you are executing a standalone executable or an interpreted command. At the end of this section, I will demonstrate a simple command-line tool that will help you with that analysis.

    It is important to note that the method used to obtain a process's output stream is called getInputStream(). The thing to remember is that the API sees things from the perspective of the Java program and not the external process. Therefore, the external program's output is the Java program's input. And that logic carries over to the external program's input stream, which is an output stream to the Java program.

    Runtime.exec() is not a command line

    One final pitfall to cover with Runtime.exec() is mistakenly assuming that exec() accepts any String that your command line (or shell) accepts. Runtime.exec() is much more limited and not cross-platform. This pitfall is caused by users attempting to use the exec() method to accept a single String as a command line would. The confusion may be due to the fact that command is the parameter name for the exec() method. Thus, the programmer incorrectly associates the parameter command with anything that he or she can type on a command line, instead of associating it with a single program and its arguments. In listing 4.6 below, a user tries to execute a command and redirect its output in one call to exec():

    Listing 4.6 BadWinRedirect.java

    import java.util.*;
    import java.io.*;
    // StreamGobbler omitted for brevity
    public class BadWinRedirect
    {
    public static void main(String args[])
    {
    try
    {
    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec("java jecho 'Hello World' > test.txt");
    // any error message?
    StreamGobbler errorGobbler = new
    StreamGobbler(proc.getErrorStream(), "ERROR");

    // any output?
    StreamGobbler outputGobbler = new
    StreamGobbler(proc.getInputStream(), "OUTPUT");

    // kick them off
    errorGobbler.start();
    outputGobbler.start();

    // any error???
    int exitVal = proc.waitFor();
    System.out.println("ExitValue: " + exitVal);
    } catch (Throwable t)
    {
    t.printStackTrace();
    }
    }
    }


    Running BadWinRedirect produces:

    E:\classes\com\javaworld\jpitfalls\article2>java BadWinRedirect
    OUTPUT>'Hello World' > test.txt
    ExitValue: 0


    The program BadWinRedirect attempted to redirect the output of an echo program's simple Java version into the file test.txt. However, we find that the file test.txt does not exist. The jecho program simply takes its command-line arguments and writes them to the standard output stream. (You will find the source for jecho in the source code available for download in Resources.) In Listing 4.6, the user assumed that you could redirect standard output into a file just as you could on a DOS command line. Nevertheless, you do not redirect the output through this approach. The incorrect assumption here is that the exec() method acts like a shell interpreter; it does not. Instead, exec() executes a single executable (a program or script). If you want to process the stream to either redirect it or pipe it into another program, you must do so programmatically, using the java.io package. Listing 4.7 properly redirects the standard output stream of the jecho process into a file.

    Listing 4.7 GoodWinRedirect.java

    import java.util.*;
    import java.io.*;
    class StreamGobbler extends Thread
    {
    InputStream is;
    String type;
    OutputStream os;

    StreamGobbler(InputStream is, String type)
    {
    this(is, type, null);
    }
    StreamGobbler(InputStream is, String type, OutputStream redirect)
    {
    this.is = is;
    this.type = type;
    this.os = redirect;
    }

    public void run()
    {
    try
    {
    PrintWriter pw = null;
    if (os != null)
    pw = new PrintWriter(os);

    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line=null;
    while ( (line = br.readLine()) != null)
    {
    if (pw != null)
    pw.println(line);
    System.out.println(type + ">" + line);
    }
    if (pw != null)
    pw.flush();
    } catch (IOException ioe)
    {
    ioe.printStackTrace();
    }
    }
    }
    public class GoodWinRedirect
    {
    public static void main(String args[])
    {
    if (args.length <>");
    System.exit(1);
    }

    try
    {
    FileOutputStream fos = new FileOutputStream(args[0]);
    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec("java jecho 'Hello World'");
    // any error message?
    StreamGobbler errorGobbler = new
    StreamGobbler(proc.getErrorStream(), "ERROR");

    // any output?
    StreamGobbler outputGobbler = new
    StreamGobbler(proc.getInputStream(), "OUTPUT", fos);

    // kick them off
    errorGobbler.start();
    outputGobbler.start();

    // any error???
    int exitVal = proc.waitFor();
    System.out.println("ExitValue: " + exitVal);
    fos.flush();
    fos.close();
    } catch (Throwable t)
    {
    t.printStackTrace();
    }
    }
    }


    Running GoodWinRedirect produces:

    E:\classes\com\javaworld\jpitfalls\article2>java GoodWinRedirect test.txt
    OUTPUT>'Hello World'
    ExitValue: 0


    After running GoodWinRedirect, test.txt does exist. The solution to the pitfall was to simply control the redirection by handling the external process's standard output stream separately from the Runtime.exec() method. We create a separate OutputStream, read in the filename to which we redirect the output, open the file, and write the output that we receive from the spawned process's standard output to the file. Listing 4.7 completes that task by adding a new constructor to our StreamGobbler class. The new constructor takes three arguments: the input stream to gobble, the type String that labels the stream we are gobbling, and the output stream to which we redirect the input. This new version of StreamGobbler does not break any of the code in which it was previously used, as we have not changed the existing public API -- we only extended it.

    Since the argument to Runtime.exec() is dependent on the operating system, the proper commands to use will vary from one OS to another. So, before finalizing arguments to Runtime.exec() and writing the code, quickly test the arguments. Listing 4.8 is a simple command-line utility that allows you to do just that.

    Here's a useful exercise: try to modify TestExec to redirect the standard input or standard output to a file. When executing the javac compiler on Windows 95 or Windows 98, that would solve the problem of error messages scrolling off the top of the limited command-line buffer.

    Listing 4.8 TestExec.java

    import java.util.*;
    import java.io.*;
    // class StreamGobbler omitted for brevity
    public class TestExec
    {
    public static void main(String args[])
    {
    if (args.length < cmd =" args[0];" rt =" Runtime.getRuntime();" proc =" rt.exec(cmd);" errorgobbler =" new" outputgobbler =" new" exitval =" proc.waitFor();">


    Running TestExec to launch the Netscape browser and load the Java help documentation produces:

    E:\classes\com\javaworld\jpitfalls\article2>java TestExec "e:\java\docs\index.html"
    java.io.IOException: CreateProcess: e:\java\docs\index.html error=193
    at java.lang.Win32Process.create(Native Method)
    at java.lang.Win32Process.(Unknown Source)
    at java.lang.Runtime.execInternal(Native Method)
    at java.lang.Runtime.exec(Unknown Source)
    at java.lang.Runtime.exec(Unknown Source)
    at java.lang.Runtime.exec(Unknown Source)
    at java.lang.Runtime.exec(Unknown Source)
    at TestExec.main(TestExec.java:45)


    Our first test failed with an error of 193. The Win32 error for value 193 is "not a valid Win32 application." This error tells us that no path to an associated application (e.g., Netscape) exists, and that the process cannot run an HTML file without an associated application.

    Therefore, we try the test again, this time giving it a full path to Netscape. (Alternately, we could add Netscape to our PATH environment variable.) A second run of TestExec produces:

    E:\classes\com\javaworld\jpitfalls\article2>java TestExec
    "e:\program files\netscape\program\netscape.exe e:\java\docs\index.html"
    ExitValue: 0


    This worked! The Netscape browser launches, and it then loads the Java help documentation.

    One additional improvement to TestExec would include a command-line switch to accept input from standard input. You would then use the Process.getOutputStream() method to pass the input to the spawned external program.

    To sum up, follow these rules of thumb to avoid the pitfalls in Runtime.exec():

    1. You cannot obtain an exit status from an external process until it has exited
    2. You must immediately handle the input, output, and error streams from your spawned external process
    3. You must use Runtime.exec() to execute programs
    4. You cannot use Runtime.exec() like a command line

    Files about Latex

    There are also files that are created by LaTeX2e, the .aux file, the .toc file and the .bib file. The .aux (auxiliary) file is where LaTeX stores all the information about the counters (like section numbers), footnotes, bibliography entries, reference marks, and anything else that LaTeX may need to keep track of. This file is written over whenever a file is typeset by LaTeX. Whenever a document is typeset LaTeX reads this file to get the information it need, and writes to it after typesetting is completed. This is why changes in the counters will not take effect until LaTeX is run twice, because the .aux file is not up to date the first time. The .bib file is where all the bibliography information is kept. You can either make this file yourself, or you can use BibTeX to create the file. The .toc file contains all the information needed to create the Table of Contents. This file is created when LaTeX sees the command \tableofcontents, and the section names, numbers and page numbers are all read from the .aux file.

    My photo
    London, United Kingdom
    twitter.com/zhengxin

    Facebook & Twitter