星期四, 十二月 20, 2007

How to Turn Off beep

笔记本上的beep声音确实够恐怖,把我郁闷的,关键我还是在办公室,想起来就尴尬。

①Windowsでビープ音を止める
デバイスマネージャで「表示 > 非表示のデバイスの表示」としてから「プラグアンドプレイでないドライバ」の「Beepのプロパティ」を停止して無効にすれば止まる。
一時的に止めるだけでよいなら、コマンドプロンプトでnet stop beepとすればよい。
特定の場合にのみ警告音を殺したい場合は、無音のWAVEファイルを用意して割り当てるというアイデアも見かけた。


②VMwareでビープ音を止める
VMware設定ファイルに
mks.noBeep = "TRUE"
と追加してVMwareを再起動すれば止まる。

設定ファイル:
windowsの場合:C:\Documents and Settings\foxee\Application Data\VMware\preferences.ini
linuxの場合:  ~/.vmware/preferences

http://www.debuntu.org/how-to-turn-off-virtual-console-beep

如果还是不能禁止的话,可以把那句放在另一个设置文件里面
C:\Documents and Settings\All Users\Application Data\VMware\VMware Workstation\config.ini

星期三, 十一月 14, 2007

やってやれないことはない、やらずにできるわけがない

やってやれないことはない、やらずにできるわけがない

ubuntu 7.10 设置

PDF乱码

星期六, 十一月 10, 2007

ubuntu 7.10 下挂载XP的分区

前言

以前用的ubuntu 7.04,记得装上系统就能自动识别window下的分区,虽然那个时候还不能自动支持写NTFS分区,需要安装一个包才能支持。这次听说ubuntu 7.10自动支持了,挺好。

由于某些原因,没能从7.04升级到7.10,于是从系统里先删除7.04然后重新安装7.10。

这中间有个小插曲,我使用MbrFix小工具来恢复MBR。本来要立即装7.10的,想着windows的那个病毒把我折腾坏了,干脆把window也重装,试一试网上说的最好的XP---疯子版XP,结果问题出来了,我的硬盘装不了系统了,在“SetUp is inspecting your computer's configuration....”界面就停住了,我google,baitu了半天,网上有很多解决方案,包括微软的官方解决方案都搞不定,看来还是没有找到对症的。后来想着,是不是跟linux的分区相关,于是用PQ把两个linux分区给删除了,PQ居然报告说不认识分区格式,巨汗:《 (只能先格式化成NTFS,然后再删除,并且发现,我的window磁盘管理也不认识这两个分区),这才得以安装windows XP。这才想起来,装7.04的时候分区的时候,选择的是扩展分区,而不是主分区,可能是这个原因,不是很清楚。

所以这次装7.10的时候,选择了主分区。然后就出现了,系统安装完之后,windows下的分区一个都没有自动加载。只能自己手动加载了。

言归正卷
关于加载NTFS分区,在网上找到了很多解决方案:
1. SAMBA: Cannot share folder on NTFS drive
2. Problems sharing a NTFS Folder in Gutsy


这中间又是因为某种原因,在把fstab文件备份之后,回到windows XP去了,第二天再回到ubuntu下时,发现所有的NTFS分区全部自动加载,而且发现fstab和备份的fstab一模一样,巨汗+无语。



# /etc/fstab: static file system information.
#
#
proc /proc proc defaults 0 0
# /dev/sda3
UUID=a2cb11ff-07a2-4142-9414-1a83696f20d7 / ext3 defaults,errors=remount-ro 0 1
# /dev/sda1
UUID=627C4C957C4C663F /media/sda1 ntfs defaults,umask=007,gid=46 0 1
# /dev/sda5
UUID=341825B418257650 /media/sda5 ntfs defaults,umask=007,gid=46 0 1
# /dev/sda6
UUID=5E384AA0384A76D5 /media/sda6 ntfs defaults,umask=007,gid=46 0 1
# /dev/sda7
UUID=9A384D1B384CF831 /media/sda7 ntfs defaults,umask=007,gid=46 0 1
# /dev/sda8
UUID=DA1C95611C953989 /media/sda8 ntfs defaults,umask=007,gid=46 0 1
# /dev/sda4
UUID=d8aabd43-4e5f-4745-9971-6f16a5788c7e none swap sw 0 0
/dev/scd0 /media/cdrom0 udf,iso9660 user,noauto,exec 0 0
/dev/fd0 /media/floppy0 auto rw,user,noauto,exec 0 0

星期二, 十月 09, 2007

JavaScript で日本語文字を1つづつ切り出す

<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=x-sjis">
<TITLE>文字の切り出し練習</TITLE>
<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
<!--
function cutLetter(targetstring,targetindex,targetlength){
var i = 0;
var j = 0;
var k = 0;
var l = '漢';

var targetstring = document.myform.txt1.value;
var targetindex = parseInt(document.myform.txt2.value);
var targetlength = parseInt(document.myform.txt3.value);

if (l.length == 2){
j = 0;
for (i=0;i<targetindex;i++){
l = escape(targetstring.substring(j,j+1)).substring(1,2);
if (l=='8'||l=='9'||l=='E'||l=='F')
j += 2;
else
j += 1;
}
k = j;
for (i=0;i<targetlength;i++){
l = escape(targetstring.substring(k,k+1)).substring(1,2);
if (l=='8'||l=='9'||l=='E'||l=='F')
k += 2;
else
k += 1;
}
} else {
j = targetindex;
k = parseInt(targetindex) + parseInt(targetlength);
}
l = targetstring.substring(j,k);
document.myform.txt4.value = l;
return false;
}
//-->
</SCRIPT>
</HEAD>
<BODY>
<FORM name="myform">
<H1>文字の切り出し練習</H1>
 文字列:<INPUT type="text" name="txt1" value="" size=70 maxlength="256"><BR>
 切り出し開始位置:<INPUT type="text" name="txt2" value="0" size=5 maxlength=5> 
 切り出し文字数:<INPUT type="text" name="txt3" value="1" size=5 maxlength=5>
 <INPUT type="button" name="btn1" value="実行" onClick="cutLetter()"><BR><BR>
 ===> 切り出し文字列:<INPUT type="text" name="txt4" value="" size=70 maxlength="256">
</FORM>
</BODY>
</HTML>

Perl打印整个画面时候

用Perl开发Web的时候,使用Perl打印出整个画面的时候,一些特殊符号需要注意
' " \ $ @

string.replace(/’/g,'\\\'');
string.replace(/”/g,'\\\"');
string.replace(/¥/g,'\\\\');
string.replace(/$/g,'\\\$');
string.replace(/@/g,'\\\@');

Javascript Function : escape()

escape(string)

ASCII Table

The top-level function, escape, encodes the string that is contained in the string argument to make it portable. A string is considered portable if it can be transmitted across any network to any computer that supports ASCII characters.

To make a string portable, characters other than the following 69 ASCII characters must be encoded:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
1234567890
@*-_+./

All other characters are converted either to their two digit (%xx) or four digit (%uxxxx) hexadecimal equivalent (refered to as the character's "hexadecimal escape sequence"). For example, a blank space will be represented by %20 and a semicolon by %3B. (Note that the hexadecimal numbers are: 0123456789ABCDEF).

星期日, 十月 07, 2007

全角⇔半角変換 VBscript

//全角半角変換用文字列定数

Const FullKana = "。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワ゛゜";
Const HalfKana = "。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚";

Const FullKana2 = "ヴガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ";
Const HalfKana2 = "ヴガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ";

Const FullAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
Const HalfAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

Const FullNumber = "0123456789";
Const HalfNumber = "0123456789";

Const FullSymbol = " !”#$%&’()*+,-./:;<=>?@[¥]^_‘{|}~";
Const HalfSymbol = " !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~";

//大文字小文字変換用文字列定数

Const UpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
Const LowerCase = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";

//ひらがなカタカナ変換用文字列定数
Const HiraKana = "をぁぃぅぇぉゃゅょっあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわんゐゑ";
Const HiraKana2= "がぎぐげござじずぜぞだぢづでどばびぶべぼぱぴぷぺぽ";
Const HiraKana3= "う゛";

Const KataKana = "ヲァィゥェォャュョッアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワンヰヱ";
Const KataKana2= "ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ";
Const KataKana3= "ヴ";
Const KataKana4= "ヲァィゥェォャュョッアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン";
Const KataKana5= "ガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポ";


Function TranslateString(OriginalString, strSource, strDestination)
Dim strResult
strResult = OriginalString

Dim nLength
nLength = Len(strSource)
Dim i
For i = 1 To nLength
strResult = Replace(strResult, Mid(strSource, i, 1), Mid(strDestination, i, 1))
Next

TranslateString = strResult
End Function

Function EncodeWKana(OriginalString)
Dim strResult
strResult = OriginalString
If chkWKana.checked Then

strResult = TranslateString(strResult, FullKana, HalfKana)

Dim nLength
nLength = Len(FullKana2)
Dim i
For i = 1 To nLength
strResult = Replace(strResult, Mid(FullKana2, i, 1), Mid(HalfKana2, ((i -1) *2) +1, 2))
Next

End If
EncodeWKana = strResult
End Function

Function EncodeWAlphabet(OriginalString)
Dim strResult
strResult = OriginalString
If chkWAlphabet.checked Then
strResult = TranslateString(strResult, FullAlphabet, HalfAlphabet)
End If
EncodeWAlphabet = strResult
End Function

Function EncodeWNumber(OriginalString)
Dim strResult
strResult = OriginalString
If chkWNumber.checked Then
strResult = TranslateString(strResult, FullNumber, HalfNumber)
End If
EncodeWNumber = strResult
End Function

Function EncodeWSymbol(OriginalString)
Dim strResult
strResult = OriginalString
If chkWSymbol.checked Then
strResult = TranslateString(strResult, FullSymbol, HalfSymbol)
End If
EncodeWSymbol = strResult
End Function

Function EncodeCase(OriginalString)
Dim strResult
strResult = OriginalString
If chkCase.checked Then
strResult = TranslateString(strResult, UpperCase, LowerCase)
End If
EncodeCase = strResult
End Function

Function EncodeKana(OriginalString)
Dim strResult
strResult = OriginalString
If chkKana.checked Then

strResult = Replace(strResult, HiraKana3, KanaKana3)
strResult = TranslateString(strResult, HiraKana, KataKana)
strResult = TranslateString(strResult, HiraKana2, KataKana2)

End If
EncodeKana = strResult
End Function

Function DecodeWKana(OriginalString)
Dim strResult
strResult = OriginalString
If chkWKana.checked Then

Dim nLength
nLength = Len(FullKana2)
Dim i
For i = 1 To nLength
strResult = Replace(strResult, Mid(HalfKana2, ((i -1) *2) +1, 2), Mid(FullKana2, i, 1))
Next

strResult = TranslateString(strResult, HalfKana, FullKana)

End If
DecodeWKana = strResult
End Function

Function DecodeWAlphabet(OriginalString)
Dim strResult
strResult = OriginalString
If chkWAlphabet.checked Then
strResult = TranslateString(strResult, HalfAlphabet, FullAlphabet)
End If
DecodeWAlphabet = strResult
End Function

Function DecodeWNumber(OriginalString)
Dim strResult
strResult = OriginalString
If chkWNumber.checked Then
strResult = TranslateString(strResult, HalfNumber, FullNumber)
End If
DecodeWNumber = strResult
End Function

Function DecodeWSymbol(OriginalString)
Dim strResult
strResult = OriginalString
If chkWSymbol.checked Then
strResult = TranslateString(strResult, HalfSymbol, FullSymbol)
End If
DecodeWSymbol = strResult
End Function

Function DecodeCase(OriginalString)
Dim strResult
strResult = OriginalString
If chkCase.checked Then
strResult = TranslateString(strResult, LowerCase, UpperCase)
End If
DecodeCase = strResult
End Function

Function DecodeKana(OriginalString)
Dim strResult
strResult = OriginalString
If chkKana.checked Then

Dim nLength
nLength = Len(HiraKana2)
Dim i
For i = 1 To nLength
strResult = Replace(strResult, Mid(KataKana5, ((i -1) *2) +1, 2), Mid(HiraKana2, i, 1))
Next

strResult = TranslateString(strResult, KataKana, HiraKana)
strResult = TranslateString(strResult, KataKana2, HiraKana2)
strResult = Replace(strResult, KanaKana3, HiraKana3)
strResult = TranslateString(strResult, KataKana4, HiraKana)

End If
DecodeKana = strResult
End Function

Function EncodeString(OriginalString)
Dim strResult
strResult = OriginalString
strResult = EncodeCase(strResult)
strResult = EncodeKana(strResult)
strResult = EncodeWKana(strResult)
strResult = EncodeWAlphabet(strResult)
strResult = EncodeWNumber(strResult)
strResult = EncodeWSymbol(strResult)
EncodeString = strResult
End Function

Function DecodeString(OriginalString)
Dim strResult
strResult = OriginalString
strResult = DecodeWKana(strResult)
strResult = DecodeWAlphabet(strResult)
strResult = DecodeWNumber(strResult)
strResult = DecodeWSymbol(strResult)
strResult = DecodeCase(strResult)
strResult = DecodeKana(strResult)
DecodeString = strResult
End Function

入力チェックについて方法もありますよ

Javascript trim

/**
*
* Javascript trim, ltrim, rtrim
* http://www.webtoolkit.info/
*
*
**/

function trim(str, chars) {
return ltrim(rtrim(str, chars), chars);
}

function ltrim(str, chars) {
chars = chars || "\\s";
return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
}

function rtrim(str, chars) {
chars = chars || "\\s";
return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
}


三种方法

Javascript sprintf

Several programming languages implement a sprintf function, to output a formatted string. It originated from the C programming language, printf function. Its a string manipulation function.

This is limited sprintf Javascript implementation. Function returns a string formatted by the usual printf conventions. See below for more details. You must specify the string and how to format the variables in it. Possible format values:

%% - Returns a percent sign
%b - Binary number
%c - The character according to the ASCII value
%d - Signed decimal number
%f - Floating-point number
%o - Octal number
%s - String
%x - Hexadecimal number (lowercase letters)
%X - Hexadecimal number (uppercase letters)
Additional format values. These are placed between the % and the letter (example %.2f):

+ (Forces both + and - in front of numbers. By default, only negative numbers are marked)
- (Left-justifies the variable value)
0 zero will be used for padding the results to the right string size
[0-9] (Specifies the minimum width held of to the variable value)
.[0-9] (Specifies the number of decimal digits or maximum string length)
If you plan using UTF-8 encoding in your project don't forget to set the page encoding to UTF-8 (Content-Type meta tag), and use Javascript UTF-8 utility found on this website.




/**
*
* Javascript sprintf
* http://www.webtoolkit.info/
*
*
**/

sprintfWrapper = {

init : function () {

if (typeof arguments == "undefined") { return null; }
if (arguments.length < 1) { return null; }
if (typeof arguments[0] != "string") { return null; }
if (typeof RegExp == "undefined") { return null; }

var string = arguments[0];
var exp = new RegExp(/(%([%]|(\-)?(\+|\x20)?(0)?(\d+)?(\.(\d)?)?([bcdfosxX])))/g);
var matches = new Array();
var strings = new Array();
var convCount = 0;
var stringPosStart = 0;
var stringPosEnd = 0;
var matchPosEnd = 0;
var newString = '';
var match = null;

while (match = exp.exec(string)) {
if (match[9]) { convCount += 1; }

stringPosStart = matchPosEnd;
stringPosEnd = exp.lastIndex - match[0].length;
strings[strings.length] = string.substring(stringPosStart, stringPosEnd);

matchPosEnd = exp.lastIndex;
matches[matches.length] = {
match: match[0],
left: match[3] ? true : false,
sign: match[4] || '',
pad: match[5] || ' ',
min: match[6] || 0,
precision: match[8],
code: match[9] || '%',
negative: parseInt(arguments[convCount]) < 0 ? true : false,
argument: String(arguments[convCount])
};
}
strings[strings.length] = string.substring(matchPosEnd);

if (matches.length == 0) { return string; }
if ((arguments.length - 1) < convCount) { return null; }

var code = null;
var match = null;
var i = null;

for (i=0; i<matches.length; i++) {

if (matches[i].code == '%') { substitution = '%' }
else if (matches[i].code == 'b') {
matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(2));
substitution = sprintfWrapper.convert(matches[i], true);
}
else if (matches[i].code == 'c') {
matches[i].argument = String(String.fromCharCode(parseInt(Math.abs(parseInt(matches[i].argument)))));
substitution = sprintfWrapper.convert(matches[i], true);
}
else if (matches[i].code == 'd') {
matches[i].argument = String(Math.abs(parseInt(matches[i].argument)));
substitution = sprintfWrapper.convert(matches[i]);
}
else if (matches[i].code == 'f') {
matches[i].argument = String(Math.abs(parseFloat(matches[i].argument)).toFixed(matches[i].precision ? matches[i].precision : 6));
substitution = sprintfWrapper.convert(matches[i]);
}
else if (matches[i].code == 'o') {
matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(8));
substitution = sprintfWrapper.convert(matches[i]);
}
else if (matches[i].code == 's') {
matches[i].argument = matches[i].argument.substring(0, matches[i].precision ? matches[i].precision : matches[i].argument.length)
substitution = sprintfWrapper.convert(matches[i], true);
}
else if (matches[i].code == 'x') {
matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(16));
substitution = sprintfWrapper.convert(matches[i]);
}
else if (matches[i].code == 'X') {
matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(16));
substitution = sprintfWrapper.convert(matches[i]).toUpperCase();
}
else {
substitution = matches[i].match;
}

newString += strings[i];
newString += substitution;

}
newString += strings[i];

return newString;

},

convert : function(match, nosign){
if (nosign) {
match.sign = '';
} else {
match.sign = match.negative ? '-' : match.sign;
}
var l = match.min - match.argument.length + 1 - match.sign.length;
var pad = new Array(l < 0 ? 0 : l).join(match.pad);
if (!match.left) {
if (match.pad == "0" || nosign) {
return match.sign + pad + match.argument;
} else {
return pad + match.sign + match.argument;
}
} else {
if (match.pad == "0" || nosign) {
return match.sign + match.argument + pad.replace(/0/g, ' ');
} else {
return match.sign + match.argument + pad;
}
}
}
}

sprintf = sprintfWrapper.init;

Javascript string pad

This functions returns the input string padded on the left, the right, or both sides to the specified padding length. If the optional argument "pad" is not supplied, the input is padded with spaces, otherwise it is padded with characters from "pad" up to the "len" length.


/**
*
* Javascript string pad
* http://www.webtoolkit.info/
*
**/

var STR_PAD_LEFT = 1;
var STR_PAD_RIGHT = 2;
var STR_PAD_BOTH = 3;

function pad(str, len, pad, dir) {

if (typeof(len) == "undefined") { var len = 0; }
if (typeof(pad) == "undefined") { var pad = ' '; }
if (typeof(dir) == "undefined") { var dir = STR_PAD_RIGHT; }

if (len + 1 >= str.length) {

switch (dir){

case STR_PAD_LEFT:
str = Array(len + 1 - str.length).join(pad) + str;
break;

case STR_PAD_BOTH:
var right = Math.ceil((padlen = len - str.length) / 2);
var left = padlen - right;
str = Array(left+1).join(pad) + str + Array(right+1).join(pad);
break;

default:
str = str + Array(len + 1 - str.length).join(pad);
break;

} // switch

}

return str;

}

星期一, 九月 24, 2007

VMware的虚拟网络

VMware的虚拟网络有三种模式供选择:Bridge, Host-only, NAT。

一、Bridge模式:
这种方式最简单,直接将虚拟网卡桥接到一个物理网卡上面,和linux下一个网卡绑定两个不同地址类似,实际上是将网卡设置为混杂模式,从而达到侦听多个IP的能力。此模式可理解为Client的网卡B与Host的真实网卡A桥接在一起,A和B的地位是完全一至的,他们相当于在同一个子网。在此种模式下,虚拟机和host机处于对等的地位,在网络关系上是平等的,没有谁在谁后面的问题.
使用这种方式很简单,前提是你可以得到1个以上的地址.对于想进行种种网络实验的朋友不太适合,因为你无法对虚拟机的网络进行控制,它直接出去了. Bridge模式还有一个缺点,就是如果Host的网卡A如果没有插网线,将导致A不可用,那么Host与Client间的虚拟网络也将失效。 需要用RJ45的水晶头做一个闭合的网络终结器解决。


二、Host-only模式:
这种模式下,VMware为Host添加一块虚拟网卡A,默认叫做VMware Network Adapter VMnet1,可理解为A网卡与Client的B网卡以交叉线相连。而Host的C网卡连到Network上。A与B设置同一网段的IP地址,A为B的网关。默认情况下,Vmware提供了DHCP,它能提供给B一个与A同网段的IP,以保证通讯。此时Client并不能与Network通讯。如果Network是Internet,应当在Host上启用类似NAT的服务。而如果Network指内网,则需要启用路由功能,使网络连通。
这应该是最为灵活的方式,有兴趣的话可以进行各种网络实验.和nat唯一的不同的是,此种方式下,没有地址转换服务,因此,默认情况下,虚拟机只能到主机访问,这也是hostonly的名字的意义. 默认情况下,也会有一个dhcp服务加载到vmnet1上.这样连接到vmnet8上的虚拟机仍然可以设置成dhcp,方便系统的配置. 是不是这种方式就没有办法连接到外网呢,当然不是,事实上,这种方式更为灵活,你可以使用自己的方式,从而达到最
理想的配置,例如:
a.使用自己dhcp服务:首先停掉vmware自带的dhcp服务,使dhcp服务更为统一.
b.使用自己的nat,方便加入防火墙.windows host可以做nat的方法很多,简单的如windows xp的internet共享,复杂的如windows server里的nat服务.
c. 使用自己的防火墙.因为你可以完全控制vmnet1,你可以加入(或试验)防火墙在vmnet1和外网的网卡间.从以上可以看出,hostonly这种模式和普通的nat server带整个内网上网的情形类似,因此你可以方便的进行与之有关的实验,比如防火强的设置等


三、NAT模式:
这种方式下host内部出现了一个虚拟的网卡vmnet8(默认情况下),如果你有过做nat服务器的经验,这里的vmnet8就相当于连接到内网的网卡,而虚拟机本身则相当于运行在内网上的机器,虚拟机内的网卡(eth0)则独立于vmnet8.
你会发现在这种方式下,vmware自带的dhcp会默认地加载到vmnet8界面上,这样虚拟机就可以使用dhcp服务.更为重要的是,vmware自带了nat服务,提供了从vmnet8到外网的地址转 换,所以这种情况是一个实实在在的nat服务器在运行,只不过是供虚拟机用的. 很显然,如果你只有一个外网地址,此种方式很合适.

星期一, 五月 21, 2007

在Ubuntu英文界面下处理中文

在中文 Linux 社区中,除了讨论有关中文字体美化的问题之外,就属在 Linux 英文界面下进行中文处理的话题最热门了。得益于 Linux 良好的 i18n 特性,几乎所有的 Linux 发行版在安装之后,都可以自由地切换到任意语言的界面下进行工作。(而不似 Windows 那般,一个操作系统,居然还分成 N 种语言版本来销售。)


以前在 Redhat/Fedora Core 中弄过一样的事情,不过内中流程甚为繁琐。还好在 Ubuntu 中,这件事情变得简单易行。在 Linux 英文界面下处理中文,主要需要解决两件事情。首先是中文输入法的问题,其次是中文显示(美观)的问题。


在切换到英文界面之后,编辑配置文件 /etc/environment,增加或者修改相应的 locale 设置:

LC_CTYPE="zh_CN.UTF-8"

LC_NUMERIC="en_US.UTF-8"

LC_TIME="en_US.UTF-8"

LC_COLLATE="en_US.UTF-8"

LC_MONETARY="en_US.UTF-8"

LC_MESSAGES="en_US.UTF-8"

LC_PAPER="en_US.UTF-8"

LC_NAME="en_US.UTF-8"

LC_ADDRESS="en_US.UTF-8"

LC_TELEPHONE="en_US.UTF-8"

LC_MEASUREMENT="en_US.UTF-8"

LC_IDENTIFICATION="en_US.UTF-8"

LC_ALL=

LANGUAGE="en_US:en"

GST_ID3_TAG_ENCODING=GBK

LANG=en_US.UTF-8

这样使得在需要使用中文的地方能够良好的表现中文,而其他地方能够展现英文。


然后编辑 X 的输入法配置文件 /etc/X11/Xsession.d/95input(如果没有这个文件,就创建一个):

export XIM=SCIM

export XMODIFIERS=@im=SCIM

scim -d

(这一步在安装 SCIM 就应该做好了的。)


最后编辑字体配置文件 /etc/fonts/fonts.conf。我使用的中文字体是 Apple OS X 下的华文黑体,因而需要在此文件中定义一段:

<!--

OS X Heiti

-->

<match target="font">

<test name="family">

<string>STHeiti</string>

</test>

<edit name="hinting">

<bool>false</bool>

</edit>

</match>

然后在此配置文件中找到

<!--

Mark common families with their generics so we'll get

something reasonable

-->

这 么一段,在日文字体前加上你所要使用的中文字体(因为很多日文汉字也可以用来表示汉文汉字,所以如果不做这一步的话,在浏览网页的时候就会容易出现两种语 言的汉字混合在一起显示的情况)。比如说 Kochi Mincho 明显的是日文字体的配置,那我们就可以在此之前加上

<family>STHeiti</family>

的配置。之后还需要修改

<!--

Provide required aliases for standard names

-->

下面的相应配置。


修改完毕之后,重启 X Server,重新登录就 OK 了。

把rpm包转成deb包的工具

apt-get install alien

alien -d 把rpm包转成deb包

alien -i name-of-the-pakage.rpm直接就能装上rpm


おすすめURL:88250的灰色天空

temp

打造实用的Ubuntu

RMVB

TeXlive2007安装

AMD64问题

Firefox浏览部分网页字体模糊的解决方案及字体美化方案说明

[火星][Feisty]AMD64 播放 RMVB

amd64中Ubuntu安装使用全记录 这里有一个很好的Ubuntu圈子

Ubuntu安装笔记(未完--因最近工作原因忙未整理)

http://hi.baidu.com/stringtheory/blog/item/572bf9191148a17bdab4bda9.html

Ubuntu 7.04の設定集

Ubuntu 7.04 amd64 版本flash问题解决方案

使用moziila-flash的插件,似乎也能运行flash,但功能不全。使用nspluginwrapper更好一点。

nspluginwrapper is an Open Source compatibility plugin for Netscape 4 (NPAPI) plugins. That is, it enables you to use plugins on platforms they were not built for. For example, you can use the Adobe Flash plugin on Linux/x86_64, NetBSD and FreeBSD platforms.


1:安装一系列不可或缺的软件包。这些包是为了能够和32位相兼容
sudo apt-get install ia32-libs ia32-libs-gtk linux32 lib32asound2

2:去nspluginwrapper主页下载最新的rpm包,然后使用alien转换成deb包。
sudo apt-get install alien
sudo alien nspluginwrapper-VerNum.x86_64.rpm
sudo alien nspluginwrapper-i386-VerNum.x86_64.rpm

sudo dpkg -i nspluginwrapper-VerNum.x86_64.deb
sudo dpkg -i nspluginwrapper-i386-VerNum.x86_64.deb

3:去adobe下载flash 9.

4:untar下载文件。将libflashplayer.so和flashplayer.xpt复制到~/.mozilla/plugins/,执行
nspluginwrapper -i /usr/lib/mozilla/plugins/libflashplayer.so

5:(一)if it is all right, it would have to return to the prompt without no messages in the folder .mozilla/plugins/ 。in our /home we can see the file “npwrapper.libflashplayer.so”, created from the previous command.

Copy it into the folder /usr/lib/mozilla/plugins/ [Epiphany works] and create a link (or copy it) into the folder /usr/lib/mozilla-firefox/plugins/ [now Firefox works, too]

(二)nspluginwrapper -l
若返回:
/home/'whoami'/.mozilla/plugins/npwrapper.libflashplayer.so
Original plugin: .mozilla/plugins/libflashplayer.so
Wrapper version string: 0.9.91.2
类似信息,则OK。

Ubuntu 7.04 + Beryl 纯粹是好玩

1:安全第一,首先备份。随着各个模块的升级,安装Nvidia驱动是最容易失败的。
sudo cp /etc/X11/xorg.conf /etc/X11/xorg.conf.backup.beryl-script(安装程序会自动备份的)
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup.beryl-script


2:安装Nvidia驱动
a:使用Envy(简单,但是有时出现错误时,无法定位)
1:下载Envy(推荐使用稳定版)
2:是deb包,双击安装就可以了。然后选择安装Nvidia驱动,就可以搞定。

b:手动安装
根据自己的显卡决定使用9755/nvidia-glx-new9631/nvidia-glx还是8762/nvidia-glx-legacy

$sudo apt-get install nvidia-glx-new(nvidia-glx/nvidia-glx-legacy)
$sudo nvidia-xconfig --add-argb-glx-visuals --composite
ctrl+alt+backspace

c:手动
1. 到http://www.nvidia.com/ 下载驱动
2. 删除原来的驱动(如果你装过驱动)
sudo apt-get --purge remove nvidia-glx
3. 备份当前的显示设置,这样可以在驱动安装失败时恢复到原来的设置
sudo cp /etc/X11/xorg.conf.backup /etc/X11/xorg.conf
4. 安装驱动程序编译环境
sudo apt-get install build-essential linux-headers-`uname -r`
5. 禁止系统使用默认的驱动
sudo gedit /etc/default/linux-restricted-modules-common
在最后的双引号中添加nv,即“”改成“nv”
6. 按Ctrl+Alt+F1,登录,停止gdm或kdm
sudo /etc/init.d/gdm(kdm) stop
7. 进入下载的驱动安装文件 nvidia-linux-x86-*.run所在目录(请确定xorg-dev软件包已经安装,编译过程中可能会用到)
sudo sh nvidia-linux-x86-*.run
如果提示缺少某某模块(modules),询问是否上网下载,选no;
8. 安装完成后,启动gdm
sudo /etc/init.d/gdm start

d:进入“系统”->“系统管理”->“受限驱动管理器”找到你的显卡,把那个框点成对号,会提示你安装显卡驱动,然后按照提示一步一步安装完毕,重启即可。


3:安装Beryl
a:加入源列表
你需要编辑:/etc/apt/sources.list
sudo vi /etc/apt/sources.list 或者 sudo gedit /etc/apt/sources.list
加入下面的几行(i386&64位都是)
deb http://ubuntu.beryl-project.org feisty main
保存文件并退出
在终端下输入下面的命令,获取更新Key
wget http://ubuntu.beryl-project.org/root@lupine.me.uk.gpg -O- | sudo apt-key add -
接下来再输入升级
sudo apt-get update

b:安装Beryl
在终端下输入
sudo apt-get install beryl emerald-themes beryl-manager

now,enjoy it


注意:
不知道为什么,装驱动要看RP的(应该说我是知其然不知其所以然)。经常会碰到一些问题。
1:安装驱动后,使用Nvidia——setting的时候,改变分辨率也选择了保存到xorg.conf文件中,但是GDM重启之后,分辨率又恢复了。这个时候需要两边同时改,用Nvidia——setting修改之后,在xorg.conf中的把你需要的分辨率添加到所有depth的modes分辨率选项中。
2:启用beryl之后,窗体的标题栏没有了,最小最大和关闭按钮都没有了,只是因为$sudo nvidia-xconfig --add-argb-glx-visuals 这一句未生效。需要手动在xorg.conf中在Device一节中找到 "nvidia" 所在行,在该行后启用 ARGBGLXVisuals。Option "AddARGBGLXVisuals" "True"
3:xorg.conf中在Device一节中找到 "nvidia" 所在行,在该行后添加Option "NoLogo" 可以不显示Nvidia Logo


也可以参考wiki的beryl自动安装脚本

星期日, 五月 20, 2007

Ubuntu 7.04 字体美化

一:使用STHeiti华文黑体+Lucida Grande(苹果系统标准字体组合)解决方案
1:首先下载 STHeiti华文黑体Lucida Grande,然后把它们解压后复制到/usr/share/fonts/truetype里面。

2:sudo fontconfig-voodoo -f -s zh_CN命令建立连接后,修改language-selector.conf文件。
a:设置中文为SHHeiti华文黑体
找到
<family>Bitstream Vera Serif</family>
在其下面添加一行
<family>STHeiti</family>。

b:设置英文使用Lucida Grande
“系统-首选项-字体”里面选择Lucida Grande字体,大小为10pt。(如果不喜欢Lucida Grande来做英文字体,推荐使用系统自带的Bitstream Vera Serif。)
c:sudo fc-cache -f -v 命令刷新一下字体缓存

3:调整字体渲染效果
按照上面的方法弄出来的字体效果很不理想,一些笔画多的字都重叠到一起了,那么我们就需要调整字体的渲染效果。
a:打开“系统-首选项-字体”面板,在“字体渲染”选项中,RTC选择“最佳形状”,LCD可以选择“次象素平滑”。
b:打开sudo gedit /etc/fonts/fonts.conf文件,加入下面一段:
<match target="font">
<test name="family">
<string>STHeiti</string>
</test>
<edit name="hinting">
<bool>false</bool>
</edit>

4:重启GNOME看效果(Ctrl + Alt + BackSpace)。


注》使用mac上的华文黑体来替换ubuntu中文字型时,英文字体有点模糊(带有毛边),原因是在“系统-首选项-字体”这里关掉了所有字体的微调。
关于字体渲染引擎微调的解释:

Hinting 用来最佳化字型显示的方法。由于屏幕的像素有限,向量字型的缩放需要有更多的考虑, 例如当一条线位在两个像素格子中间时, 该取左边的格子还是右边的格子? 如果这方面的控制没有做好,就常常会出现字型的衬线没有对齐,或是小字歪七扭八的情况。 Hinting 是额外的信息, 它告诉 renderer 该如何处理这些细节的部份,使得向量字在小字的时候能够好看。也因此 Hinting 是非常费时费人力的工作,TrueType 字型很多,但是有良好 Hinting 的字型不多。拙劣的 Hinting 就会让字变得很难看。 如果要拿来看中文的小字的话,目前最好把 hinting 关掉(中文字型大部分把 hinting 关掉会有比较令人高兴的外观,除了新细明体是一定要打开以外)

如果STHeiti(华文黑体)打开微调,很多字都会挤到一堆,相信mac下也关掉了这个字体的微调功能。然而我们使用的英文字体又需要打开微调,才能让文字看起来更圆滑漂亮、没有毛边。所以采用第三步的方法。而不是在“系统-首选项-字体”里关闭微调。

附录:match的一些属性说明
family - String - 字体的名称, 如 Arial, Bitstream Vera Sans…
style - String - 字体的 style, 像是 Regular, Bold, Italic…
spacing - Int - 字体的宽度,Proportional是有不同的宽度, monospace 是单一的宽度。
antialias - Bool - 字体渲染是否采用抗锯齿功能。
hinting - Bool - 渲染引擎是否采用微调 。
autohint - Bool - 决定是否要用 Freetype 自己的 hint 方法来 hint 字型。
rgba - Bool - 决定是否要用 subpixel 的方式来画字。
详情参照Fontconfig配置详解


sudo fontconfig-voodoo -f -s zh_CN
这个命令其实就是根据你指定的参数,将/usr/share/language-selector/fontconfig下面的文件链接到/etc/fonts/下面,比如
代码:
fontconfig-voodoo -S zh_CN
就等于代码:
sudo ln -sf /usr/share/language-selector/fontconfig/zh_CN /etc/fonts/language-selector.conf

再看看/etc/fonts/fonts.conf有这么一段
代码:

<!-- Load local ubuntu-specific language custom file -->
<include ignore_missing="yes">language-selector.conf</include>

fontconfig就会将选择语言的配置读取到了,自然STHeiti就发挥作用了

Ubuntu 7.10 黑体解决方案

星期三, 五月 16, 2007

如何在重装Windows后,重新安装Grub引导linux

我们可能在安装WIN时,把GRUB或者LILO从MBR上清除。如果在没有系统引导软盘只有安装盘的情况下,所采取的解决办法如下:

一:

1.把安装盘的第一张放到光驱,然后重新启动机器,在BOIS中把系统用光驱来引导。
2.等安装界面出来后,按[F4]键,也就是linux rescue模式。
3.一系列键盘以及几项简单的配制,过后就[继续]了。。。这个过程,我不说了,比较简单。
4.然后会出现这样的字符
sh#
sh#grub
会出现这样的字符
grub>
我们就可以在这样的字符后面,输入
grub>root (hdX,Y)
grub>setup (hd0)
如果成功会有一个successful......
请留意root和(hdX,Y)之间有一个空格,这里的X,如果是一个盘,就是0,如果你所安装的linux的根分区在第二个硬盘上,那X就是1了;Y,就是装有linux系统所在的根分区。 setup (hd0)就是把GRUB写到硬盘的MBR上。

附注:这里的X一般就是0,至于Y是多少,假如你的根分区安装在hda8上,那么Y就是7,以此类推,如果你不知道装在什么分区也可以按TAB键补齐.

二:另一种方法.

在boot:处输入linux rescue回车。语言选中文,不用配置网络,一直继续,到提示符处,输入
chroot /mnt/sysimage

然后
grub-install /dev/hda(安装在mbr)

附注:这次我就是按照这种方法修复的grub,但是遇到一个问题,重新启动的时候依然没有看见grub界面,原来是我修改了分区,原来的启动是root (hd0,8),现在是root (hd0,7),而在/boot/grub/menu.lst里面却没有改,还是原来的root (hd0,8),启动的时候当然找不到了,所以修改之后就OK了.

Grub配置杂谈

1、一个GRUB配置文件
2、解读grub.conf文件
3、配置grub
4、GRUB的交互性
5、常见grub除错方法的思路

1 一个GRUB配置文件
基于本例的分区如下:
hda 15G
hda1 8G / RED HAT LINUX8.0
hda5 7G /home
hdc 20G
hdc1 6.4G WinXP
hdc5 6.4G
hdc6 6.4G
hdc7 6.4G
#fdisk -l
# Disk /dev/hdc: 255 heads, 63 sectors, 2434 cylinders
Units = cylinders of 16065 * 512 bytes

Device Boot Start End Blocks Id System
/dev/hdc1 * 1 894 7181023+ b Win95 FAT32
/dev/hdc2 895 2434 12370050 f Win95 Ext'd (LBA)
/dev/hdc5 895 1787 7172991 b Win95 FAT32
/dev/hdc6 1788 2434 5196996 b Win95 FAT32

Disk /dev/hda: 255 heads, 63 sectors, 1867 cylinders
Units = cylinders of 16065 * 512 bytes

Device Boot Start End Blocks Id System
/dev/hda1 * 1 1020 8193118+ 83 Linux
/dev/hda2 1021 1802 6281415 83 Linux
/dev/hda3 1803 1867 522112+ 82 Linux swap

grub.conf,这个文件位于;/boot/grub/grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You do not have a /boot partition. This means that
# all kernel and initrd paths are relative to /, eg.
# root (hd0,0)
# kernel /boot/vmlinuz-version ro root=/dev/hda1
# initrd /boot/initrd-version.img
#boot=/dev/hda
default=0
timeout=3
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
title Red Hat Linux (2.4.18-14)
root (hd0,0)
kernel /boot/vmlinuz-2.4.18-14 ro root=LABEL=/
initrd /boot/initrd-2.4.18-14.img
title Microsoft Windows XP
map (hd0) (hd1)
map (hd1) (hd0)
root (hd1,0)
chainloader (hd1,0)+1
makeactive
boot


2 解读grub.conf文件

我们将来看看grub.conf文件内语句,(注:...)内的东西是我们的解读内容.
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You do not have a /boot partition. This means that
# all kernel and initrd paths are relative to /, eg.
# root (hd0,0)
# kernel /boot/vmlinuz-version ro root=/dev/hda1
# initrd /boot/initrd-version.img
#boot=/dev/hda (注:以上以符号井"#"开头的行表示被注释掉,没有任何意义)
default=0 (注:默认的操作系统就是由default控制的。default后加一个数字n,表明是第 n+1个。需要注意的是,GRUB中,计数是从0开始的,第一个硬盘是hd0,第一 个软驱是fd0,等等。所以,default 0 表示默认的操作系统在这儿是 Red Hat Linux (2.4.18-14)如果你修改成1就是WinXP了)
timeout=3 (注:timeout表示默认等待的时间,这儿是3秒钟。超过3秒,用户还没有作出选 择的话,系统将自动选择默认的操作系统;当然你可以改成任何你乐意的时间)
splashimage=(hd0,0)/boot/grub/splash.xpm.gz (注:指定开机画面文件splash.xpm.gz的位置,也可以splash /boot/logo/800x600x8.img)
title Red Hat Linux (2.4.18-14) (注:表示Red Hat Linux的菜单项)
root (hd0,0) (注:表示第一个硬盘第一个分区,这里的root和系 统内的root不是一码事!详细如下说明)
kernel /boot/vmlinuz-2.4.18-14 ro root=LABEL=/ (注:指定内核的位置,详细说明如下 文)
initrd /boot/initrd-2.4.18-14.img (注:初始化)
title Microsoft Windows XP (注:表示Microsoft Windows XP的菜单项)
map (hd0) (hd1) (注:map是命令,详细如下)
map (hd1) (hd0)
root (hd1,0) (注:这是指第二个硬盘(从硬盘)上第一个分区)
chainloader (hd1,0)+1 (注:链式装入器,装入一个扇区的数据然后把引导 权交给它。详细说明如下)
makeactive
boot

(注:在 Linux 中,当谈到 "root" 文件系统时,通常是指主 Linux 分区。但是,GRUB 有它自己的 root 分区定义。GRUB 的 root 分区是保存 Linux 内核的分区。这可能是您的正式 root 文件系统,也可能不是。我们讨论的是 GRUB,需要指定 GRUB 的 root 分区。进入 root 分区时,GRUB 将把这个分区安装成只读型,这样就可以从该分区中装入 Linux 内核。GRUB 的一个很“酷”的功能是它可以读取本机的 FAT、FFS、minix、ext2 和 ReiserFS 分区.到目前为止,您可能会感到一点疑惑,因为 GRUB 所使用的硬盘/分区命名约定与 Linux 使用的命名约定不同。在Linux 中,第一个硬盘的第五个分区称作 "hda5"。而 GRUB 把这个分区称作 "(hd0,4)"。GRUB 对硬盘和分区的编号都是从 0 开始计算。另外,硬盘和分区都用逗号分隔,整个表达式用括号括起。现在,可以发现如果要引导 Linux 硬盘 hda5,应输入 "root (hd0,4)"。
知道了内核在哪儿,还要具体指出哪个文件是内核文件,这就是kernel的工作。
kernel /boot/vmlinuz-2.4.18-14 ro root=LABEL=/说明/boot/vmlinuz-2.4.18-14就是要载入的内核。后面的都是传递给内核的参数。root=LABEL=/就是linux的硬盘分区表示法,ro是readonly的意思。initrd用来初始的linux image,并设置相应的参数。
命令map:当你有两块硬盘,一个无法从第二块硬盘启动的操作系统,例如Windowsxp,就可以使用map命令.你能够将hd0映射为hd1,将hd1映射为hd0。换句话说,你可以虚拟的交换两个硬盘而启动所需要的操作系统 。命令形式如下:
grub> map (hd0) (hd1)
grub> map (hd1) (hd0)
GRUB 使用了“链式装入器”(chainloader)。链式装入器从分区 (hd1,0) 的引导记录中装入winxp自己的引导装入器,然后引导它。这就是这种技术叫做链式装入的原因 -- 它创建了一个从引导装入器到另一个的链。这种链式装入技术可以用于引导任何版本的 DOS 或 Windows。
GRUB的配置文件要简单就这么简单,如果你要更个性化一点,试一试把“color light-gray/blue ”加在default语句的下面,下一次启动GRUB时,看看有什么变化,再试一试“color light-blue/red",惊喜吗? 有趣吧! )


3 配置grub
grub启动时会在/boot/grub/中寻找一个名字为menu.lst的配置文件,如果找不到此文件则不进入菜单模式而直接进入命令行模式。
现在,我们来看一下如何在启动后进入各种操作系统,如何建立menu.conf文件。我们就从GRUB支持的启动过程开始。可以有两种方法来完成启动过程:
·A.通过调用内核本地启动
·B.连续启动或者将控制转给另一个引导器
A模式启动过程
1.配置跟设备或者告诉GRUB你的根文件系统。
2.告诉GRUB你的内核影像的位置,然后将参数传送给内核。
3.重新启动,试一下。
为了启动Linux,将内核以bzImage的文件名放在/boot/目录中,跟文件系统是
/dev/hda1,或者GRUB中的(hd0,0)。启动过程如下:
1.root (hd0,0) [This sets the root partition]
2.kernel /boot/bzImage root=/dev/hda1 [This sets the kernel]
B模式启动过程(这种模式假设当前的分区中安装了另一个启动管理器,例如LILO
或者NTLDR):
1.设置根分区但不要安装它
2.激活这个分区
3.配置需要启动的分区的第一个扇区
4.重新启动,看一下效果。
我们在试试启动安装在/dev/hdc1或者(hd1,0)的windows。启动windows的过程如下:
1.rootnoverify (hd1,0)
2.makeactive
3.chainloader +1 [+1 sets the first sector of the current root
partition]
4.boot [transfers the control and quits GRUB]
menu.conf文件:它用于建立启动多操作系统时的菜单。建立menu.conf并不难。它使用简单的英语,就象你在这一节看到的那样。
所有的菜单项目都以没有逗号分隔的“title TITLENAME”开头。你可以随意设置
TITLENAME。
设置Linux启动菜单步骤如下:
1.设置标题
2.设置根分区
3.设置内核的相应参数
4.启动
一个菜单例子:
title Red Hat Linux (2.4.18-14)
root (hd0,0)
kernel /boot/vmlinuz-2.4.18-14 ro root=LABEL=/
initrd /boot/initrd-2.4.18-14.img
前面有#的行是一个注释。
建立启动Windows 或者 DOS的菜单:
title Windoze
rootnoverify (hd0,0)
makeactive
chainloader +1
boot
#----
又或者:
title Microsoft Windows XP
map (hd0) (hd1)
map (hd1) (hd0)
root (hd1,0)
chainloader (hd1,0)+1
makeactive
boot
----
注意:root和rootnoverify都是一样的,把rootnoverify改成root也行。不过经过实践来看。有时引导win时,系统安装好后,是rootnoverify (hdX.Y)这样形式的,这样会出现windows起不来,出现什么windows什么文件损坏的情况。这时,我们就要把在grub中,引导windows的那段中的rootnoverify改为root
root英文的意思就是根的意思,在这里是让linux知道自己所处的位置,也就是我们所安装linux的/根分区所在的位置 。


4 GRUB的交互性

GRUB 最好的优点之一就是其强健的设计 -- 在不断使用它时请别忘了这点。如果更新内核或更改它在磁盘上的位置,不必重新安装 GRUB。事实上,如有必要,只要更新 menu.lst 文件即可,一切将保持正常。
只有少数情况下,才需要将 GRUB 引导装入器重新安装到引导记录。首先,如果更改 GRUB root 分区的分区类型(例如,从 ext2 改成 ReiserFS),则需要重新安装。或者,如果更新 /boot/grub 中的 stage1 和 stage2 文件,由于它们来自更新版本的 GRUB,很有可能要重新安装引导装入器。其它情况下,可以不必理睬!
GRUB的最大的特点就是交互性特别强。在开机时,按一下“c”,将进入GRUB 控制台。显示如下:
GRUB version 0.5.96.1 (640K lower / 3072K upper memory)
[ Minimal BASH-like line editing is supported. For the first word, TAB
lists possible command completions. Anywhere else TAB lists the possible
completions of a device/filename. ]
grub>
欢迎使用 GRUB 控制台。现在,再研究命令:
将通过GRUB 控制台绕过lilo来启动RedHat linux,
grub> root (h
现在,按一次 Tab 键。如果系统中有多个硬盘,GRUB 将显示可能完成的列表,从 "hd0" 开始。如果只有一个硬盘,GRUB 将插入 "hd0,"。如果有多个硬盘,继续进行,在 ("hd2") 中输入名称并在名称后紧跟着输入逗号,但不要按 Enter 键。部分完成的 root 命令看起来如下:
grub> root (hd0,
现在,继续操作,再按一次 Tab 键。GRUB 将显示特定硬盘上所有分区的列表,以及它们的文件系统类型。在我的系统中,按 Tab 键时得到以下列表:
grub> root (hd0, (tab,按tab一下键)
Possible partitions are:
Partition num: 0, Filesystem type is fat, partition type 0x6
Partition num: 2, Filesystem type is ext2fs, partition type 0x83
Partition num: 4, Filesystem type unknown, partition type 0x7
Partition num: 5, Filesystem type is ext2fs, partition type 0x83
Partition num: 6, Filesystem type is fat, partition type 0xb
Partition num: 7, Filesystem type is fat, partition type 0xb
Partition num: 8, Filesystem type is ext2fs, partition type 0x83
Partition num: 9, Filesystem type unknown, partition type 0x82
如您所见,GRUB 的交互式硬盘和分区名称实现功能非常有条理。这些,只需要好好理解 GRUB 新奇的硬盘和分区命名语法,然后就可以继续操作了
grub> root (hd0,
现在已安装了 root 文件系统,到装入内核的时候了
grub> kernel /boot/vmlinuz-2.4.2 root=/dev/hda5 ro
[Linux-bzImage, setup=0x1200, size=0xe1a30]
您已经安装了 root 文件系统并装入了内核。现在,可以引导了。只要输入 "boot",Linux 引导过程就将开始。是不是很cool啊,GRUB的menu.lst更像一个linux下的脚本程序。



5 常见grub除错方法的思路
首先进去Linux的rescue模式!
用软盘或光盘启动,然后在启动的提示符输入:linux rescue
按照提示进入一个Shell状态,你可以到/mnt/下面看到一个sysimage这么目录,进去以后,就是你安装linux的/分区.
使用命令将根分区变为当前目录的根分区:chroot /mnt/sysimage
然后转到/sbin/这个目录中.
使用fdisk -l 显示当前分区情况,然后使用#grub-install /dev/hdx(x为你使用的是那块硬盘安装的,一般情况下是hda)
使用exit推出chroot,再使用exit退出linux rescue模式,系统将重新启动!取出光盘,应该可以看到grub安装好了.
在具体的环境中,编辑/boot/grub/grub.conf文件和menu.lst文件


简化:
1.安装盘启动
2.进入linux rescue模式
3.一系列键盘以及几项简单的配制,过后就[继续]了。。。这个过程,我不说了,比较简单。
4.然后会出现这样的字符
sh#
5. sh#grub
会出现这样的字符:grub>我们就可以在这样的字符后面,输入:grub>root (hdX,Y)
grub>setup (hd0)
如果成功会有一个successful......
这里的X,如果是一个盘,就是0,如果你所安装的linux的根分区在第二个硬盘上,那X就是1了;Y,就是装有linux系统所在的根分区。 setup (hd0)就是把GRUB写到硬盘的MBR上。

其他:
grub菜单项丢失,只有字符grub>时的处理方法:
grub>cat (hd0,0) /root/grub/grub.conf(为了看参数。)
grub>root (hd0,1)
grub>kernel (hd0,0) /boot/vmlinuz-2.4.18-11 ro root=/dev/hda2
grub>initrd (hd0,0) /boot/initrd-2.4.18-11.img
grub>boot
如果看不明白,可以参考后面的命令慢慢看,这里不做注释,促使大家学习,哈哈

98先装,用的是单独的硬盘,4.3G,那时候,LINUX8还没有到我手中
后来到了,在家中安装好了,选择GRUB,就会有DOS的一个菜单,我的是在主分区
到了公司,把LINUX挂在第一个盘的位置,那个盘挂在第四个盘的位置(这个无所谓)
然后GRUB配置如下
default=0
timeout=10
splashimage=(hd0,0)/grub/splash.xpm.gz
title Red Hat Linux (2.4.18-14)
root (hd0,0)
kernel /vmlinuz-2.4.18-14 ro root=LABEL=/
initrd /initrd-2.4.18-14.img
title DOS
rootnoverify (hd1,0)
makeactive
chainloader (hd1,0)+1
map (hd0) (hd1)
map (hd1) (hd0)
boot


下面是GRUB的可用命令列表:
#大部分命令我们不常用,而且我也没有每个都试验!

关于下面将要用到的三种模式的解释:
GRUB的用户界面有三种:命令行模式,菜单模式和菜单编辑模式
  (a) 命令行模式:
  进入命令行模式后GRUB会给出一个命令提示符`grub>`,此时就可以键入命令,按回车执行。此模式下可执行的命令是在menu.lst中可执行的命令的一个子集。此模式下允许类似于Bash shell的命令行编辑功能:
或 光标右移一个字符

或 光标左移一个字符

到这一行的开头

或 到行尾

或 删除光标处的字符

或 删除光标左边的字符

删除光标右边的所有字符(包括光标处的字符)

删除光标左边的所有字符(包括光标处的字符)

恢复上次删除的字符串到光标位置

或 历史记录中的上一条命令

或 历史记录中的下一条命令

  在命令行模式下键有补全命令的功能,如果你敲入了命令的前一部分,键入系统将列出所有可能以你给出的字符串开头的命令。如果你给出了命令,在命令参数的位置按下键,系统将给出这条命令的可能的参数列表,具体的可用命令集将在后面给出。

  (b) 菜单模式
  当存在文件/boot/grub/menu.lst文件时系统启动自动进入此模式。菜单模式下用户只需要用上下箭头来选择他所想启动的系统或者执行某个命令块,菜单的定义在menu.lst文件中,你也可以从菜单模式按键进入命令行模式,并且可以按键从命令行模式返回菜单模式。菜单模式下按键将进入菜单编辑模式。

  (c) 菜单编辑模式
  菜单编辑模式用来对菜单项进行编辑改变,其界面和菜单模式的界面十分类似,不同的是菜单中显示的是对应某个菜单项的命令列表。如果在编辑模式下按下,则取消所有当前对菜单的编辑并回到菜单模式下。在编辑模式下选中一个命令行,就可以对这条指令进行修改,修改完毕后按下,GRUB将提示你确认并完成修改。如果你想在当前命令列表中增加一条命令,按在当前命令的下面增加一条指令,按在当前命令前处增加一条指令。按删除一条指令。

仅用于菜单的命令(不包括菜单项内部的启动命令)

default num
设置菜单中的默认选项为num(默认为0,即第一个选项),超时将启动这个选项

fallback num
如果默认菜单项启动失败,将启动这个num后援选项。

password passwd new-config-file
关闭命令行模式和菜单编辑模式,要求输入口令,如果口令输入正确,将使用new-config-file
作为新的配置文件代替menu.lst,并继续引导。

timeout sec
设置超时,将在sec秒后自动启动默认选项。

title name ...
开始一个新的菜单项,并以title后的字串作为显示的菜单名。

在菜单(不包括菜单项内部的命令)和命令行方式下都可用的命令

bootp
以BOOTP协议初始化网络设备

color normal [highlight]
  改变菜单的颜色,normal是用于指定菜单中非当前选项的行的颜色,highlight是用于指定当前菜单选项的颜色。如果不指定highlight,GRUB将使用normal的反色来作为highlight颜色。指定颜色的格式是“前景色/背景色”,前景色和背景色的可选列表如下:
* black
* blue
* green
* cyan
* red
* magenta
* brown
* light-gray
下面的颜色只能用于背景色
* dark-gray
* light-blue
* light-green
* light-cyan
* light-red
* light-magenta
* yellow
* white
你可以在前景色前加上前缀"blink-",产生闪烁效果,你可以在menu.lst中加上下面这个选项来改变颜色效果:
title OS-BS like
color magenta/blue black/magenta

device drive file
在GRUB命令行中,把BIOS中的一个驱动器drive映射到一个文件file。你可以用这条命令创建一个磁盘映象或者当GRUB不能真确地判断驱动器时进行纠正。如下
grub> device (fd0) /floppy-image
grub> device (hd0) /dev/sd0
这条命令只能在命令行方式下使用, 是个例外。

dhcp
用DHCP协议初始化网络设备。目前而言,这条指令其实就是bootp的别名,效果和bootp一样。

hide partition
这条指令仅仅对DOS和WINDOWS有用,当在一个硬盘上存在多个DOS/WIN的主分区时,有时需要这条指令隐藏其中的一个或几个分区,即在分区表中设置“隐藏”位。

rarp
用RARP协议初始化网络设备。

setkey to_key from_key
改变键盘的映射表,将from_key映射到to_key,注意这条指令并不是交换键映射,如果你要交换两个键的映射,需要用两次setkey指令,如下:
grub> setkey capslock control
grub> setkey control capslock

其中的键必须是字母,数字或者下面的一些代表某一键的字符串:
`escape', `exclam', `at', `numbersign', `dollar', `percent',
`caret', `ampersand', `asterisk', `parenleft', `parenright',
`minus', `underscore', `equal', `plus', `backspace', `tab',
`bracketleft', `braceleft', `bracketright', `braceright', `enter',
`control', `semicolon', `colon', `quote', `doublequote',
`backquote', `tilde', `shift', `backslash', `bar', `comma',
`less', `period', `greater', `slash', `question', `alt', `space',
`capslock', `FX' (`X' is a digit), and `delete'.
下面给出了它们和键盘上的键的对应关系:
`exclam'=`!'
`at'=`@'
`numbersign'=`#'
`dollar'=`$'
`percent'=`%'
`caret'=`^'
`ampersand'=`&'
`asterisk'=`*'
`parenleft'=`('
`parenright'=`)'
`minus'=`-'
`underscore'=`_'
`equal'=`='
`plus'=`+'
`bracketleft'=`['
`braceleft'=`{'
`bracketright'=`]'
`braceright'=`}'
`semicolon'=`;'
`colon'=`:'
`quote'=`''
`doublequote'=`"'
`backquote'=``'
`tilde'=`~'
`backslash'=`'
`bar'=`|'
`comma'=`,'
`less'=`'
`slash'=`/'
`question'=`?'
`space'=` '

unhide partition
仅仅对DOS/WIN分区有效,清除分区表中的“隐藏”位。

仅用于命令行方式或者菜单项内部的命令

blocklist file
显示文件file在所占磁盘块的列表。

boot
仅在命令行模式下需要,当参数都设定完成后,用这条指令启动操作系统

cat file
显示文件file的内容,可以用来得到某个操作系统的根文件系统所在的分区,如下:
grub> cat /etc/fstab

chainloader [`--force'] file
把file装入内存进行chainload,除了能够通过文件系统得到文件外,这条指令也可以用磁盘块列表的方式读入磁盘中的数据块,如'+1`指定从当前分区读出第一个扇区进行引导。如果指定了`--force`参数,则无论文件是否有合法的签名都强迫读入,当你在引导SCO UnixWare时需要用这个参数。

cmp file1 file2
比较文件的内容,如果文件大小不一致,则输出两个文件的大小,如下:
Differ in size: 0x1234 [foo], 0x4321 [bar]
如果两个文件的大小一致但是在某个位置上的字节不同,则打印出不同的字节和他们的位移:
Differ at the offset 777: 0xbe [foo], 0xef [bar]
如果两个文件完全一致,则什么都不输出。

configfile FILE
将FILE作为配置文件替代menu.lst。

embed stage1_5 device
如果device是一个磁盘设备的话,将Stage1_5装入紧靠MBR的扇区内。如果device是一个FFS文件系统分区的话,则将Stage1_5装入此分区的第一扇区。如果装入成功的话,输出写入的扇区数。

displaymem
显示出系统所有内存的地址空间分布图。

find filename
在所有的分区中寻找指定的文件filename,输出所有包含这个文件的分区名。参数filename应该给出绝对路径。

fstest
启动文件系统测试模式。打开这个模式后,每当有读设备请求时,输出向底层例程读请求的参数和所有读出的数据。输出格式如下:
先是由高层程序发出的分区内的读请求,输出:之后由底层程序发出的扇区读请求,输出:[磁盘绝对扇区偏移] 可以用install或者testload命令关闭文件系统测试模式。

geometry drive [cylinder head sector [total_sector]]
输出驱动器drive的信息。

help [pattern ...]
在线命令帮助,列出符合pattern的命令列表,如果不给出参数,则将显示所有的命令列表。

impsprobe
检测Intel多处理器,启动并配置找到的所有CPU。

initrd file ...
为Linux格式的启动映象装载初始化的ramdisk,并且在内存中的Linux setup area中设置适当的参数。

install stage1_file [`d'] dest_dev stage2_file [addr] [`p'] [config_file] [real_config_file]
这是用来完全安装GRUB启动块的命令,一般很少用到。

ioprobe drive
探测驱动器drive所使用的I/O口,这条命令将会列出所有dirve使用的I/O口。

kernel file ...
装载内核映象文件(如符合Multiboot的a.out,ELF,Linux zImage或bzImage,FreeBSD a.out,NetBSD
a.out等等)。文件名file后可跟内核启动时所需要的参数。如果使用了这条指令所有以前装载的模块都要重新装载。

makeactive
使当前的分区成为活跃分区,这条指令的对象只能是PC上的主分区,不能是扩展分区。

map to_drive from_drive
映射驱动器from_drive到to_drive。这条指令当你在chainload一些操作系统的时候可能是必须的,这些操作系统如果不是在第一个硬盘上可能不能正常启动,所以需要进行映射。如下:
grub> map (hd0) (hd1)
grub> map (hd1) (hd0)

这个就用来对付双硬盘最过瘾!!!哈哈

module file ...
对于符合Multiboot规范的操作系统可以用这条指令来装载模块文件file,file后可以跟这个module所需要的参数。注意,必须先装载内核,再装载模块,否则装载的模块无效。

modulenounzip file ...
同module命令几乎一样,唯一的区别是不对module文件进行自动解压。

pause message ...
输出字符串message,等待用户按任意键继续。你可以用(ASCII码007)使PC喇叭发声提醒用户注意。

quit
退出GRUB shell,GRUB shell类似于启动时的命令行模式,只是它是在用户启动系统后执行/sbin/grub才
进入,两者差别不大。

read addr
从内存的地址addr处读出32位的值并以十六进制显示出来。

root device [hdbias]
将当前根设备设为device,并且试图mount这个根设备得到分区大小。hdbias参数是用来告诉BSD内核在当前分区所在磁盘的前面还有多少个BIOS磁盘编号。例如,系统有一个IDE硬盘和一个SCSI硬盘,而你的BSD安装在IDE硬盘上,此时,你就需要指定hdbias参数为1。

rootnoverify device [hdbias]
和root类似,但是不mount该设备。这个命令用在当GRUB不能识别某个硬盘文件系统,但是仍然必须指定根设备。

setup install_device [image_device]
安装GRUB引导在install_device上。这条指令实际上调用的是更加灵活但是复杂的install指令。如果
image_device也指定了的话,则将在image_device中寻找GRUB的文件映象,否则在当前根设备中查找。

testload file
这条指令是用来测试文件系统代码的,它以不同的方式读取文件file的内容,并将得到的结果进行比较,如果正确的话,输出的`i=X,filepos=Y`中的X,Y的值应该相等,否则就说明有错误。通常这条指令正确执行的话,之后我们就可以正确无误地装载内核。

uppermem kbytes
强迫GRBU认为高端内存只有kbytes千字节的内存,GRUB自动探测到的结果将变得无效。这条指令很少使用,可能只在一些古老的机器上才有必要。通常GRUB都能够正确地得到系统的内存数量。

GRUB三步通

##################
# GRUB的优点 #
##################
GRUB 是引导装入器(boot loader) -- 它负责装入内核并引导 Linux 系统。GRUB 还可以引导其它操作系统,如 ........

##################
# GRUB的优点 #
##################
GRUB 是引导装入器(boot loader) -- 它负责装入内核并引导 Linux 系统。GRUB 还可以引导其它操作系统,如 FreeBSD、NetBSD、OpenBSD、GNU HURD 和 DOS,以及 Windows 95、98、NT 和 2000。尽管引导操作系统看上去是件平凡且琐碎的任务,但它实际上很重要。如果引导装入器不能很好地完成工作或者不具有弹性,那么就可能锁住系统,而无法引导计算机。另外,好的引导装入器可以给您灵活性,让您可以在计算机上安装多个操作系统,而不必处理不必要的麻烦。
GRUB 是一个很棒的boot loader。它有许多功能,可以使引导过程变得非常可靠。例如,它可以直接从 FAT、minix、FFS、ext2 或 ReiserFS 分区读取 Linux 内核。这就意味着无论怎样它总能找到内核。另外,GRUB 有一个特殊的交互式控制台方式,可以让您手工装入内核并选择引导分区。这个功能是无价的:假设 GRUB 菜单配置不正确,但仍可以引导系统。哦,对了 -- GRUB 还有一个彩色引导菜单。

更令人惊讶的是,这是一个自由软件!!!



##################
# GRUB菜单 #
##################
先来看一个例子,这是位于/boot/grub/目录下的menu.lst文件。
此文件将在开机是产生一个菜单,包含有Debian linux,Windows2000,RedHat linux和 Mandrake linux,共四个选择项。我一共分了8个区,一个fat16(0x6),一个ntfs(0x7),三个ext2fs分区(0x83),一个swap分区(0x82)。ntfs用来装win2000,三个ext2fs装了三个linux,c盘fat16分区没有装任何东西。
#例子由此开始

######################
# #
# 一个GRUB configure 的例子 #
# #
######################

timeout 10
default 2


# --> Debian linux <--

title Debian linux
root (hd0,2)
kernel /boot/vmlinuz-2.2.18 root=/dev/hda3 ro
initrd /boot/initrd-2.2.18.gz


# --> Debian END <--

# --> Windows 菜单选项 <--

title Windows2000
root (hd0,0)
chainloader +1

# --> Winddows 结束 <--

# --> RedHat linux 菜单选项 <--

title RedHat linux
root (hd0,8)
chainloader +1 # 在硬盘主引导分区装了lilo,所以也用了chainloader。

# --> RedHat linux 结束 <--

# --> Mandrake linux 菜单选项 <--

title Mandrake linux
root (hd0,5)
kernel /boot/vmlinuz-2.4.3-20mdk root=/dev/hda6 ro
initrd /boot/initrd-2.4.3-20mdk.img

# --> Mandrake linux 结束 <--


#例子到此结束

以符号井"#"开头的行表示被注释掉,没有任何意义。

timeout表示默认等待的时间,这儿是10秒钟。超过10秒,用户还没有作出选择的话,系统将自动选择默认的操作系统。

默认的操作系统就是由default控制的。default后加一个数字n,表明是第n+1个。需要注意的是,GRUB中,计数是从0开始的,第一个硬盘是hd0,第一个软驱是fd0,等等。所以,default 2 表示默认的操作系统在这儿是 Redhat linux。

接下来,正如你所想象的,title表示的是“Debian linux”菜单项。root (hd0,2)表示第一个硬盘,第三个分区。这儿的root 于linux的root分区及其不同,此root非彼root也!

在 Linux 中,当谈到 "root" 文件系统时,通常是指主 Linux 分区。但是,GRUB 有它自己的 root 分区定义。GRUB 的 root 分区是保存 Linux 内核的分区。这可能是您的正式 root 文件系统,也可能不是。我们讨论的是 GRUB,需要指定 GRUB 的 root 分区。进入 root 分区时,GRUB 将把这个分区安装成只读型,这样就可以从该分区中装入 Linux 内核。GRUB 的一个很“酷”的功能是它可以读取本机的 FAT、FFS、minix、ext2 和 ReiserFS 分区。

到目前为止,您可能会感到一点疑惑,因为 GRUB 所使用的硬盘/分区命名约定与 Linux 使用的命名约定不同。在 Linux 中,第一个硬盘的第五个分区称作 "hda5"。而 GRUB 把这个分区称作 "(hd0,4)"。GRUB 对硬盘和分区的编号都是从 0 开始计算。另外,硬盘和分区都用逗号分隔,整个表达式用括号括起。现在,可以发现如果要引导 Linux 硬盘 hda5,应输入 "root (hd0,4)"。

知道了内核在哪儿,还要具体指出哪个文件是内核文件,这就是kernel的工作。
kernel /boot/vmlinuz-2.2.18 root=/dev/hda3 ro说明/boot/vmlinuz-2.2.18 就是要载入的内核。后面的都是传递给内核的参数。root=/dev/hda3就是linux的硬盘分区表示法,ro是以readonly的意思。
initrd用来初始的linux image,并设置相应的参数。

是不是感觉很简单啊!再来看一看windows的定义段吧。
这里,我添加了一项来引导 Windows2000。要完成此操作,GRUB 使用了“链式装入器”(chainloader)。链式装入器从分区 (hd0,0) 的引导记录中装入 win2000 自己的引导装入器,然后引导它。这就是这种技术叫做链式装入的原因 -- 它创建了一个从引导装入器到另一个的链。这种链式装入技术可以用于引导任何版本的 DOS 或 Windows。

我的RedHat linux在硬盘主引导分区装了lilo,所以也用了chainloader。

GRUB的配置文件要简单就这么简单,如果你要更个性化一点,试一试把“color light-gray/blue ”加在default语句的下面,下一次启动GRUB时,看看有什么变化,再试一试“color light-blue/red",惊喜吗? 有趣吧!

######################
# GRUB的交互性 #
######################




GRUB 最好的优点之一就是其强健的设计 -- 在不断使用它时请别忘了这点。如果更新内核或更改它在磁盘上的位置,不必重新安装 GRUB。事实上,如有必要,只要更新 menu.lst 文件即可,一切将保持正常。

只有少数情况下,才需要将 GRUB 引导装入器重新安装到引导记录。首先,如果更改 GRUB root 分区的分区类型(例如,从 ext2 改成 ReiserFS),则需要重新安装。或者,如果更新 /boot/grub 中的 stage1 和 stage2 文件,由于它们来自更新版本的 GRUB,很有可能要重新安装引导装入器。其它情况下,可以不必理睬!

GRUB的最大的特点就是交互性特别强。在开机时,按一下“c”,将进入GRUB 控制台。显示如下:

GRUB version 0.5.96.1 (640K lower / 3072K upper memory)

[ Minimal BASH-like line editing is supported. For the first word, TAB
lists possible command completions. Anywhere else TAB lists the possible
completions of a device/filename. ]

grub>

欢迎使用 GRUB 控制台。现在,再研究命令:
我将通过GRUB 控制台绕过lilo来启动RedHat linux,

grub> root (h

现在,按一次 Tab 键。如果系统中有多个硬盘,GRUB 将显示可能完成的列表,从 "hd0" 开始。如果只有一个硬盘,GRUB 将插入 "hd0,"。如果有多个硬盘,继续进行,在 ("hd2") 中输入名称并在名称后紧跟着输入逗号,但不要按 Enter 键。部分完成的 root 命令看起来如下:

grub> root (hd0,

现在,继续操作,再按一次 Tab 键。GRUB 将显示特定硬盘上所有分区的列表,以及它们的文件系统类型。在我的系统中,按 Tab 键时得到以下列表:

grub> root (hd0, (tab,按tab一下键)
Possible partitions are:
Partition num: 0, Filesystem type is fat, partition type 0x6
Partition num: 2, Filesystem type is ext2fs, partition type 0x83
Partition num: 4, Filesystem type unknown, partition type 0x7
Partition num: 5, Filesystem type is ext2fs, partition type 0x83
Partition num: 6, Filesystem type is fat, partition type 0xb
Partition num: 7, Filesystem type is fat, partition type 0xb
Partition num: 8, Filesystem type is ext2fs, partition type 0x83
Partition num: 9, Filesystem type unknown, partition type 0x82

如您所见,GRUB 的交互式硬盘和分区名称实现功能非常有条理。这些,只需要好好理解 GRUB 新奇的硬盘和分区命名语法,然后就可以继续操作了
grub> root (hd0,8)
现在已安装了 root 文件系统,到装入内核的时候了

grub> kernel /boot/vmlinuz-2.4.2 root=/dev/hda5 ro
[Linux-bzImage, setup=0x1200, size=0xe1a30]

您已经安装了 root 文件系统并装入了内核。现在,可以引导了。只要输入 "boot",Linux 引导过程就将开始。是不是很cool啊,GRUB的menu.lst更像一个linux下的脚本程序。


#####################
# GRUB启动盘 #
#####################
要制作引导盘,需执行一些简单的步骤。首先,在新的软盘上创建 ext2 文件系统。然后,将其安装,并将一些 GRUB 文件复制到该文件系统,最后运行 "grub" 程序,它将负责设置软盘的引导扇区。准备好了吗?

将一张空盘插入 1.44MB 软驱,输入:

# mke2fs /dev/fd0
创建了 ext2 文件系统后,需要安装该文件系统:

# mount /dev/fd0 /mnt/floppy
现在,需要创建一些目录,并将一些关键文件(原先安装 GRUB 时已安装了这些文件)复制到软盘:

# mkdir /mnt/floppy/boot
# mkdir /mnt/floppy/boot/grub
# cp /boot/grub/stage1 /mnt/floppy/boot/grub
# cp /boot/grub/stage2 /mnt/floppy/boot/grub
再有一个步骤,就能得到可用的引导盘。

在linux bash中,从 root 用户运行“grub”,该程序非常有趣并值得注意,因为它实际上是 GRUB 引导装入器的半功能性版本。尽管 Linux 已经启动并正在运行,您仍可以运行 GRUB 并执行某些任务,而且其界面与使用 GRUB 引导盘或将 GRUB 安装到硬盘 MBR 时看到的界面(即GRUB控制台)完全相同。
在 grub> 提示符处,输入:

grub> root (fd0)
grub> setup (fd0)
grub> quit

现在,引导盘完成了。
如果要把GRUB装到硬盘上,也很容易。这个过程几乎与引导盘安装过程一样。首先,需要决定哪个硬盘分区将成为 root GRUB 分区。在这个分区上,创建 /boot/grub 目录,并将 stage1 和 stage2 文件复制到该目录中,可以通过重新引导系统并使用引导盘,或者使用驻留版本的 GRUB 来执行后一步操作。在这两种情况下,启动 GRUB,并用 root 命令指定 root 分区。例如,如果将 stage1 和 stage2 文件复制到 hda5 的 /boot/grub 目录中,应输入 "root (hd0,4)"。接着,决定在哪里安装 GRUB -- 在硬盘的 MBR,或者如果与 GRUB 一起使用另一个“主”引导装入器,则安装在特定分区的引导记录中。如果安装到 MBR,则可以指定整个磁盘而不必指定分区,如下(对于 hda):

grub> setup (hd0)

如果要将 GRUB 安装到 /dev/hda5 的引导记录中,应输入:

grub> setup (hd0,4)

现在,已安装 GRUB。引导系统时,应该立即以 GRUB 的控制台方式结束(如果安装到 MBR)。现在,应创建引导菜单,这样就不必在每次引导系统时都输入那些命令。



小结:在这里只是介绍了 GRUB 的一部分。例如,可以使用 GRUB 来执行网络引导,引导 BSD 文件系统,或更多操作。另外,GRUB 有许多配置和安全性命令也很有用。如需所有 GRUB 功能的完整描述,请阅读 GRUB 出色的 GNU 文档。只要在 bash 提示中输入 "info grub" 就可以阅读该文档。


有用的一些信息:xosl是一个支持鼠标的图形界面boot loader,可以于system command和boot manager相比,
网址是www.xosl.org。

GRUB的下载:ftp://alpha.gnu.org/gnu/grub/


GRUB入门 http://www.linuxfans.org/nuke/modules.php?name=News&file=article&op=view&sid=921

用NTLoader 引导多系统

感觉到将grub装到mbr影响了我的电脑的启动速度,主要是主板自检吧! 出现logo好慢。
今天将mbr拷贝了出来,然后fdisk /mbr(M$ dos)按照M$的标准修复了mbr
启动快了, 然后用会nt的引导,又没破坏linux的引导! 重装系统也好恢复了!

下面的操作步骤!
首先起确认你的grub正常,并能启动linux, 然后启动到linux (Ubuntu)
如果你的是IDE硬盘
代码:
sudo dd if=/dev/hda of=/media/linux.lnx bs=512 count=1

如果你硬盘的被识别为SATA
代码:
sudo dd if=/dev/sda of=/media/linux.lnx bs=512 count=1

题外话:如果没有bs=512 count=1的话,dd好像跟ghost一样,不知道是不是哦,高手赐教
然后你可以到/media找到linux.lnx这个文件
将它cp到你的win根目录,例如是C:\,而且我建议你对这个文件做多个备份!

然后重启到win
进入后确认你的系统根目有linux.lnx这个文件
然后修改boot.ini
boot.ini请在win 下修改,因为编码不同! 大侠除外


它可能隐藏和只读,然后在后面加入
如果有 代码:
time=0

请将0更改!如time=5
代码:
C:\linux.lnx="linux"


保存

然后你就可以reboot看效果了
nt的引导菜单会出现linux这一项,选择后好像又会到grub的菜单了
事实上它只是读了linux.lnx
上面这个确认能进入linux后你就可以选者性的对mbr做M$的恢复了
win9x的引导盘是
代码:
fdisk /mbr

而nt就是用安装光盘或别的方法进入修复控制台

然后 代码:
fixmbr

这样你的mbr 就跟只装win的一样了!


如果你对win重装了只要做

拷尼备份的linux.lnx到win的根目录
并修改boot.ini (修改在前面已经有了)



这是dd的用法!


dd

1.作用

dd命令用来复制文件,并根据参数将数据转换和格式化。

2.格式

dd [options]

3.[opitions]主要参数

bs=字节:强迫 ibs=<字节>及obs=<字节>。

cbs=字节:每次转换指定的<字节>。

conv=关键字:根据以逗号分隔的关键字表示的方式来转换文件。

count=块数目:只复制指定<块数目>的输入数据。

ibs=字节:每次读取指定的<字节>。

if=文件:读取<文件>内容,而非标准输入的数据。

obs=字节:每次写入指定的<字节>。

of=文件:将数据写入<文件>,而不在标准输出显示。

seek=块数目:先略过以obs为单位的指定<块数目>的输出数据。

skip=块数目:先略过以ibs为单位的指定<块数目>的输入数据。

星期四, 五月 10, 2007

Configuring the GRUB Bootloader

GRUB is configured through the file /boot/grub/grub.conf; typical contents of this file look like this:

# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/main/root
# initrd /initrd-version.img
#boot=/dev/hda
default=0
timeout=5
splashimage=(hd0,1)/grub/splash.xpm.gz
hiddenmenu
title Fedora Core (2.6.31-1.3420_fc6)
root (hd0,1)
kernel /vmlinuz-2.6.31-1.3420_fc6 ro root=/dev/main/root rhgb quiet
initrd /initrd-2.6.31-1.3420_fc6.img
title Other
rootnoverify (hd0,0)
chainloader +1

--------------------------------------------------------------------------
This configuration file specifies two menu options, identified by the title keywords: Fedora Core and Windows (which Anaconda labels Other by default). Lines that start with a pound sign are comments. The first lines after the initial comments set up the appearance of the bootloader at startup time:



default= 0

Configures the first title enTRy as the default entry (they are numbered starting at 0)in this case, Fedora Core.



timeout= 5

Sets the delay in seconds before the default entry is booted.



splashimage=( hd0,1)/grub/splash.xpm.gz

Loads a graphical background for the boot display.



hiddenmenu

Does not display the boot menu unless the user presses a key during the timeout period, in which case all of the available operating system entries are shown.



The filename given in the splashimage line is in a special, GRUB-specific form: (hd0,1) specifies the first hard disk, second partition (/dev/hda2 in Linux terminology), and /grub/splash.xpm.gz identifies the pathname on that drive. Because /dev/hda1 is normally mounted on /boot, the full pathname within the Fedora system is /boot/grub/splash.xpm.gz.

*GRUB numbers partitions starting at 0, while Linux numbers them starting at 1.


--------------------------------------------------------------------------------
The remainder of this file configures the two menu options. The first one consists of these four lines:

title Fedora Core (2.6.31-1.3420_fc6 )
root (hd0,1)
kernel /vmlinuz-2.6.31-1.3420_fc6 ro root=/dev/main/root rhgb quiet
initrd /initrd-2.6.31-1.3420_fc6.img



Each line provides specific information:



title Fedora Core (2.6.31-1.3420_fc6)

The title displayed on the menu. The number in parentheses is the kernel version number; since it's standard practice to keep the second-most-recent kernel installed when the kernel is updated, just in case the new kernel does not boot properly, this information enables you to identify which kernel is newer.



root (hd0,1)

The root filesystem for the boot process, written using GRUB notation. Note that this may not be the root directory of the Fedora Core installation; it's usually the filesystem mounted at /boot when the system is running.



kernel /vmlinuz-2.6.31-1.3420_fc6 ro root=/dev/main/root rhgb quiet

The kernel location within the root filesystem, plus boot options. These boot options specify that the root filesystem for Linux is /dev/main/root (logical volume root in volume group main), and the root filesystem will be mounted read-only (ro), that the Red Hat Graphical Boot (rhgb) display is enabled, and that noncritical kernel boot messages will be suppressed (quiet).



initrd /initrd-2.6.31-1.3420_fc6.img

The location of the initrd ramdisk file. This file contains a compressed filesystem image that contains all of the files other than the kernel necessary for the initial phases of the Fedora system startup, including device drivers, programs, and scripts.

The other title entry is simpler:

title Other
rootnoverify (hd0,0)
chainloader +1



The lines in this entry invoke the Windows Stage 2 bootloader, found at the start of the Windows partition:



rootnoverify (hd0,0)

Similar to the root option in the Fedora Core entry, except that this partition will not be mounted, and therefore files cannot be accessed within the partition by GRUB.



chainloader +1

Specifies that the boot process should be turned over to the bootloader found in sector 1 of the partition.


The Grub manual: http://www.gnu.org/software/grub/manual/

星期三, 五月 02, 2007

PHP与MySQL开发中页面乱码的产生与解决

一般来说,乱码的出现有2种原因,首先是由于编码(charset)设置错误,导致浏览器以错误的编码来解析,从而出现了满屏乱七八糟的“天书”,其次是文件被以错误的编码打开,然后保存,比如一个文本文件原先是GB2312编码的,却以UTF-8编码打开再保存。要解决上述乱码问题,首先需要知道开发中哪些环节涉及到了编码:

1、文件编码:指的是页面文件(.html,.php等)本身是以何种编码来保存的。记事本和Dreamweaver在打开页面时候会自动识别文件编码因而不太会出问题。而ZendStudio却不会自动识别编码,它只会根据首选项的配置固定以某种编码打开文件,如果工作时候一不注意,用错误编码打开文件,做了修改之后一保存,乱码就出现了(我深有体会)。

2、页面申明编码:在HTML代码HEAD里面,可以用 <meta http-equiv="Content-Type" content="text/html; charset="XXX" />来告诉浏览器网页采用了什么编码,目前中文网站开发中XXX主要用的是GB2312和UTF-8两种编码。

3、数据库连接编码:指的是进行数据库操作时候以哪种编码与数据库传输数据,这里需要注意的是不要与数据库本身的编码混淆,比如MySQL内部默认是latin1编码,也就是说Mysql是以latin1编码来存储数据,以其他编码传输给Mysql的数据会被转换成latin1编码。

知道了WEB开发中哪些地方涉及到了编码,也就知道了乱码产生的原因:上述3项编码设置不一致,由于各种编码绝大部分是兼容ASCII的,所以英文符号不会出现,中文就倒霉了。下面是一些常见的错误情况与解决:

1、数据库采用UTF8编码,而页面申明编码是GB2312,这是最常见的产生乱码的原因。这时候在PHP脚本里面直接SELECT数据出来的就是乱码,需要在查询前先使用:

mysql_query("SET NAMES GBK");
来设定MYSQL连接编码,保证页面申明编码与这里设定的连接编码一致(GBK是GB2312的扩展)。如果页面是UTF-8编码的话,可以用:
mysql_query("SET NAMES UTF8");
注意是UTF8而不是一般用的UTF-8。假如页面申明的编码与数据库内部编码一致可以不设定连接编码。
注:事实上MYSQL的数据输入输出比上面讲的更复杂一些,MYSQL配置文件my.ini中定义了2个默认编码,分别是[client]里的default-character-set和[mysqld]里的default-character-set来分别设定默认时候客户端连接和数据库内部所采用的编码。我们上面指定的编码其实是MYSQL客户端连接服务器时候的命令行参数character_set_client,来告诉MYSQL服务器接受到的客户端数据是什么编码的,而不是采用默认编码。


2、页面申明编码与文件本身编码不一致,这种情况很少发生,因为如果编码不一致美工做页面时候在浏览器看到的就是乱码了。更多时候是发布以后修改一些小BUG,以错误编码打开页面然后保存导致的。或者是用某些FTP软件直接在线修改文件,比如CuteFTP,由于软件编码配置错误而导致转换错了编码。

3、一些租用虚拟主机的朋友,明明上述3项编码都设置正确了还是有乱码。比方说网页是GB2312编码的,IE等浏览器打开却总是识别成UTF-8,网页HEAD里面已经申明是GB2312了,手动修改浏览器编码为GB2312后页面显示正常。产生原因是服务器Apache设定了服务器全局的默认编码,在httpd.conf里面加了AddDefaultCharset UTF-8。这时候服务器会首先发送HTTP头给浏览器,其优先级比页面里申明编码高,自然浏览器就识别错了。解决办法有2个,请管理员在配置文件自己的虚机里加上一条AddDefaultCharset GB2312来覆盖全局配置,或者在自己目录的.htaccess里配置。

星期二, 三月 27, 2007

WAMP配置

1:安装apache_2.2.4-win32-x86-no_ssl.msi。(C:/server/Apache2.2)注意在填写网络域名,服务器名称和管理员邮件地址时候,最好能够填上(不知道的话,用localhost),否则第一次启动时会报错。这些参数都在httpd.conf里。

2:解压缩php-5.2.1-Win32.zip。(C:/server/PHP5)注意所在路径不能含有空格。并把安装路径(C:/server/PHP5)追加到环境变量path中去,这是为了让apache能访问php5ts.dll。

3:修改apache的httpd.conf(修改之前最好备份一下,以防万一),把下面的指令追加在LoadModule之后。

#configuration for PHP5
#如果是apache2.0.x的话,使用php5apache2.dll(或者使用PHP5.1也可以使用它):该死的兼容性问题。
LoadModule php5_module C:/server/PHP5/php5apache2_2.dll
#亦可以修改 mime.types
AddType application/x-httpd-php .php
PHPIniDir "C:/server/PHP5"

4:把php.ini-dist重命名为php.ini。

5:测试

6:想要使用扩展的模块:修改php.ini
extension_dir = "C:/server/PHP5/ext"
打开extension=“你需要的模块”
extension=php_mysql.dll
extension=php_mysqli.dll

7:安装mysql-5.0.27-win32_Setup.exe,完毕后,在CMD下测试,MySQL -u root -p

8:测试WAMP(修改配置文件之后,需要重启Apache才能让修改生效)

$link = mysql_connect('localhost','root','huzp');
if(!$link) echo "fail";
else echo "success";
mysql_close();
?>


9:解压缩phpMyAdmin-2.10.0.1-all-languages.zip到Apache的发布目录。修改config.default.php文件。

$cfg['PmaAbsoluteUri'] = 'http://localhost/phpMyAdmin';
$cfg['Servers'][$i]['password'] = '123456'

10:打开http://localhost/phpMyAdmin,进入管理页面,DONE。

星期五, 二月 23, 2007

再读《人月神话》笔记

《人月神话》
1.在众多软件项目中,缺乏合理的进度安排是造成项目滞后的最主要原因,它比其他所有因素加起来的影响还要大。导致这种灾难如此普遍的原因是:

a: 我们对估算技术缺乏有效的研究,更加严肃地说,它反映了一种悄无声息,但并不真实的假设-----一切都将运作良好。
1:所有的编程人员都是乐观主义者(这次它肯定会运行,我刚刚找到最后一个bug)
2:进度安排背后的第一个错误的假设是:一切都将运作良好,每一项任务仅花费它所“应该”花费的时间
3:在单个任务中,“一切都将运转正常”的假设在进度上具有可实现性。因为所遇到的延迟是一个概率。
4:分布曲线,“不会延迟”具有限定的概率,所以现实情况可能会像计划安排得那样顺利。然而大型的编程工作,或多或少包含了很多任务,某些任务间还具有前后的次序,从而一切正常的概率变得非常小,甚至接近于无。

b: 我们采用的估算技术隐含地假设人和月可以互换,错误地将进度与工作量相混淆。
1:成本的确随开发产品的人数和时间的不同,有着很大的变化,进度却不是如此。
2:用人月作为衡量一项工作的规模是一个危险和带有欺骗性的神话。
3:人数和时间的互换仅仅适用于以下情况:某个任务可以分解给参与人员,并且它们之间不需要相互的交流。这在割小麦或收获棉花的工作中是可行的。
4:无论哪个母亲,孕育一个生命都需要10个月。
5:对于可以分解,但子任务之间需要相互沟通和交流的任务,必须在计划工作中考虑沟通的工作量。因此,相同人月的前提下,采用增加人手来减少时间得到的最好情况,也比未调整前要差一些。沟通所增加的负担由两个部分组成,培训和相互交流。培训增加的工作量(不能分解)随人员的数量呈线性变化。相互交流的工作量按照n(n-1)/2递增。

c: 由于对自己的估算缺乏信心,软件经理通常不会有耐心持续地估算这项工作。
在进度安排中,顺序限制所造成的影响,没有哪个部分比单元测试和系统测试所受到的牵涉更彻底。
进度安排参考法则:
1/3计划
1/6编码
1/4构件测试和早期系统测试
1/4系统测试,所有的构件已完成
在许多重要的方面,上面的进度安排与传统的方法不同:
分配个计划的时间比平常的多。即便如此,只是勉强够产生详细和稳定的计划规格说明,并不足以容纳对全新技术的研究和探索。
对所完成代码的调试和测试,投入近一半的时间。
容易评估的部分,如编码,仅仅分配了1/6的时间。研究发现,很少有项目允许为测试分配一半的时间。但大多数项目的测试实际上是花费了进度中一半的时间。他们中许多项目,在系统测试之前还能保持进度。

d: 对进度缺少跟踪和监督。
 非阶段化方法的采用,少得可怜的数据支持,加上完全借助软件经理的知觉,这样的方法很难生产出有力的,看似可靠的和规避风险的估计。
 开发并推行生产率图表、缺陷率图表、估算规则等等,而整个组织最终会从这些数据的共享上获益。

e: 当意识到进度的偏移时,下意识(以及传统)的反应是增加人力。这就像使用汽油灭火一样,只会使事情更糟。
 项目的时间依赖于顺序上的限制。人员的最大数量依赖于独立子任务的数量。



2. 需要协作沟通的人员数量影响着开发成本,因为成本的主要组成部分是相互沟通和交流,以及更正沟通不当所引起的不良结果(系统调试)。这一点也暗示,系统应该有尽可能少的人员来开发。



3. 对于效率和概念的完整性来说,最好有少数干练的人员来设计和开发,而对于大型系统,则需要大量的人手,以使产品能在时间上满足要求,如何调和这两方面的矛盾。Mills的建议:大型项目的每一个部分由一个团队解决,但是该团队以类似外科手术的方式组建,而并非一拥而上。也就是说,同每一成员截取问题某个部分的做法相反,由一个人来完成问题的分解,其他人给予他所需要的支持,以提高效率和生产力。



4. 外科手术团队:
 外科医生(首席程序员):定义功能、设计、编码、测试、要很高经验,熟悉业务
 副手:外科医生的保险机制。提供设计、编码、功能的建议,不负责具体的事务
 管理人员:管理财务、人员、工作地点、办公设备,听从外科医生
 编辑:文档的生成,维护。来自于外科医生的口述或者草稿。
 两个文秘:管理人员和编辑各配一个文秘。负责项目的协作一致。
 程序职员:负责团队所有的程序和数据的管理。
 工具维护人员:保证所有基本服务的可靠性,一致性以及构建,升级,维护。
 测试人员:编写测试用例和准备测试数据。
 语言专家:语言方面的专家,咨询。解决复杂,棘手的问题。



5. 对于计算机系统而言,出现概念差异和不一致性的问题,是由于设计被分成了由若干人完成的若干任务。所以需要具备设计上的完整性,就需要一个系统架构师从上之下的进行所有的设计。要使工作易于管理,必须清晰地划分体系结构设计和实现之间的界线,系统架构师必须一丝不苟的专注于体系结构。(本文的体系结构指的是完整和详细的用户接口说明,更偏重于现今的需求概念,不是指系统的框架。)



6. 功能与理解上复杂程度的比值才是系统设计的最终测试标准,也就是易用性。而易用性需要设计的一致性和概念上的完整性来保证。体系结构和实现必须要严格分离开来。产品的成本性能比很大程度上依靠实现人员,就如同易用性很大程度上依赖架构师一样。两者都有需要很高的创造性。



7. 系统架构规定实际上是增强,而不是限制了实现小组的创造性。一旦他们将注意力集中在没有人解决过的问题上,创意就开始奔涌而出。在毫无限制的实现小组中,在进行系统架构上的决策时,会出现大量的想法和争议,对具体实现的关注反而会比较少。



8. 当建议由小型体系结构团队来编写系统的所有外部技术说明时,编程人员常常会提出这样的反对意见:
 该说明中的功能过于繁多,而对实际情况中的成本考虑比较少。
 警惕second-system effect。在设计第一个项目时,架构师会面对不断产生的装饰和润色功能,但这些功能都会被搁置在一边,作为“下一个”项目的内容。第二个系统是设计师们所设计最危险的系统。而当着手第三第四个系统时,先前的经验会相互验证,得到对此类系统通用特性的判断,而且系统之间的差异会帮助他识别出经验中不够通用的部分。
 second-system effect:一种普遍倾向是过分的设计第二个系统,向系统中添加很多修饰功能和想法。另一种倾向是对某些技术进行细化、精炼的趋势,由于基本系统设想发生了变化,这些技术已经显得落后。
 架构师获得了所有创造发明的快乐,剥夺了实现人员的创造力。
 具体实现中创造和发明的机会,并不会因为指定了外部技术说明而大为减少,相反创造性活动会因为规范化而得到增强,整个产品也是一样。
 当体系结构的队伍缓慢工作时,很多实现人员只能空闲的坐着等待。
 在外部技术说明完成的时候,才雇佣实现人员。 ;)



9. 把工作进行垂直划分,保证概念的完整性;尽量避免水平划分。



10. 文档化的规格说明----手册:手册是产品的外部规格说明,它描述和规定了用户所见的每一个细节;同时它还避免描述用户看不见的事物。后者是编程实现人员的工作范畴,而这里他的设计和创造自由是不应该被限制的。体系结构设计人员必须为自己描述的任何特性准备一种实现方法,但是他不应该试图支配具体的实现过程。



11. 周例会是每周半天的会议,有所有的架构师,加上硬件和软件实现人员代表和市场计划人员参与,由首席系统架构师主持。会议中,任何人可以提出问题和修改意见,但是建议书通常是以书面的形式,在会议之前分发。周例会的决策会给出迅速的结论,使工作继续开展下去。这种会议的卓有成效是在于:
 数月内,相同小组-----架构师、用户和实现人员-----每周交流一次。因此大家对项目相关的内容比较了解,不需要安排额外时间对人员进行培训。
 上述小组十分睿智和敏锐,深刻理解所面对的问题,并且与产品密切相关。没有人是“顾问”的角色,每个人都要承担义务。
 当问题出现时,在界线的内部和外部同时寻找解决方案。
 正式的书面建议集中了注意力,强制了决策的制定,避免了会议草稿纪要方式的不一致。
 明确的授予首席架构师决策的权力,避免了妥协和拖延。



12. 电话日志:日志中,它记录了每一个问题和相应的回答。QA表



13. 产品测试:项目经理最好的朋友就是他每天要面对的对手----独立的产品测试机构/小组。每一个开发机构都需要这样一个独立的技术监督部门,来保证其公正性。测试人员不时地总会发现一些没有贯彻执行、设计决策没有正确或准确实现的地方。出于这方面的原因,设立测试小组是使设计决策得以贯彻执行的必要手段,同样也是需要尽早着手,与设计同时实施的重要环节。

敏捷方法书籍(转载)

“敏捷软件开发宣言:我们正在通过亲身实践和帮助其他人实践,揭示更好的软件开发方法,通过这项工作,我们认为:
人和交流胜过过程和工具
可工作的软件胜过面面俱到的文档
客户协作胜过合同谈判
响应变化胜过遵循计划
虽然右项也有价值,但是我们认为左项更重要。”
—— Kent Beck,Mike Beedle,Arie van Bennekum,Alistair Cockburn,Ward Cunningham,Martin Fowler,James Grenning,Jim Highsmith,Andrew Hunt,Ron Jeffries,Jon Kern,Brian Marick, Robert C. Martin,Steve Mellor,Ken Schwaber,Jeff Sutherland,Dave Thomas

敏捷软件开发这个词在2006年的中国软件界听起来仍然显得有些陌生。自2001年敏捷联盟被发起以来,敏捷方法的实践经验和理论研究都在不断的更新。而我国的大多数程序员还是只能在书本上读到敏捷的好处,很难在项目中进行实践。这其中的原因,主要是缺乏拥有实际敏捷项目经验的人来带领实施敏捷。虽然敏捷开发是种实践行为,很难从书本上直接学习,不过多数程序员了解敏捷,却都是先从书本开始的。无论结果怎样,从认识到实践的过程是免不了的。

敏捷软件开发之方法论篇
大家都知道敏捷软件开发方法包括了多种方法论,主要有:SCRUM,Crystal,特征驱动软件开发(FDD),自适应软件开发(ASD),以及最著名的极限编程(XP)。这些方法论分别在不同的著作上专门论述过:
SCRUM:《Agile Software Development with Scrum》 by Ken Schwaber, Mike Beedle,《Agile Project Management With Scrum》by Ken Schwaber
FDD: 《Java Modeling in Color with UML》by Peter Coad, 《A Practical Guide to Feature-Driven Development》(特征驱动开发) by Stephen R Palmer, John M. Felsing,
Crystal: 《Crystal Clear》by Alistair Cockburn
ASD: 《Adaptive Software Development》(自适应软件开发)by James A. Highsmith

其中尤以XP系列的书籍居多。人民邮电出版社的一系列极限编程系列丛书,在国内引进较早。在还没有统一敏捷词汇的情况下,引发了一批敏捷先锋人士的热情,是我国程序员的敏捷启蒙教材。这些书包括《Extreme Programming Explained》(解析极限编程),《Extreme Programming Examined》(极限编程研究),《Extreme Programming Installed》(极限编程实施),《Extreme Programming Explored》(探索极限编程),《Extreme Programming Applied》(应用极限编程)《Extreme Programming in Practice》(极限编程实践),《Planning Extreme Programming》(规划极限编程)等,这些书有的是作者的XP实践论文,有些是对XP项目的介绍,其中,值得推荐的是下面两部著作。

《Extreme Programming Explained: Embrace Change》by Kent Beck
第一版中译版:《解析极限编程:拥抱变化》,唐东铭,人民邮电出版社
第二版中译版:雷剑文,电子工业出版社
作为XP的开山之作,目前已经出版了第二版。在第一版中,Kent Beck对XP作了详细的描述。从当前软件开发的现状和问题谈起,从需求的变化到如何拥抱变化,给出了XP的四项价值观和十二项实践。对于想了解敏捷的来龙去脉的人,此书属于必读之类。在第二版,Kent根据几年来的实践,为XP增加了一项价值观:尊重,并增加了原则的概念,同时增加和删改了一些实践。
该书第一版是程序员的宣言,这和Kent的背景很有关系。随后XP经历了五六年的发展和实践,Kent自己也逐渐意识到,这样的观点太狭隘了。因此就有了第二版,与其说这是技术书籍,到更像是纯粹意义的软工书籍。期间也可以看出XP的体系更加完备。这其中尤为突出的是把人放到了更为重要的地位。

《Extreme Programming in Practice》by James Newkirk, Robert C. Martin
中译版:《极限编程实践》,王钧,人民邮电出版社
读过了一些列的XP书籍,程序员们都会觉得XP非常好,但到底如何才能开始实施XP呢?还不是太清楚。本系列中的这本书用一个完整的小项目作例子,从头到尾教给人如何敏捷开发,是一本不可多得的实践教材。如果想直接实施XP开发,这本书可以给你很大启示。

敏捷软件开发之实践篇
一、极限编程最佳实践
由于极限编程是如此的流行,多数敏捷团队都会或多或少的借鉴一些XP中的敏捷实践,而XP的每一个敏捷实践也确实值得大书特书,而其中最著名的是测试驱动开发和重构实践:

《Test-Driven Development》 by Kent Beck
中译版:《测试驱动开发》,崔凯,中国电力出版社
测试驱动开发是Kent Beck另一部力作。“Clean Code That Works”是敏捷开发的目标之一,那么如何达到这个目标?TDD给出了一种方式。测试实质上是需求。由需求产生出的代码肯定是能够工作的功能代码,而要实现Class本身的可测试性,就不得不写出高度解耦合的Clean的代码。本书从一个Money的例子入手,从最初的一点需求开始,逐步增加需求,完成整个货币系统的代码。后面又给出了Unit Test中的一些最佳实践和模式供参考。
然而,本书的教导意义比其实践意义更突出。作为一本TDD的教程或入门教材,这本书无疑是最佳的,其中提出的一些最佳实践更是值得经常阅读来温习。本书面向的是单元测试,而实际开发中面对的数据库测试,Web测试等问题并不属于单元测试的范畴。因此读者并不能从中直接进入到实战。
另一本同名书《Test Driven Development: A Practical Guide》由Davis Astels撰写,他将该书看作是Kent著作的补充,重点阐述利用TDD开发所必要的技术和工具上,因此对实际开发更具实用性。

《Refactoring: Improving the Design of Existing Code》by Martin Fowler
中译版:《重构:改善既有代码的设计》,侯捷,熊节,中国电力出版社
重构这本书的意义在于,他提供了一种让你写出更加优美代码的能力。在测试的保证下,重构能够发挥强大的威力。敏捷团队中,不断的重构出简单且高效的代码才能够保持拥抱不断变化的需求。后来的一本书《Refactoring to Patterns》(从重构到模式)by Joshua Kerievsky,更是将重构的威力发挥到极限。
重构曾被称为软件开发图书的双璧,另一本书是《Design Patterns》(设计模式) by GoF。当然,对现在的软件开发这二者已经不是最重要的。ThoughtWorks的首席科学家Martin Fowler总结了朋友们的各种实践心得,写出了这本书。从几年后的目光来看,这本书中的多数实践都被各种IDE做到了操作菜单中。虽然IDE提供了大量重构功能,但仅靠IDE是无法写出简洁美妙代码的,多数的敏捷团队重构工作做得还是不够。

另外有一本专门介绍结对编程的书,《Pair Programming Illuminated》(结对编程技术)by by Laurie Williams and Robert Kessler,指出了为什么要结对?并从各种不同水平不同性格的程序员结对情况来讨论该实践的优劣。对此有兴趣的程序员不妨一读。

二、敏捷软件开发实践
自从2001年敏捷联盟成立以来,单独推广极限编程的书变少了,而统一口径推广敏捷的书变得越来越多。两本同名的敏捷软件开发都是不可多得的好书,

《Agile Software Development:Principles, Patterns, and Practices》by Robert C. Martin
中译版:《敏捷软件开发:原则,模式与实践》,邓辉,清华大学出版社
被业内人士称为Uncle Bob的Robert C Martin在沉寂几年后写出了这部书。该书可以算是从软件开发角度对敏捷方法阐述的最详细和全面的一本。之前的敏捷书籍多是关注于过程改进,而对如何从技术角度实施讲的比较少。本书一开始先介绍了敏捷联盟和敏捷开发过程。之后详细论述了面向对象设计的原则,这些原则是本书的精华之一。后面通过几个项目介绍了如何将设计模式应用于项目中。
Uncle Bob不愧是实践的大师,写出来的书也是拥有很强的实践意义。在敏捷团队的办公桌上,应当常备此书,一来可作为参考查询,二来可以作为新成员的必读书目。

《Agile Software Development》by Alistair Cockburn
中译版:《敏捷软件开发》,俞涓,人民邮电出版社
这本书更加适合管理者来阅读。Alistair从项目人数和交流难易程度,将敏捷的各种方法划分了其适用范围。人数多的或分布式项目就需要靠其他手段来加强交流,人数少的就可以靠pair programming等进行面对面的交流。交流和反馈是敏捷的核心。同时Alistair也介绍了一下他提出的Crystal方法族。

三.敏捷项目管理和敏捷需求分析
在推广敏捷一段时间后,敏捷社群也意识到,多数书籍更像是面向开发人员,过于技术化,难以吸引项目经理或主管。因此,一批面向管理者视角的书也开始浮出水面,这些书包括:
《Agile and Iterative Development》(敏捷迭代开发)by Craig Larman
《Lean Software Development》(敏捷软件开发工具—精益开发方法)by Mary Poppendieck
《Agile Software Development Ecosystems》(敏捷软件开发生态系统)by Jim Highsmith
书中从各种角度比较和分析各种敏捷方法的优劣,异同,起源,适用范围等。这些书对于一个项目主管决策使用何种过程来在自己的团队中实践敏捷有很好的参考作用。

近两年,人们开始逐渐意识到敏捷开发的侧重点不仅仅是开发过程和开发实践,还包括对需求和项目管理等其他相关方面的实践。一些相关的书籍也悄然出现在人们的视野:
《Agile Project Management》(敏捷项目管理)by Jim Highsmith
《User Stories Applied》by Mike Cohn
《Agile Estimating and Planning》by Mike Cohn
《Agile Requirements & User Stories》 by Louis Molnar
这些书不同于以往强调新方法,新过程的书目。敏捷项目管理类的书主要介绍如何管理敏捷团队,如何计划要开发的需求,如何为客户提供最大的价值。介绍敏捷需求分析的书主要帮助商务分析师或项目经理挖掘和分析用户需求,写出用户故事,评估和计划用户故事等。人们已经意识到,各种方法论的实质是相同的,都是提供商业价值,减少浪费,增加交流,快速反馈。因此不需要着重于区分是使用了那种方法。对项目经理来说,不同的项目或团队应当采用适应其特殊情况的方法,而这些方法的基本原则是相同的。

四.敏捷软件开发新方向
对架构师或程序员来说,近年来的技术进展,也使得敏捷开发有了新的研究方向:
《Agile Web Development with Rails》by Dave Thomas, David Hansson, Leon Breedt, and Mike Clark
该书是获得2006JOLT奖的书,讲得是采用Ruby on Rails这个Web开发工具新贵来快速开发Web项目,从而达到快速反馈拥抱变化的目的。
《Refactoring Databases》by Scott W Ambler
此书是Scott的新作,延续和继承了《Agile Modeling》(敏捷建模)和《Agile Database Techniques》(敏捷数据)的思想。在敏捷开发过程中,作为持久化最常见技术的数据库如果不能够敏捷,怎么能够适应一次次迭代和一次次发布的修改呢?书中介绍了如何进行数据库演化,如何保证升级后数据库数据的正确性,以及最佳实践。

我们可以看到,随着敏捷方法和市场的不断成熟,敏捷的书籍也从理论性转向了实用和最佳实践类型。然而,不可否认的是,一个团队的敏捷化很难仅靠阅读书本来完成,由成功实践过敏捷的开发者手把手的带领,才是最好的方法。

星期四, 二月 08, 2007

漫谈创业和管理-程序员5大思维障碍(转载)

程序员是最容易创业的,或者说是创业成本最低的职业。只要有一台电脑和投入自己的时间,就可以写出畅销天下的软件,这是每个程序员的梦想。更何况世界首富常年以来就是程序员出身的比尔盖茨,这也刺激了更多的程序员走上创业之路。
可是等到真的开始创业,才发现这条路并不容易.由于创办CSDN网站和《程序员》杂志的原因,接触了大量的技术创业者,或者从技术转向管理的程序员。我发现真正程序员创业成功的例子非常罕见,我自己也曾经创业三次,经历了很多的挫折和失败。
我总结了一下,由于程序员的思维习惯给创业或者管理带来的障碍:(为什么要谈管理,因为真正创业做企业,靠一个人是不行的,必须有团队,团队如何管理就是第一步创业的挑战)

程序员思维定势:
1)机器思维
优秀的程序员最擅长和电脑程序打交道,并通过代码去控制反馈。而管理需要和人打交道,需要收集人的反馈。电脑是按逻辑来执行的,而人却要复杂很多,特别是团队中有女性成员,挑战难度就更大。
由于长期和电脑接触,很多程序员缺乏和别人沟通的技巧,或者说情商相对较低。这在管理上是比较致命的缺点。

2)BUG思维
优秀的程序员追求完美,看自己或者别人代码时第一有限是看什么地方可能有BUG, 管理时如果带着BUG思维,就会只看到别人的不足和错误,而不去表扬其有进步的地方。(完美思维的坏处还有一个,就是过于关注细节)如果方向和前提有问题,过于关注细节反而会带来延误
3)工匠思维
程序员靠手艺吃饭,创业总是会碰到各种困难,在碰到困境的时候程序员出身的创业者是有退路的,大不了我再回去写程序搞技术好了。有时候创业就是差那么一步,不能坚持到底,也就不能收获果实。

4)大侠思维
以技术创业起家的容易迷信技术,忽视市场,忽视管理,总以为只有自己的是最好的。遗憾的是技术变迁实在太快,一时的先进不能代表永远的先进。先进的技术也不一定就是致胜的法宝。

5)边界思维
程序员设计代码和系统时,常常会考虑要处理边界和异常。反映到思维习惯上,就是遇到问题,就会全面的思考各种情况。这是很好的优点,但做事业时,这有时候反而会是缺点。

上面五类有不少具体例子,大家也可以看看自己的思维习惯里面是不是这样?
习惯是很难改变的,最好的处理方式是找到搭档,能弥补自己的不足,这样成功的概率才会加大。HP, Apple Microsoft, Oracle,Adobe, 都是两个主要创始人搭档创业成功的。

from http://blog.csdn.net/jiangtao/archive/2007/02/07/1504627.aspx

星期五, 二月 02, 2007

list of the coding requirements for XHTML compliance

A short list of the coding requirements for XHTML compliance

1. Declare a DOCTYPE
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
<"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<"http://www.w3.org/TR/html4/loose.dtd">

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
<"http://www.w3.org/TR/html4/frameset.dtd">

2. Declare an XML namespace
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

3. Declare your content type
<meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />

4. Close every tag, whether enclosing or nonenclosing

5. All tags must be nested correctly

6. Inline tags can't contain block level tags

7. Write tags entirely in lowercase

8. Attributes must have values and must be quoted

9. Use the encoded equivalents for a left angle bracket and ampersand within content

bash点滴

bash的配置文件有三个,.bash_profile .bashrc .bash_logout,它们一般就在用户home目录下。没有的情况下会使用系统默认的/etc/bashrc

1: .bash_profile:用户Login时执行,设置个人环境。
.bash_profile的修改要在用户重新Login的时候才会生效。也可以使用source命令或者.命令执行,使之生效。
bash向前兼容C shell的.login(bash中更名为.bash_login)和Bourne shell和Korn shell的.profile配置文件。当你Login的时候,这三个文件只有一个会被执行,配置文件搜索顺序:.bash_profile---> .bash_login---> .profile

2: .bashrc:用户调用shell时执行,设置调用shell的运行环境。 (bash的环境配置文件)
提供将用户的Login环境和subshell环境区分开来的灵活性。
  用户特定的aliases和functions在.bashrc里定义。避免subshell运行舒畅,尽可能把所有的定义放在这里
用户自己的特定配置和需要启动的程序在.bash_profile里给出

3: .bash_logout:顾名思义,用户Logout时执行,做一些清理工作。



Alias 为命令创建合适的名字
格式:alias name=command
bash在执行命令前,会将所有的aliases进行文本置换,所以通配符及特殊字符不能包含在alias名字中
对文件夹的名字进行alias,需要一点技巧。alias anim='/work/fisrt/second/third/fourth' cd anim的时候,系统会报错,找不到这个文件或者文件夹。需要再加一个alias cd='cd ' 或者 shopt -s cdable_vars 允许cd的参数是变量
不建议用很多aliases,shell脚本和function能够提供更强大的功能

Option
格式:set -o | set +o +表示关闭option -表示打开option(The reason for this incongruity is that the dash (-) is the conventional UNIX way of specifying options to a command, while the use of + is an afterthought)
或者使用shopt -psuqo

varible
声明:variable=value 使用:$variable 删除:unset variable(此时只有当set -o nounset的时候,才有用。因为对于bash来说,所有未定义变量的值为null(即等于''),nounset 选项使得bash在碰到一个未定义的变量时,提示错误)

在命令行执行命令时,命令的执行优先级
1: Aliases
2: Keywords such as function if for
3: Functions
4: Built-ins like cd and type
5: Scirpt and Executable programs in directories listed in the PATH

星期四, 二月 01, 2007

FC6启动过程分析——启动图形界面

上次我们说到,inittab启动到最后,使用/etc/X11/prefdm这个脚本来选择一个DM(Display Manager)来启动图形界面.这个脚本根据/etc/sysconfig/desktop中的配置来选择是该运行gdm,kdm还是xdm,默认将会使用gdm。

无论是gdm,xdm还是kdm,所做的事情都是类似的,及启动一个X窗口,基于这个X窗口提供一个图形化的用户登录界面,以便在实际进入X窗口系统之前,对用户进行验证,并且提供用户选择自己希望的语言,窗口管理器等的机会。除此之外,dm程序一般还支持别的一些操作,比如提供直接关机的选项以及根据配置决定是否打开XDMCP服务的端口等。

XDMCP服务是X窗口显示管理器控制协议的缩写,它允许用户在远程电脑上运行X窗口服务,然后通过XDMCP协议使用本地的XDM登录,登录以后的后续操作将使用远程的X窗口作为显示系统。一个很简单的例子,首先使用gdmsetup程序(管理菜单的登录屏幕)打开XDMCP的支持(远程选项卡更改为与本地相同),然后打开一个终端窗口,运行Xnest :1 -query 127.0.0.1命令(Xnest并不是默认安装的命令),你将在一个新开的窗口中看到和你的登录屏幕一模一样的登录屏幕,你可以登录其它用户,进行所有和本地用户一样的操作。显然如果你是在另外一台电脑上,只需要把相应的ip地址改掉就可以了。

并不一定非要使用Xnest程序,你甚至可以在远程的Win32系统上进行基于XDMCP的远程登录,这首先需要你在你的windows系统上运行一个X 窗口系统,有很多种类似的实现,包括X-win32和cygwin在内的各种免费和收费版本都是一个不错的选择,事实上,一台强劲的服务器可以通过这种方法可以将N台落魄的486PC转变成可以运行高级科学运算的X终端。

说到远程X终端,除了上面提到的方法,你还可以使用内置于gnome之中的vino程序,这个程序可以基于本地的X窗口打开一个兼容于vnc的服务,你可以使用各种类型的vncviewer来连接这个服务并进行远程操作(参见首选项菜单中的远程桌面),这种实现方式下,远程显示的屏幕和本地屏幕是完全相同的。或者你也可以使用单独的vncserver,这种使用方式和XDMCP的使用方法类似,只是登录的用户和使用的窗口管理器都是由vncserver指定好的。

gdm的配置定义在/etc/gdm/custom.conf中,对于其预定义配置的默认值你还可以查询/usr/share/gdm/defaults.conf文件,它们都采用了类似windows下ini文件的文件格式。

在用户选择了语言和窗口管理器以后,DM根据用户的选择设置相应的locale变量,然后运行和那个窗口管理器对应的命令。通常在语言选择菜单中,我们只能看到区域的选择,比如中国大陆,中国香港这样的选项,但是中国大陆的选项可以使用GBK的编码方式,也可以使用UTF8的编码方式,选择的区域是怎样和编码方式对应的呢?所有gdm相关的配置文件保存在/etc/gdm这个目录中,在这个目录中有一个 locale.alias文件,这个文件列出了系统支持的语言以及各个语言对应的编码方式,你可以通过更改这个文件,以便在选择中国大陆的语言时,将编码由默认的UTF8更改为GBK,当然,适应UTF8的编码方式也是一个不错的选择,如果你不需要经常的和windows环境打交道,你应该保留这个默认的设置。

除了选择语言以外,gdm还允许你选择要登录的会话. 系统内建的几个会话包括安全模式终端,安全模式gnome以及上一次的成功登录等,其它的会话则是从配置文件中读取的,gdm将会在多个目录中寻找设定的会话,包括/etc/X11/sessions/,/usr/share/gdm/BuiltInSessions/, /usr/share/xsessions/等,路径可以通过daemon/SessionDesktopDir配置项进行更改,gdm在这些目录中寻找扩展名为desktop的文件,比如默认会话对应的文件是 /usr/share/gdm/BuiltInSessions/default.desktop,而gnome会话对应的文件为 /usr/share/xsessions/gnome.desktop.这些配置文件定义了在不同的语言中这个会话要显示的名称。

当用户选择了一个对话,输入了正确的用户名和密码以后,gdm执行命令的顺序依次是,首先它将执行位于daemon/PreSessionScriptDir 配置项路径下(默认为/etc/gdm/PreSession/)的所有脚本文件,来执行启动会话前的一些任务,比如更改X窗口的默认背景之类,然后它将调用位于daemon/PostLoginScriptDir配置的目录中(默认为/etc/gdm/PostLogin)的脚本,执行一些在刚刚登录以后需要运行的命令,然后它将以前面提到的desktop文件中定义的exec参数的值作为参数,调用daemon/BaseXsession配置项指定的脚本(默认为 /etc/gdm/Xsession),比如如果你选择的是默认会话,那么执行的命令将会是/etc/gdm/Xsession default,如果你查看这个文件你将发现,在这种情况下,它将首先检查是否存在主目录的.xsession文件,如果存在就执行它,否则检查是否存在主目录下的.Xclients文件,如果存在则执行它,否则就将执行/etc/X11/xinit/Xclients文件,这个文件根据 /etc/sysconfig/desktop配置文件中的设置选择相应的命令执行,默认为执行gnome-session.

而配置在 daemon/PostSessionScriptDir配置项(默认值为/etc/gdm/PostSession/)所设定的目录中的脚本将在会话结束以后运行,这意味着无论出于什么原因,gnome程序已经完全退出了,也许是你选择了注销命令,也许是X窗口崩溃了,如果你有这方面的需要,可以将相应的脚本放在对应的目录中。

最后还有一点要说的是,gdm通常是由/etc/X11/prefdm脚本启动的,这个脚本中将会重复启动自己,因此,如果你想在运行级别5的时候完全退出X窗口,你应该将prefdm这个程序杀死,而不是简单的杀死X窗口或者是gdm。

引导器GNU GRUB简析

GNU GRUB是我见到的最灵活的、功能最强大的、加载速度最快的、最精炼的引导器。(除了GRUB,我还用过NT loader, OS/2 loader, DOS MBR loader, PQ BOOT, System Commander, Lilo等引导器)。因此,GRUB成为现在各大Linux发布版的主流引导器。

一、安装GRUB的四大要素

想玩转GRUB,必须理解GRUB的组成部分和其大概的功能、实现的思路。如下,是我的GRUB目录的文件:

menulst
stage1
stage2
e2fs_stage1_5
fat_stage1_5
ffs_stage1_5
jfs_stage1_5
minix_stage1_5
reiserfs_stage1_5
vstafs_stage1_5
xfs_stage1_5


如果你下载一个grub,编译后装上,那么产生的就是这些文件和一个从linux环境进入grub环境的程序grub,但是不包括menulst(也可能有个例子文件menulst.conf,记不清了)。这些文件是通用的,copy到别的机器上也能用,这就是一大灵活之处。

stage1是用来装入到MBR或者primary disk的super block的,它应该是16位环境引导模块;stage1引导完成后,就切换到32位保护模式,把stage2从磁盘读到内存,然后把控制权交给stage2执行。stage2会读取menulst,从而确定如何引导Linux。menulst文件中详细写明了引导菜单和内核的位置,这个纯文本文件是需要手工配置的。其余的那些文件,如e2fs_stage1_5那些,偶不说你也明白,是对应于各种类型文件系统的驱动程序,在stage1从磁盘读取stage2时会加载它先。

下面是偶得menulst,我用了最简捷的语法:

#-----------------------------------------

default 1
timeout 3

#-------------------------------
#-- Slackware Linux 10 kernel 2.4.26
title Slackware Linux 10 kernel 2.4.26
kernel (hd0,4)/boot/vmlinuz ro root=/dev/hda5
boot

#-----------------------------------------


default 指定默认引导的系统,对应序号是引导菜单的条目序号,从1开始计数。timeout 指定引导菜单延迟等待的时间,如果timeout为0你就看不到引导菜单了。title指定引导菜单上显示的文字,kernel指定引导内核和root设备的位置。这里要注意,(hd0,4)是grub指定文件设备的语法,跟Linux通用的/dev/hda5表示法类似,只不过它的数字是从0开始计数的,而/dev/hda5这种表示法是从1开始计数的。(hd0)指向/dev/hda, (hd1)指向/dev/hdb,(hd0,1)指向/dev/hda2,(hd2,6)指向/dev/hdc7,以此类推......

要注意,根设备前要加上ro,指定为只读挂载,不然后患无穷。

还有一点一定要注意,(hd0,4)/boot/vmlinuz中(hd0,4)指的是你的内核vmlinuz所在的设备根路径,和root设备未必相同(比方说我把vmlinuz放在(hd0,0)上,但是我的linux root确在(hd0,4)上),切记切记。有时候,你会看到grub中用root (hd0,0) 这里的root指的不是你的linux的root所在的设备路径,而指的是在grub中的 / 所对应的设备路径,如:
kernel (hd0,4)/boot/vmlinuz ro root=/dev/hda5
等同于:
root (hd0,4)
kernel /boot/vmlinuz ro root=/dev/hda5
这点要仔细理解。

二、灵活自如的安装方法

至少有2种方法来安装grub,1>在Linux中把grub安装包装上,会同时装一个从Linux中进入grub环境的工具grub,这样你就可以执行grub进入grub环境,然后再执行安装指令;2>从grub引导盘(很多D盘都有提供,还有那种光盘的Linux修复环境也有提供)进入grub,执行安装指令。

安装指令很简单,就1行命令:
install <要安装到那个引导位置> p

如我的,就是:
grub>install (hd0,0)/grub/stage1 (hd0) (hd0,0)/boot/grub/stage2 p (hd0,0)/grub/menulst

这里要说明一点,有很多人分不清/boot是什么意思,以至于老是在任何环境下都这么写(hd0,0)/boot/grub/stage1。这是不对的。Linux下的几乎所有目录都是可以挂载的,例如我把/boot挂载到了/dev/hda1上,这样,我写(hd0,0)/grub/stage1就相当于/boot/grub/stage1,这点一定要弄清楚!在举一个例子,如果我把/home挂载到/dev/hda7上,那么(hd0,6)/smileonce指向的就是/home/smileonce。

三、grub引导环境的使用技巧

有一些tip可能你花了很上时间才学到,比如我当初就想像不出在输入grub命令的时候,按tab键居然有提示,比如install (hd0,然后我按tab,那么会提示一堆设备列表的清单。在系统启动的时候,按c可以进入grub命令环境,按e可以编辑当前菜单条目的命令,按b重新执行boot等等。这些需要看一些grub的文档才能彻底掌握。

四、发烧级技巧

有很多人问:XX版本的Linux只有ISO能不能从硬盘安装?其实现在发行的版本(老版本可能不支持),都支持从硬盘安装,并且连ISO都不需要解压缩开。

实现原理说穿不值一钱:利用ISO一个叫做boot目录中提供的boot盘引导用的压缩内核,用grub挂载引导这个内核,而Linux安装程序又支持从ISO中寻找目录。注意,如果安装盘有几张,ISO应该除序号外名字都一致(默认你下载的光盘镜像都是这样的),这样安装程序才会自动换盘;否则就需要手动切换控制台,然后手动mount,就麻烦了。

举个例子如下:

title From HD
root (hd0,6)
kernel /isolinux/kernel devfs=nomount vga=normal load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=22000 root=/dev/ram0 rw
initrd /isolinux/rescue.gz

(hd0,6)是ISO文件所在的设备位置(改成你的实际位置),把ISO放在该分区根目录。那个kernel和rescue.gz文件在你Linux安装盘的第一张盘的boot目录里面有,自己找一下,不同版本Linux可能名字不同。

FC6启动过程分析——从run level 到 log in

根据inittab的指示,在启动完rc.sysinit之后,init程序将进入相应的运行级别,并运行这个级别的脚本。 默认的运行级别也是在inittab中指定的,一般设置为3或者5,两者的区别在于是否默认进入图形模式(启动XWindow)。

启动脚本是通过/etc/rc.d/rc这个程序运行的,它做的事情也不算很复杂,首先它将根据你是否在前面的rc.sysinit的时候摁下"I"键来决定是交互启动模式还是非交互启动模式并且进行相应的输出,然后,依次运行位于相应启动级别目录(/etc/rc.d/rc启动级别.d/)中的脚本,运行的次序是,首先按照名称顺序运行那些K打头的脚本,然后按照名称顺序运行那些S打头的脚本。如果是交互启动模式,它将在运行每个S打头的脚本之前,询问你是否运行这个脚本。

由于脚本运行的顺序是按照字母顺序,你就可以理解为什么在每个脚本之前要被加上一个两位的数字,这只是为了在排列脚本执行顺序的时候显的更直观,另外,所有的启动脚本文件都存在在/etc/rc.d/init.d目录中,位于不同启动级别下的脚本是指向 /etc/rc.d/init.d目录中相应脚本的符号链接。启动脚本符号链接中的数字是怎么来的呢,它是由你指定的,如果你要增加自己的启动脚本到相应的启动级别中去,这个数字当然应该由你指定,因为只有你才知道这个脚本应该以什么样的优先级启动。但是对于那些已经存在的启动脚本,作为FC6发行的一部分,它们的优先级是在脚本中最前面的注释行中的chkconfig这一行指定的,在这一行中,你可以看到类似# chkconfig: 35 99 95的字样,它的含义是:这个脚本应该增加到运行级别3和运行级别5中,启动的优先级是99,关闭的优先级是95,当然,这些数字是由那些FC6的开发者测试过没有问题,所以才写在这里的。一个二进制的程序/sbin/chkconfig将会读取这一行,并且在将服务增加到启动级别中去的时候自动生成文件名。

文件名中的第一个字符S和K代表了什么含义呢?它代表了你在services控制面中选择了打开这个服务还是关闭这个服务,如果你在那里打开了这个服务,则以S作为前导符,否则为K,结合我们前面介绍的启动过程,你就可以知道,在启动的时候,FC6会首先保证那些K打头的脚本是关闭的(通过以stop参数调用这个脚本),然后才会逐个启动那些S打头的脚本(通过以start参数调用这个脚本)。

对于每个启动脚本文件,如果想知道启动了时候都做了些什么,可以查看相应脚本中的start()函数,比如对于avahi-dnsconfd这个脚本,我们可以看到,它只是运行了/usr/sbin/avahi-dnsconfd -D这个命令。

除了位于系统控制面板中对各个services的简单描述以外,你还可以在 http://www.mjmwired.net/resources/mjm-services-fc5.html 找到对各个Fedora Core服务功能的描述以便决定是启动还是关闭某个服务。

在所有需要启动的服务都启动完毕以后,rc程序通过rhgb-client程序通知rhgb图形界面退出,rhgb的使命就完成了。

接下来,init程序在tty1-tty6启动mingetty程序,从现在开始,你可以通过Ctrl-Alt+F1..F6在各个不同的tty之间进行切换了。

然后,如果当前启动级别为5,init程序通过调用/etc/X11/prefdm程序,启动一个图形界面的登录屏幕,让用户登录。这个程序将会读取位于 /etc/sysconfig/desktop中的配置文件,如果没有指定任何配置文件,prefdm运行的顺序依次为gdm,kdm和xdm.

后面的启动部分就属于Gnome,Kde或者其它相应的窗口管理器了。

FC6启动过程分析——Init 过程

在上一篇文章中,我们介绍了从上电到切换到真正的root之前,FC6都做了哪些事情,接下来,我们将开始介绍从切换到真正的Root到图形界面的用户登录,FC6都做了哪些事情。在切换到真正的Root以后,FC6将电脑的控制权交给真正的init程序,通常使用的都是标准的SysVinit程序,这个程序读取配置文件/ets/inittab,然后按照其中的配置执行指定的任务。研究这个文件,就可以了解从切换到新Root,到提示用户登录,FC6都做了哪些事情。

首先,这个配置文件指定运行文件/etc/rc.d/rc.sysinit,这是个使用bash的执行的脚本文件,它首先检测一些基本系统的挂载情况,然后从/etc/sysconfig/network文件中读取网络配置,检查SELinux(安全性增强Linux)的状态,然后开始设置终端字体(使用/sbin/setsysfont命令,这个命令将读取/etc/sysconfig/i18n配置文件,然后开始打印 "Welcome to Fedora ..."的字样,其中Fedora是从配置文件/etc/redhat-release中读取的。然后开始提示按"I"键将进入交互启动模式,在这种模式,你可以选择是否启动某个特定的服务。然后,使用/sbin/hwclock这个程序从BIOS中读取系统时间,其间使用了配置文件 /etc/sysconfig/clock,然后杀死所有的nash(我们在initrd中使用的shell)进程,启动udev(动态设备管理进程,通过监视sysfs按照规则动态创建/dev目录中的设备,已经逐渐取代了hotplug和coldplug).

然后rc.sysinit程序检查/etc/sysconfig/modules/下的所有的脚本,如果找到可以执行的脚本,就执行它,这里的脚本通常用来定义一些用户级别的模块加载。我想如果你希望额外加载一些比如遥控器之类的模块,你可以在这里增加脚本。

然后,FC6准备进入图形界面继续init过程,进入初始化需要满足的条件包括内核命令行参数中包含rhgb参数并且不包含early-login参数, BOOTUP="color",GRAPHICAL="yes"(这些变量在/etc/sysconfig/init定义)并且 /usr/bin/rhgb是可执行的程序。如果所有这些条件都满足,那么现在将执行rhgb程序. rhgb程序的作用是在启动的时候建立一个临时的仅使用loopback网络的X窗口服务器,然后在这个窗口上显示启动进度,init程序的其他部分可以通过rhgb-client程序向这个进度窗口发送消息,rhgb-client使用到的update参数是在rhgb的代码中写死的,总共有20个步骤,从最开始的"RCclock"到最后的"loginscreen"。

现在我们已经进入了FC6启动的图形界面部分。解下来首先做的事情是在运行期配置内核参数,读取的配置文件是/etc/sysctl.conf,然后是加载键盘配置,你在安装FC6的时候可能被问到这个选项,配置文件是/etc/sysconfig/keyboard,然后是使用hostname命令设置主机名,接下来如果/proc/acpi目录存在则尝试加载所有位于/lib/modules/$unamer/kernel/drivers/acpi/中的模块。然后尝试设置RAID(磁盘阵列) 加载相应模块并按需进行磁盘加密, 根据配置文件/etc/sysconfig/autofsck,/etc/sysconfig/readonly-root以及命令行参数中指定的属性决定是否对磁盘进行检查以及判断检查的结果。根据内核命令行参数决定是否进行磁盘限额检查。

重新将根分区挂载为读写模式,删除在磁盘检查过程中产生的临时文件并更新/etc/mtab文件,挂载fstab中所有非网络分区的分区并且打开磁盘限额配置。

按需要进行本机配置:如果存在/.unconfigured文件,调用/usr/bin/system-config-keyboard配置键盘,调用 /usr/bin/passwd root配置超级用户密码,调用/usr/sbin/netconfig配置网络,调用/usr/sbin/timeconfig配置时区,调用 /usr/sbin/authconfig --nostart配置网络登录,调用/usr/sbin/ntsysv配置默认的运行级别。清空包括/var/lock/,/var/run/, /tmp等在内的临时目录并创建新的临时文件,初始化串口,按照内核命令行参数的指示加载scsi相关模块,进行网络配置等(netprofile=), 创建/.autofsck文件,这个文件应该在关机的时候被删除,如果没有被删除说明没有正常关机,将会执行磁盘检测。

现在,检查用户是否按下了"I"键来决定是否运行交互模式的启动。至此,rc.sysinit完成了。


附 inittab 文件的解析

Linux 内核启动之后,启动的第一个进程就是 init 进程。该进程从 /etc/inittab 文件中读取配置,对系统进行一系列的初始化工作。下面我们来分析一下 /etc/inittab 文件的结构。

inittab 文件的每一行的基本格式如下所示:

l3:3:wait:/etc/rc.d/rc 3
可以看到,该行使用冒号分成了四段。各段的意思如下。

1. ID
用于标识该配置项的 id,长度为 1~4 个字符。
2. 运行级
列出在哪些运行级时执行该配置项的命令。本例表明使用运行级3 启动系统时执行该条指令。
3. 动作
指示该条命令应该如何执行。本例中动作为 wait,表示在这条命令未执行完之前不要去执行下一条命令。
4. 进程
执行该项时需要启动的可执行文件名及其参数。

常见的动作如下所示。

initdefault: 该配置项指定系统的默认运行级。
respawn: 该配置项所指定的进程如果被结束,则重新启动该进程。
wait: 该配置项指定的进程在运行结束之前不要执行下一条配置项。
once: 切换到对应的运行级之后,仅执行指定的进程一次。
sysinit: 无论以什么运行级启动,系统启动时都要执行该配置项指定的进程。
boot: 仅在系统启动时执行一次。
bootwait: 仅在系统启动时执行一次,在执行结束之前不执行下一条配置项
powerfail: 当接收到UPS的断电通知时执行该项指定的进程。
powerwait: 与powerfail相同,但init会等待进程执行结束。
powerokwait: 接收到UPS的供电通知时执行。
ctrlaltdel: 当用户同时按下 Ctrl+Alt+Del 时执行该项指定的进程。
下面我们看看实际的例子。这是 Fedore Core 3 的 /etc/inittab 文件。删掉了其中的一些注释,并适当地对每一行增加了解释。

# 下面用 initdefault 动作设置默认的运行级。注意该项没有指定进程,
# 但是最后的分号不要漏掉
# 0 - 关机 (不要将此运行级设为默认)
# 1 - 单用户模式
# 2 - 多用户,不支持 NFS。若无网络则与 3 相同
# 3 - 完整的多用户模式
# 4 - 未使用
# 5 - X11图形界面
# 6 - 重新启动 (不要将此运行级设为默认)

# id:5:initdefault:

# 系统初始化,包括主机名设置、激活交换分区、检查根分区、
# 以读写方式加载根分区、加载 /etc/fstab 中的分区、
# 激活磁盘配额、加载内核模块等功能
si::sysinit:/etc/rc.d/rc.sysinit

# 执行 rc 脚本,启动各种系统服务
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6

# 接管 CTRL-ALT-DELETE,按下时重新启动系统 ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# 当 UPS 发来断电通知时,准备在 2 分钟之后关闭系统 pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"

# 如果在关闭系统之前 UPS 恢复供电,则取消关闭系统 pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"

# 在标准运行级时启动虚拟终端。这里准备了六个虚拟终端,

# 要想改变虚拟终端的数目,只需要增删这里的配置项即可 1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6

# 运行级 5 的时候启动 X 的登录管理器
x:5:respawn:/etc/X11/prefdm -nodaemon