百度首页 | 百度空间
 
文章列表
 
您正在查看 "Tutorials" 分类下的文章

2008-01-30 21:47
版权信息:该文章版权由岳光所有.可在非商业目的下任意传播和复制.对于商业目的下对本文的任何行为需经作者同意.联系方式:ygxy@msn.com

    制作软盘Linux(即在软盘上放一个Linux系统)的目的在于可以深入了解Linux的结构,可利用软盘起动机器修复系统,抢救数据.注意!!:软盘 Linux和Linux启动盘不同,后者只是将核心放于软盘,引导硬盘上的Linux系统,而前者是存在于软盘上的Linux系统.

成功的制作有用的软盘Linux在于:
1)编译一个足够小而且有一定功能的内核.
2)采用busybox并适当的编译它.
3)创建系统必需的目录和文件(如/dev,hda,inittab等)
4)配置引导程序GRUB
5)将以上三点恰当的组织在软盘上.
本文将按照以上顺序介绍制作软盘Linux的方法.
(busybox是一个微小的程序可以让系统提供ls,ash,rm,cp,init等多种服务,它只有一个很小的busybox文件,用ls,rm,init联接他,执行这些联接就可运行相应的服务)

准备:创建/tmp/floppy目录存放临时文件.

I.)编译内核
make mrproper
拷贝../SRC/configs/i386-BOOT(类似文件)到.../SRC/.config
make menuconfig
(最好去掉第二项中所有的*以去掉对模块的支持.必需使核心支持 RamDisk其余选项自定)注意:!!完全去掉网络功能可能造成编译失败(2.4.20-8内核即如此),但可部分去掉.)
make dep
make clean
make bzImage
../SRC/arch/i386/boot/bzImage即为内核
编译成功的内核应不超过1M

II.)编译busybox
busybox源程序可在RedHat的网站上(ftp//ftp.redhat.com/pub/redhat/linux/9/en/os/i386/SRPMS)找到相应的软件包.假设安装后源码目录为/../src/busybox
修改/../src/busybox/Config.h文件,在不用的功能前加//
修改/../src/busybox/Makefile文件,将DOSTATIC=true
执行:
make
(生成的名为busybox的文件大小应在650K左右)
make PREFIX=/tmp/floppy install
(此时在/tmp/floppy目录下即有Linux启动运行所必须的目录和文件了)

III.)创建系统必需的目录和文件
1.在/tmp/floppy目录下
mkdir proc mnt etc dev
在etc目录下创建inittab文件和rc.S文件(用vi)
执行:
chmod 777 inittab
chmod 777 rc.S

inittab内容为:
::sysinit:/etc/rc.S
::askfirst:/bin/sh

rc.S文件内容为:
#!/bin/sh
mount -t proc /proc /proc

2.在dev目录下创建设备文件
应创建的设备文件有:console, hda, hda1, hda2, hda3...(根据硬盘分区数而定), hdb, hdc, hdd, tty, tty0, tty1, fd0, null, loop0, ram0, tty5
相应的文件在/dev下都可找到但不能复制,须自己创建:
这里采用mknod命令语法如下:
mknod 文件名 类型 MAJOR MINOR
类型 MAJOR MINOR可用ls -l在/dev下查找.(权限串的前一位即为"类型")
如创建console文件须在/tmp/floppy/dev下执行:
mknod console c 5 1

IV.)配置grub并组织软盘.
1.取一张格式化为ext2的空盘.在其上创建boot boot/grub目录
拷贝/boot/grub/stage1和stage2到软盘的boot/grub下
执行:
grub
root (fd0)
setup (fd0)
quit
至此grub安装成功!

在软盘的boot/grub目录下创建grub.conf文件
内容为:
default=0
timeout=10
title Linux
    root (fd0)
    kernel /bzImage
    initrd /image.gz
grub配置成功!
拷贝bzImage到软盘根目录下.

2.
cd /tmp
dd if=/dev/zero of=image bs=1k count=2048
losetup /dev/loop0 image
mke2fs -m 0 /dev/loop0
mount -t ext2 /dev/loop0 /mnt
cp -R floppy/* /mnt
umount /mnt
losetup -d /dev/loop0
sync
dd if=image|gzip -9>image.gz
拷贝image.gz到软盘根目录下.

至此,软盘Linux制作成功!重新启动用软盘引导看看自己制作的Linux吧!
类别:Tutorials | 评论(2) | 浏览()
 
2008-01-04 21:27
先介绍一些文件的基本概念, 文件实际上是一个指向inode的链接, inode链接包含了文件的所有属性, 比如权限和所有者, 数据块地址(文件存储在磁盘的这些数据块中). 当你删除(rm)一个文件, 实际删除了指向inode的链接, 并没有删除inode的内容. 进程可能还在使用. 只有当inode的所有链接完全移去, 然后这些数据块将可以写入新的数据.
  
    proc文件系统可以协助我们恢复数据. 每一个系统上的进程在/proc都有一个目录和自己的名字: 里面包含了一个fd(文件描述符)子目录(进程需要打开文件的所有链接). 如果从文件系统中删除一个文件, 此处还有一个inode的引用:
/proc/进程号/fd/文件描述符 DL.bitsCN.com网管软件下载
    接下来, 你需要知道打开文件的进程号(pid)和文件描述符(fd). 这些都可以通过lsof工具方便获得, lsof的意思是”list open files, 列出(进程)打开的文件”. 然后你将可以从/proc拷贝出需要恢复的数据. bitsCN_com
下面介绍在Fedora Core 5系统上使用lsof恢复误删的文件:
环境
主机: 使用微睦独立主机, 一台基于vmware的虚拟独立主机.
系统: Fedora Core 5
内核: 2.6.16-1.2122_FC5
lsof版本: www_bitscn_com
[zhaoke@fedora5 ~]$ /usr/sbin/lsof -v
lsof version information:
revision: 4.77 bitsCN.nET中国网管博客
预备工作:
如果你的系统没有安装lsof, 可以从作者网站或pbone获得.
作者网站: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/
Pbone: http://rpm.pbone.net/ www.bitsCN.com
恢复过程:
首先, 我们需要创建一个文本文件, 删除然后恢复:
[zhaoke@fedora5 ~]$ man lsof | col -b > myfile
然后看一下文件内容:
[zhaoke@fedora5 ~]$ less myfile 中国网管论坛
你可以看到lsof所有的文本帮助信息.
现在按Ctrl-Z退出less命令, 然后在shell提示符下查看文件属性信息:
[zhaoke@fedora5 ~]$ stat myfile
File: `myfile’
Size: 116549 Blocks: 240 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 492686 Links: 1
Access: (0664/-rw-rw-r–) Uid: ( 505/ zhaoke) Gid: ( 505/ zhaoke)
Access: 2006-11-20 12:59:38.000000000 +0800
Modify: 2006-11-20 12:59:34.000000000 +0800
Change: 2006-11-20 12:59:34.000000000 +0800
没问题, 继续下面工作:
[zhaoke@fedora5 ~]$ rm myfile
[zhaoke@fedora5 ~]$ ls -l myfile
ls: myfile: No such file or directory
[zhaoke@fedora5 ~]$ stat myfile
stat: cannot stat `myfile’: No such file or directory
myfile文件删除了.
这时候, 你不要终止仍在使用文件的进程. 因为一旦终止, 文件将很难恢复.
现在我们开始找回数据, 首先用lsof查看一下:
[zhaoke@fedora5 ~]$ lsof | grep myfile
less 9104 zhaoke 4r REG 253,0 116549 492686 /home/zhaoke/myfile (deleted)
第一个纵行是进程的名称(命令名), 第二纵行是进程号(PID), 第四纵行是文件描述符(r意思是普通文件), 现在你知道9104进程仍有打开文件, 文件描述符是4. 那我们开始从/proc里面拷贝出数据. 你可能会考虑使用cp -a, 但实际上没有作用, 你将拷贝的是一个指向被删除文件的符号链接:
[zhaoke@fedora5 ~]$ ls -l /proc/9104/fd/4
lr-x—— 1 zhaoke zhaoke 64 Nov 20 13:00 /proc/9104/fd/4 -> /home/zhaoke/myfile (deleted)
[zhaoke@fedora5 ~]$ cp -a /proc/9104/fd/4 myfile.wrong
[zhaoke@fedora5 ~]$ ls -l myfile.wrong
lrwxrwxrwx 1 zhaoke zhaoke 29 Nov 20 13:02 myfile.wrong -> /home/zhaoke/myfile (deleted)
[zhaoke@fedora5 ~]$ file myfile.wrong
myfile.wrong: broken symbolic link to `/home/zhaoke/myfile (deleted)’
[zhaoke@fedora5 ~]$ file /proc/9104/fd/4
/proc/9104/fd/4: broken symbolic link to `/home/zhaoke/myfile (deleted)’
然后, 使用cp拷贝出数据: bitscn.com
[zhaoke@fedora5 ~]$ cp /proc/9104/fd/4 myfile.saved
最后, 确认一下文件:
[zhaoke@fedora5 ~]$ ls -l myfile.saved
-rw-rw-r– 1 zhaoke zhaoke 116549 Nov 20 13:03 myfile.saved
[zhaoke@fedora5 ~]$ man lsof | col -b > myfile.new
[zhaoke@fedora5 ~]$ cmp myfile.saved myfile.new
cmp比较无任何显示, 表示两个文件完全相同, 恢复成功. bbs.bitsCN.com
参考:
Bring back deleted files with lsof
类别:Tutorials | 评论(0) | 浏览()
 
2007-11-08 07:53
作为一个多用户、多任务的操作系统,Linux下的文件一旦被删除,是难以恢复的。尽管删除命令只是在文件节点中作删除标记,并不真正清除文件内容,但是其他用户和一些有写盘动作的进程会很快覆盖这些数据。不过,对于家庭单机使用的Linux,或者误删文件后及时补救,还是可以恢复的。

1、Ext2文件系统结构的简单介绍

在Linux所用的Ext2文件系统中,文件是以块为单位存储的,默认情况下每个块的大小是1K,不同的块以块号区分。每个文件还有一个节点,节点中包含有文件所有者,读写权限,文件类型等信息。对于一个小于12个块的文件,在节点中直接存储文件数据块的块号。如果文件大于12个块,那么节点在12个块号之后存储一个间接块的块号,在这个间接块号所对应的块中,存储有256个文件数据块的块号(Ext2fs中每个块号占用4字节,这样一个块中所能存储的块号就是1024/4=256)。如果有更大的文件,那么还会在节点中出现二级间接块和三级间接块。

2、恢复被误删文件的方法

大多数Linux发行版都提供一个debugfs工具,可以用来对Ext2文件系统进行编辑操作。不过在使用这个工具之前,还有一些工作要做。

首先以只读方式重新挂载被误删的文件所在分区。使用如下命令:(假设文件在/usr分区)

mount –r –n –o remount /usr -r表示只读方式挂载;-n表示不写入/etc/mtab,如果是恢复/etc上的文件,就加上这个参数。如果系统说xxx partion busy,可以用fuser命令查看一下是哪些进程使用这个分区上的文件:

fuser –v –m /usr

如果没有什么重要的进程,用以下命令停掉它们:

fuser -k –v –m /usr

然后就可以重新挂载这些文件系统了。

如果是把所有的文件统一安装在一个大的/分区当中,可以在boot提示符下用linux single进入单用户模式,尽量减少系统进程向硬盘写入数据的机会,要不干脆把硬盘挂在别的机器上。另外,恢复出来的数据不要写到/上面,避免破坏那些有用的数据。如果机器上有dos/windows,可以写到这些分区上面:

mount –r –n /dev/hda1 /mnt/had

然后就可以执行debugfs:(假设Linux在 /dev/hda5)

#debugfs /dev/hda5

就会出现debugfs提示符debugfs:

使用lsdel命令可以列出很多被删除的文件的信息:

debugfs:lsdel

debugfs: 2692 deleted inodes found.

Inode Owner Mode Size Blocks Time deleted

164821 0 100600 8192 1/ 1 Sun May 13 19:22:46 2001

…………………………………………………………

36137 0 100644 4 1/ 1 Tue Apr 24 10:11:15 2001

196829 0 100644 149500 38/ 38 Mon May 27 13:52:04 2001

debugfs:

列出的文件有很多(这里找到2692个),第一字段是文件节点号,第二字段是文件所有者,第三字段是读写权限,接下来是文件大小,占用块数,删除时间。

然后就可以根据文件大小和删除日期判断那些是我们需要的。比如我们要恢复节点是196829的文件:

可以先看看文件数据状态:

debugfs:stat <196829>

Inode: 196829 Type: regular Mode: 0644 Flags: 0x0 Version: 1

User: 0 Group: 0 Size: 149500

File ACL: 0 Directory ACL: 0

Links: 0 Blockcount: 38

Fragment: Address: 0 Number: 0 Size: 0

ctime: 0x31a9a574 -- Mon May 27 13:52:04 2001

atime: 0x31a21dd1 -- Tue May 21 20:47:29 2001

mtime: 0x313bf4d7 -- Tue Mar 5 08:01:27 2001

dtime: 0x31a9a574 -- Mon May 27 13:52:04 2001

BLOCKS:

594810 594811 594814 594815 594816 594817 ………………………………….

TOTAL: 38

然后就可以用dump指令恢复文件:

debugfs:dump <196829> /mnt/hda/01.sav

这样就把文件恢复出来了。退出debugfs:

debugfs:quit

另一种方法是手工编辑inode:

debugfs:mi <196829>

Mode [0100644]

User ID [0]

Group ID [0]

Size [149500]

Creation time [0x31a9a574]

Modification time [0x31a9a574]

Access time [0x31a21dd1]

Deletion time [0x31a9a574] 0

Link count [0] 1

Block count [38]

File flags [0x0]

Reserved1 [0]

File acl [0]

Directory acl [0]

Fragment address [0]

Fragment number [0]

Fragment size [0]

Direct Block #0 [594810]

…………………………….

Triple Indirect Block [0]

使用mi指令后每次显示一行信息以供编辑,其它行可以直接按回车表示确认,把deletion time改成0(未删除),Link count改成1。改好后退出debugfs:

debugfs:quit

然后用fsck检查/dev/hda5

fsck /dev/hda5

程序会说找到丢失的数据块,放在lost+found里面。这个目录里的文件就是我们要的东东
类别:Tutorials | 评论(0) | 浏览()
 
2006-06-13 15:50
更新日志
2007年9月8日 本文发布

前言

并行计算一直算是比较专业的领域,当然在Linux下依据现有的开源软件搭建一个并行计算的集群还是相对容易的,通常在Linux下使用 PVM/MPI的方式来实现并行计算集群的,网络上有许多关于PVM和MPICH搭建计算集群的方法,但似乎还没有针对OpenMPI的搭建方式,至少中 文的介绍比较少,所以这里我采用最新的OpenMPI来搭建一个基于LFS平台的集群系统。

本文的目的是为了说明一个简单的并行计算平台搭建的过程 ,作为真正运用的计算集群应该要比这个复杂许多,但通过本文的方法也能体会一下并行计算的感觉。同时,很多人对于LFS的实用性表示怀疑,认为只是一个作 为研究的东西,而不能真正的使用到实际的应用中去,所以我希望通过本系列的文章来表明原代码打造的系统所带来的好处:精简,高效。


更新

由于篇幅比较长所以难免出现一些错误或者笔误,也有可能加入新内容,因此难免会进行修正或增删一些内容,如果本文被转载可以在本人的Blog中查看最新版本。
我的Blog:http://youbest.cublog.cn
如须转载请注明作者为孙海勇,并提供转载出处。


OpenMPI,写本文时最新的版本为1.2.2,你可以尝试下载目前最新的版本来使用。

下载http://www.open-mpi.org/software/omp...-1.2.2.tar.bz2


注意:

OpenMPI所搭建的集群,是利用了特定的通讯方式/协议(当然也可以用TCP协议)来进行各个节点间的协作完成计算的,应此节点间应尽量保证网络通讯的流畅,以避免因网络线路上的问题而导致的性能下降。

本文采用标准的LFS做为基本系统,因此省略了LFS的制作过程。


预期目标:

用两台以上的个人电脑组成一个可以进行并行计算的计算集群,为了说明的方便,本文采用两个计算节点作为例子,两个以上的机器的做法和两台机器基本是一 样的,重复制作就可以完成N个计算机组成的集群,当然这里建立的计算集群是比较简单的,真正的计算集群应该会更加的复杂。

每台计算机我们都可以称为节点,在本例子中有三类节点:控制节点、计算节点、共享存储节点,这三类节点可以相互合并,甚至可以把三类节点放在一个节点 上,这里为了说明方便,我们将三类节点分开来,这里共享存储节点不是必须的,但有了这个节点对于计算任务的发布将变的非常容易,所以本文也将对其进行讲 解。

我们先来看一副即将构建的计算集群的逻辑结构图。

逻辑结构图:


(黄色区域代表相同的共享存储空间)



为了实现这种逻辑可以有多种网络的架设方法,这里选择一个比较简单的架设为例子。



网络结构图:


这里需要注意的事,最好节点都在同一个网段中,而不要通过网关之类的设备,这样不但可以减少问题的发生而且也可以提高计算过程中的通讯性能。



节点的命名和IP分配

控制节点: 192.168.0.1 nfs-node

存储节点: 192.168.0.2 control-node

计算节点: 192.168.0.11 mpi-node1

192.168.0.12 mpi-node2

192.168.0.13 mpi-node3

注:计算节点可以继续增加,这里以三个节点为例子。



前期准备(所有节点)

LFS基本系统

内核需要nfs文件系统支持



建立共享存储节点

设置系统的IP为192.168.0.1

设置系统的机器名为nfs-node

编译软件包

Tcp_wrapper-7.6

Portmap-5beta

NFS Utilities-1.0.10

Blfs-bootscript-20070620

配置NFS(共享存储节点)

mkdir /opt/shared

echo “/opt/shared 192.168.0.0/255.255.255.0(rw,subtree_check,anonuid=99,anongid=99)” >> /etc/exports

启动nfs服务

/etc/rc.d/init.d/nfs-server restart



建立控制节点:

设置系统的IP为192.168.0.2

使节点支持nfs,并挂载存储节点上的共享空间

安装软件包:

Tcp_wrapper-7.6

Portmap-5beta

Blfs-bootscript-20070729

make install-portmap

make install-netfs

挂载共享空间

groupadd -g 99 nogroup

useradd -c "Unprivileged Nobody" -d /dev/null -g nogroup -s /bin/false -u 99 nobody

mkdir /opt/share

chmod 0777 /opt/share

echo “192.168.0.1:/opt/share /opt/share nfs rw,_netdev,rsize=8192,wsize=8192 0 0” >> /etc/fstab

/etc/rc.d/init.d/portmap restart

/etc/rc.d/init.d/netfs start

建立主机名文件

cat > /etc/hosts << “EOF”

127.0.0.1 localhost

192.168.0.1 nfs-node

192.168.0.2 control-node

192.168.0.11 mpi-node1

192.168.0.12 mpi-node2

192.168.0.13 mpi-node3



为编译OpenMPI做准备

提示:由于软件包编译时间较长应此,对于节点的硬件结构相同的机器应当在一台机器上编译完成后,直接把编译好的东西复制到其它结点上,以加速集群的建设,同时对于今后加入新的节点提供了方便。

在控制节点上(当然其它节点也可以,不过这里为了简化说明,我就在控制节点上进行)

1)创建计算用户(同时“兼职”编译用户)

useradd -s /bin/bash -m -k /dev/null youbest

su - youbest

mkdir ~/sources

2)将需要的软件包复制到~/sources/目录下。

3)设置编译安装用的环境变量

export DEST_DIR=~/packages

4)编译Openssh,以支持节点间的相互通讯。

OpenSSL-0.9.8e

patch -Np1 -i ../openssl-0.9.8e-fix_manpages-1.patch

./config --openssldir=/etc/ssl --prefix=/usr shared

make MANDIR=/usr/share/man

make test(这里应该正常通过测试,如果进行测试建议先安装bc软件包)

su root

make MANDIR=/usr/share/man install

make MANDIR=/usr/share/man INSTALL_PREFIX=${DEST_DIR} install

cp -v -r certs /etc/ssl

cp -v -r certs ${DEST_DIR}/etc/ssl

exit

OpenSSH-4.6p1

su root

install -v -m700 -d /var/lib/sshd

install -v -m700 -d ${DEST_DIR}/var/lib/sshd

chown -v root:sys /var/lib/sshd

chown -v root:sys ${DEST_DIR}/var/lib/sshd

/usr/sbin/groupadd -g 50 sshd

/usr/sbin/useradd -c 'sshd PrivSep' -d /var/lib/sshd -g sshd -s /bin/false -u 50 sshd

exit

sed -i "s:-lcrypto:/usr/lib/libcrypto.a -ldl:g" configure

sed -i "s/lkrb5 -ldes/lkrb5/" configure

./configure --prefix=/usr --sysconfdir=/etc/ssh \
--libexecdir=/usr/lib/openssh --with-md5-passwords \
--with-privsep-path=/var/lib/sshd

make

su root

make install

make DESTDIR=${DEST_DIR} install

echo "PermitRootLogin no" >> /etc/ssh/sshd_config

echo “PermitRootLogin no” >> ${DEST_DIR}/etc/ssh/sshd_config

exit

blfs-bootscripts-20070620

su root

make install-sshd

make DESTDIR=${DEST_DIR} install-sshd

exit


5)编译OpenMPI及其依赖包(推荐)

1、由于OpenMPI目前支持几种语言,所以如果你还是比较标准的LFS基本系统建议重新编译GCC以加入fortran语言的支持,如果你只想让OpenMPI支持C,那么可以跳过这段gcc的重新编译

1)gmp-4.2.1

./configure --prefix=/usr --enable-cxx --enable-mpbsd

make

make check (这里的测试应该正常通过)

su root

make install

make DESTDIR=${DEST_DIR} install

exit

2)mpfr-2.2.1

./configure --prefix=/usr --enable-shared

make

make check(这里的测试应该正常通过)

su root

make install

make DESTDIR=${DEST_DIR} install

exit

3)gcc-4.1.2

sed -i 's/install_to_$(INSTALL_DEST) //' libiberty/Makefile.in

sed -i 's@\./fixinc\.sh@-c true@' gcc/Makefile.in

sed -i 's/@have_mktemp_command@/yes/' gcc/gccbug.in

mkdir ../gcc-build

cd ../gcc-build

../gcc-4.1.2/configure \
--prefix=/usr \
--libexecdir=/usr/lib \
--enable-shared \
--enable-threads=posix \
--enable-__cxa_atexit \
--enable-clocale=gnu \
--enable-languages=c,c++,fortran

make bootstrap

su root

make install

make DESTDIR=${DEST_DIR} install

ln -sfv ../usr/bin/cpp /lib

mkdir -p ${DEST_DIR}/lib

ln -sfv ../usr/bin/cpp ${DEST_DIR}/lib

ln -sfv gcc /usr/bin/cc

ln -sfv gcc ${DEST_DIR}/usr/bin/cc

chown -Rv root:root /usr/lib/gcc/$(gcc -dumpmachine)/4.1.1/include

chown -Rv root:root ${DEST_DIR}/usr/lib/gcc/$(gcc -dumpmachine)/4.1.1/include

exit

编译OpenMPI

tar xvf openmpi-1.2.3.tar.bz2

mkdir openmpi-build

cd openmpi-build

../openmpi-1.2.3/configure --prefix=/usr --sysconfdir=/etc/openmpi

make

make check (这里测试应该正常通过)

su root

make install

make DESTDIR=${DEST_DIR} install

exit

将之前编译的软件包一起打包,便于其它节点直接安装

su root

pushd ${DEST_DIR}

(压缩前可以先进行去除调试符的操作以减少空间占用,不过如果对空间不是很敏感的话不去除调试符也可以)

tar -cjf mpi-packages.tar.bz2 *

mkdir /opt/share/packages/

mv mpi-packages.tar.bz2 /opt/share/packages/

popd

exit

配置SSH

首先保证节点间的通讯畅通无阻,硬件上的不必说,软件上还需要配置一下

su - youbest

ssh-keygen -t rsa

cat ~/.ssh/id_rsa.pub >> /opt/share/authorized_keys





创建计算节点

计算节点的加入方式是相同的,这里以mpi-node1(192.168.0.11)为例子
设置系统的IP为192.168.0.11,机器名设置为mpi-node1
使节点支持nfs,并挂载存储节点上的共享空间

安装软件包:

Tcp_wrapper-7.6

Portmap-5beta

Blfs-bootscript-20070729
make install-portmap
make install-netfs

挂载共享空间

groupadd -g 99 nogroup

useradd -c "Unprivileged Nobody" -d /dev/null -g nogroup -s /bin/false -u 99 nobody

mkdir /opt/share

chmod 0777 /opt/share

echo “192.168.0.1:/opt/share /opt/share nfs rw,_netdev,rsize=8192,wsize=8192 0 0” >> /etc/fstab

/etc/rc.d/init.d/portmap restart

/etc/rc.d/init.d/netfs start

建立主机名文件

cat > /etc/hosts << “EOF”

127.0.0.1 localhost

192.168.0.1 nfs-node

192.168.0.2 control-node

EOF

cat > /etc/hosts.equiv << “EOF”

control-node

EOF

建立OpenMPI软件环境

su root

tar xvf /opt/share/packages/mpi-packages.tar.bz2 -C /



建立计算用户:

这里建立一个youbest的用户名用于集群计算

useradd -s /bin/bash -m -k /dev/null youbest



配置ssh

su - youbest

mkdir ~/.ssh

cp /opt/share/authorized_keys ~/.ssh/authorized_keys

chmod 0600 ~/.ssh/authorized_keys



在控制节点上“登记”刚刚建立的计算节点(控制节点)

su root

echo “192.168.0.11 mpi-node1” >> /etc/hosts

echo “mpi-node1” >> /etc/hosts.equiv

echo “mpi-node1” >> /etc/openmpi/openmpi-default-hostfile

或者用编辑软件编辑openmpi-default-hostfile文件加入mpi-node1

注:如果节点有多个CPU,那么可以在mpi-node1后加入”:CPU数”,如:mpi-node1的节点有两个CPU,那么可以在openmpi-default-hostfile中写入

mpi-node1 slots=2

来表示,这样可以更加有效的利用计算资源。

exit



建立其它计算节点:

这里有两种方法来建立

1) 按照mpi-node1的建立方法来一遍,在IP和机器名的地方修改为新节点的IP和机器名即可;

2) 直接将mpi-node1中所有的文件复制到新节点上,然后修改IP和机器名为新的节点的IP和机器名即可。

在建立好新的节点后都要在控制节点上“登记”刚刚建立的计算节点,以便进行计算时使用该节点。



测试ssh工作是否正常

在控制节点上运行

ssh mpi-node1 date

ssh mpi-node2 date

……

如果上述命令执行后应该直接返回日期而不会提示输入密码,那么可以继续了,否则请检查之前的操作是否有遗漏或错误。



加入到控制节点上openmpi-default-hostfile文件中的就是参与集群运算的节点,这里也可以将control-node加入到其 中,但如果计算节点较多建议不要把control-node加入,因为控制节点除了运算还要处理节点的调度,所以control-node加入运算反而可 能降低运算效率。



建立计算用目录(控制节点)

mkdir /opt/shared/test

在用户目录建立链接(控制节点及所有的计算节点)

ln -s /opt/shared/test ~/



到目前为止我们的集群环境已经搭建完成,现在可以找一个程序来测试一下了。

如果你编译Openmpi的源代码目录还没有删除,那么可以进入其目录中的example下,编译hello_c.c文件

make hello_c

会生成一个hello_c可执行文件,将该文件复制到/opt/shared/test目录下

然后在控制节点上运行

mpirun /opt/shared/test/hello_c

你将会看到多个节点的显示返回,代表集群搭建成功了。



下面我们来做一个比较能测试性能的程序,这里利用另一个mpi的软件mpich中带有一个pi的运算程序,在控制节点上编译该文件(mpich软件包可以自行到mpich的网站上下载)

mpicc icpi.c -o pi



然后将pi复制到/opt/shared/test目录下

运行mpirun -n 1 /opt/shared/test/pi (以一个节点的方式运算)

提示输入一个数,你可以按10倍的速度逐步增加,当增加到运行需要不少的时间后,重新运行

mpirun -n 2 /opt/shared/test/pi (两个节点来运算)

或者

mpirun /opt/shared/test/pi(所有的节点均参加运算)

看看是否节点越多,输入同样的数字运算速度越快。:)



好了,到此为止你已经有了一个可以实际工作的计算集群了,你可以继续添加节点来提高并行性能。把没有用的机器集合到一起看看是否可以把这些机器再利用一下。



新的尝试

前面我们是在相同架构的机器来搭建的计算集群,下面我们尝试使用不同架构的机器来搭建一个计算集群。

例如我们在上面的计算集群上加入一组由龙芯CPU为核心的机器,那么我们可以按照下面的步骤加入,下面的方法同样适合加入一台机器。

这组机器我们定义它的名字和IP为:

192.168.0.21 loongson-node1

192.168.0.22 loongson-node2

192.168.0.23 loongson-node3

因为采用的是不同体系的机器,那么之前编译的系统不能用在这些机器上,需要重新编译OpenMPI所需要的所有依赖的包,但同样可以在一台机器完成了编译之后直接应用到其它相同体系结构的机器上运行。

虽然体系不同,但编译过程大同小异(可能有些体系需要打一些补丁),下面仅讲述搭建步骤,编译过程省略。

这里以loongson-node1为例,在其上

1) 安装所有LFS标准包

2) 内核支持NFS

3) 设置机器的IP为192.168.0.21,机器名为loongson-node1

4) 安装软件包以支持NFS

Tcp_wrapper-7.6

Portmap-5beta

Blfs-bootscript-20070729
make install-portmap
make install-netfs

5) 配置NFS

groupadd -g 99 nogroup

useradd -c "Unprivileged Nobody" -d /dev/null -g nogroup -s /bin/false -u 99 nobody

mkdir /opt/share

chmod 0777 /opt/share

echo “192.168.0.1:/opt/share /opt/share nfs rw,_netdev,rsize=8192,wsize=8192 0 0” >> /etc/fstab

/etc/rc.d/init.d/portmap restart

/etc/rc.d/init.d/netfs start

6) 建立主机名文件

cat > /etc/hosts << “EOF”

127.0.0.1 localhost

192.168.0.1 nfs-node

192.168.0.2 control-node

EOF

cat > /etc/hosts.equiv << “EOF”

control-node

EOF

7) 编译gmp、mprf、gcc(为了包含fortran,推荐)

8) 编译openmpi

9) 将编译的各个包合在一起打包,以便今后同样的机器加入节点方便安装。

10) 创建用于计算的用户

注意:这里建立的用户名必须和控制节点上进行计算的用户名相同。

11) 建立计算用目录(控制节点)

mkdir /opt/shared/test-loongson

在用户目录建立链接(控制节点及所有的计算节点)

ln -s /opt/shared/test-loongson ~/test

12) 配置SSH,以便控制节点使用该节点进行计算

13) 在控制节点上“登记”刚刚建立的节点



现在我们已经加入了一个体系结构不同于之前计算节点的机器,下一步就是要探讨一下如何让不同体系架构的计算机同时进行同一项计算任务。



MPI是采用消息的方式进行计算控制的,应此这个过程是指令集无关的,利用这个特点,不同指令集的机器可以进行协同计算,下面我根据前文所建立的两种不同指令集的机器进行一次集群计算任务。

还是使用之前用过的MPICH源代码下的icpi.c文件,将该文件复制到/opt/shared/test-loongson下,然后在刚刚建立的龙芯机器上编译该文件

pushd /opt/shared/test-loongson

mpicc icpi.c -o pi

popd

这样我们就有了一个可以在龙芯机器上运行的集群计算的可执行文件,由于/opt/shared/test-loongson链接到~/test上,那么对于之前的节点中编译的pi和现在龙芯中编译的pi文件所处的位置是相同的,这个时候我们可以在控制节点上执行

mpirun ~/test/pi

如果之前的操作没有问题,那么这个时候将出现请求输入的界面,输入数字后,计算便开始了,在不久后(视你输入数字的大小)你将见到计算结果。

好了,一个多种架构的计算集群搭建完成,而对于在控制节点上进行计算任务的人来说完全感觉不到这个计算集群是由不同指令集来搭建的。

我们可以再加入更多不同类型的机器来构建这样一个集群,是不是很有意思?:-)


性能调节:
对计算节点性能的研究,在一个集群中最好是相同工作能力的计算机搭建,如果性能差异比较大,同时配置节点不够合理那么即使计算节点变多了,可能计算性能反而下降了。我这里给出一个简单的设计原则

以速度最慢的节点作为单位1,如果比该节点速度快一倍则在openmpi-default-hostsfile文件中将该节点的slots的值设置为2,以此类推,快多少倍就设置slots的值为倍数即可

曾经做过一个优化的设置和没优化的设置,在两个单节点的机器上做集群计算,在其中比较快的节点上单独运行pi计算使用了5秒左右,而在慢的节点上单独 计算则需要20秒左右,而如果两个节点都不设置slots的值则使用10秒左右,这大大超过了最快的节点单独运算所耗费的时间,计算节点增加了,但计算速 度却降低了,之后进行了优化设置,将比较快的节点的slots值设置为5后,两个节点的计算时间缩小到4秒左右,这样两个节点的计算速度终于要少于最快的 节点单独计算的速度了。


总结:
下面来总结一下本文对于计算集群架设的要点:

1) 所有的节点均建立好了标准的LFS系统,并且内核支持NFS

2) 建立共享存储使用的节点,通过该节点可以非常方便的为后续的节点建立和计算任务的发布提供方便

3) 除了存储节点,其它节点应该安装上openmpi及openmpi所依赖的所有相关软件包,不过为了加快节点的节点可以使用同种类型节点所编译软件包。

4) 建立至少一个控制节点,用于计算任务的发布和计算控制。

5) 建立至少两个计算节点(废话!否则就不是计算集群了)

6) 设置好各个节点的SSH,这里的要点是控制节点可以顺利的通过SSH访问各个计算节点,为了计算方便,发布控制节点的公钥到各个计算节点上。

7) 控制节点的openmpi的配置文件中配置好需要用来计算的节点,而计算节点则不需要进行任何openmpi的配置。

8) 共享存储节点、控制节点及计算节点可以相互合并为一个节点,甚至三种节点可以合并到一台节点上,如果计算机设备比较充裕,建议将三类节点分开。

9) 计算节点可以由不同指令集或者不同计算机架构的节点共同组成,并可以共同完成同一个计算任务。

10) 如果计算节点中包含不同类型的计算节点,则应该在发布计算任务(计算用的可执行文件)的时候应该针对不同的计算节点发布能在该节点上运行的执行文件。

11) 如果计算集群由不同性能的节点构成,那么应该根据性能倍数的原则设置各个节点上slots的值,以便充分发挥集群的计算性能。

补充一下:
本文写好有一段时间了,但没有进行细致的整理,因此一直没有发出来,最近抽了点时间整理了一下发布出来,所以本文中使用的一些软件版本可能已经不是最 新的了,不过这并不影响文章的整体思路,由于本人能力所限文中难免会有错误和偏差,希望发现问题后能及时告诉我,以便最快的进行修改。



(转载请保持文章的完整性,请注明作者和出处)



     作者:孙海勇

Email:youbest@sina.com

发表日期:2007年9月8日
类别:Tutorials | 评论(3) | 浏览()
 
2006-06-03 10:56
终端下正确显示中文相信是大多人头痛的一个问题,现在终于搞定了,就此写出来给各位参考.
首先美化设置一下:
光标选Underline 和Cursor blinks

Font settings Change… 修改成 Fixedsys并且字符集为CHINESE_GB2312

接下来设置字符集:

设置所有字符集为zh_CN.gb2312 date看看是不是对了?

fstab挂挂硬盘的时候用的是utf8字符集所以这里也该一下 设置成 gb2312

E.G.

LANG=zh_CN.gb2312

mount -t vfat -o iocharset=gb2312 /dev/hda4 /mnt/hda4

Linux群:24406485

类别:Tutorials | 评论(3) | 浏览()
 
2006-03-05 11:15
源代码搭建应用(二)——建立自己的Linux LiveCD系统
作者:孙海勇
更新日志
2008年2月12日:本文发布。

前言:
也许有很多朋友想将自己制作的Linux系统应用到自己的实际工作生活中,但往往因为各种原因不能在你操作的机器上安装你要的系统,所以现在出现了各 种不同的LiveCD来解决各种应用方面的需求,可能有朋友对这种LiveCD的制作非常感兴趣,我结合我自己的认识和实际的应用经验总结了一套手工制作 LiveCD的方法,希望对想制作LiveCD或者对这方面感兴趣的朋友有所帮助。
制作LiveCD的方法有很多,我这里只介绍我实际制作LiveCD的方法,与通常制作LiveCD的软件有所不一样,不过效果类似,希望能起到抛砖引玉的效果,如果有什么建议或想法也欢迎一起探讨,共同提高水平。

更新,文章中难免出现一些错误或者笔误,也有可能加入新内容,因此难免会进行修正或增删一些内容,如果本文被转载可以在www.linuxsir.org的LFS版中或者在本人的Blog中查看最新版本。
  linuxsir:http://www.linuxsir.org/bbs/showthread.php?t=322970
  我的Blog:http://youbest.cublog.cn
  如须转载请注明作者为孙海勇(冲天飞豹),并提供转载出处。
  


LiveCD原理分析
启动过程
1)计算机启动光盘上的引导程序,这部分我采用grub来完成,当然还可以使用如lilo,如果是其它非x86架构的机器也可以用其它适合的引导程序。
2)引导程序装入光盘上的Linux内核,并同时装入一个RAM disk,本文中采用grub的功能来完成,RAM disk使用的是initrd的方式,当然也可以采用其它Linux支持的方式,不过可能启动脚本需要进行一定的修改。
3)内核启动后转入到initrd中linuxrc,由linuxrc来完成各种初始化的操作。
4)linuxrc必须是一个可执行文件,这里我们采用的是bash的脚本来完成,本文中的linuxrc主要是完成各种必须的文件加载、设备的识别及内核模块的加载,建立和准备好用户操作根目录环境
5)linuxrc运行结束后会进入根系统的/sbin/init继续执行,该程序将利用/etc/inittab文件来完成系统的启动过程
6)启动完成,进入用户操作模式。
需要注意的地方
1)RAM disk的大小必须小于Linux中对RAM disk设置的大小,如果超过了必须重新配置内核并重新编译。
2)RAM disk所使用的文件系统必须是Linux内核内制支持的,在编译内核的时候不能把该文件系统编译成模块。
3)LiveCD在启动中或者启动后会需要创建或者写入一些文件,所以这部分文件就需要存放在可以写入的文件系统中,这里我采用tmpfs的方式 来存放这些需要变动的文件,经过分析本文所制作的LiveCD需要修改的目录包括/etc、/home、/root、/var,对于/etc则将其打包并 在系统启动中的适当时机解压缩到一个可以写入的空间中,而对于/home、/root、/var本文采用了动态生成生成的方式,当然这个没有必须的方法, 这个需要随具体情况来变化,也都可以采用类似/etc的处理方式。


准备工作:
请按照LFS手册也可以参考我写的《第二版 手把手教你如何建立自己的Linux系统(LFS速成手册)》创建好一个基本的Linux系统,本文的内容将基于一个标准的LFS-6.3系统来完成全部工作。

编译安装必要的工具:
1、squashfs的内核补丁
本文创建的系统利用的是squashfs方式压缩文件系统,所以必须让内核支持squashfs
1)下载squashfs-3.3,并解压缩,在其目录中有linux kernel的补丁,找到你需要的内核补丁,因为LFS-6.3使用的是Linux-2.6.22.5这个版本,因此在内核的源代码目录中使用
patch -Np1 -i <path>/squashfs-3.3/kernel-patch/linux-2.6.22/squashfs-patch
2)重新配置内核,添加如下选项
File systems -> Miscellaneous filesystems -> SquashFS 3.3

3)重新编译安装内核,使其支持squashfs
2、安装squashfs-tools
内核支持squashfs后,还需要有专门的工具来创建squasfs文件,该工具包含在squashfs软件包中,进入squashfs-tools
make
install -m 755 unsquashfs mksquashfs /usr/bin
现在系统已经可以创建并识别squashfs文件系统了。
3、安装cdrtools-2.01
安装这个包是为了使用其包含的命令mkisofs,这个是建立光盘镜像的工具。编译该包可以参考BLFS手册中该软件包部分。
patch -Np1 -i ../cdrtools-2.01-mkisofs_iconv-1.patch
patch -Np1 -i ../cdrtools-2.01-ascii-2.patch
make INS_BASE=/usr DEFINSUSR=root DEFINSGRP=root
make INS_BASE=/usr DEFINSUSR=root DEFINSGRP=root install &&
install -v -m755 -d /usr/share/doc/cdrtools-2.01 &&
install -v -m644 README* ABOUT doc/*.ps \
/usr/share/doc/cdrtools-2.01
好,到目前为止,系统已经具备了创建LiveCD的必要环境,下面就开始讲解创建一个简单的LiveCD的制作步骤。


准备工作目录:
代码:
mkdir -pv /opt/iso/{boot,modules}
cd /opt/iso
编译制作LiveCD专用的内核:
LiveCD可以通过initrd来加载需要的设备驱动,因此建议将不是开始运行就需要的功能都制作成模块形式,这样可以减少内核的体积,同时也可以增加系统的灵活性。
内核必须功能(这些功能必须包含在内核本身,不能以模块的形式出现)
Automatic kernel module loading支持:
这样可以方便今后加载模块。
RAM disk support:
initrd是采用RAM disk的方式使用的,因此内核必须支持该功能
同时,这里设定RAM disk的大小的时候为了方便今后可能的扩展,如果在使用的机器上内存不是很紧张的话建议调整的大一些,我在这里把起调整为10M大小

ext2支持:
因为initrd.img本身是一个ext2的文件系统,所以要想使用initrd就必须让内核能够识别出ext2文件系统。
内核必须的功能,但可以使用模块的形式出现
loop支持:
squashfs需要loop的支持才能正常使用,因此必须包含此功能。
squashfs支持:
这里制作LiveCD的方法中,压缩的文件系统采用squashfs,所以内核也必须包含此功能。
非必须功能:
如网卡、声卡、磁盘驱动等,这些并不是一定需要的,可以根据你的LiveCD的功能来进行取舍,如你需要制作一个应急修复盘,那么磁盘驱动方面就比较重要了,而声卡什么的则不是必须的了;而如果你是要制作一个桌面的LiveCD,那么声卡什么的则非常必要了。
编译内核,将内核文件放入/opt/iso/boot目录中,将模块放入/opt/iso/modules中。


制作LiveCD主系统:
LiveCD主系统用于提供各种软件,整个系统为了减少存放体积,一般使用压缩的文件系统,这里我使用squashfs来制作。
本文使用LFS-6.3的标准系统来制作LiveCD系统,如果你想制作的系统包含更多功能可能需要增加自己的软件后再制作压缩文件系统。
代码:
cd /
mksquashfs bin lib sbin usr SYSTEM

现在在根目录建立好了一个SYSTEM文件,该文件就是一个经过squashfs压缩过的文件系统,将该文件放入“制作基地”中。
代码:
mv /SYSTEM /opt/iso

制作initrd.img:
initrd.img的主要目的是为了在不同的机器环境下只加载适用于该机器的一些内核模块,如果将所有的内核模块都加入到内核文件本身中,那么内核 本身将会变的非常臃肿,且占用需要不必占用的资源,因此一般的LiveCD都将大量的驱动编译为模块形式,在必要的时候才将其加载到内存中,这个时候 initrd的作用就比较明显,initrd一般可以用来检测系统的硬件来适当的加载各种驱动模块。
下面我们就制作一个简单的initrd的实现。
1)建立initrd
代码:
cd /opt/iso/boot
mkdir initrd
dd if=/dev/zero of=initrd.img bs=1M count=8
mkfs.ext2 initrd.img
mount -o loop initrd.img initrd
2)创建initrd下的目录
代码:
export INITRD=/opt/iso/boot/initrd
cd ${INITRD}
mkdir bin boot dev etc lib proc sbin sys
3)确定initrd需要的东西
initrd其实是一个最小化的Linux系统,但又必须包含一些检查硬件设备的功能。
1)一个shell,这里我就直接用bash了,如果你觉得大也可以使用其它的shell,比如csh,或者busybox中包含的shell。
代码:
cp -a /bin/bash ${INITRD}/bin
2)linux kernel模块组,该模块组应该与引导用的内核相匹配,这里直接使用之前为LiveCD专门编译的内核生成的模块。
代码:
mv /opt/iso/modules ${INITRD}/lib
3)Udev,这里我就直接使用udev来进行硬件的检查,并自动加载必要的内核模块了。
代码:
cp -a /lib/udev ${INITRD}/lib
代码:
cp -a /lib/firmware ${INITRD}/lib
代码:
cp -a /dev/{console,null} ${INITRD}/dev
代码:
cp -a /etc/udev ${INITRD}/etc
4)modprobe,udev需要使用该命令工具来加载内核。
5)常用的一些命令。
4)编写linuxrc文件
initrd是从linuxrc文件开始运行的(这个是由内核决定的),那么我们所有的工作就从这个文件开始了
首先是一些特定的文件系统,后面的许多程序需要这些文件系统的支持
代码:
cat > ${INITRD}/linuxrc << "EOF"
#!/bin/bash
mount -t proc proc /proc
mount -t sysfs sysfs /sys

# 如果你将loop模块化,那么需要加入
/sbin/modprobe loop

# 建立/dev设备目录,并使用udev来创建各种设备文件
mount -n -t tmpfs -o mode=0755 udev /dev
cp --preserve=all --recursive --remove-destination /lib/udev/devices/* /dev
chmod 1777 /dev/shm
echo "" > /sys/kernel/uevent_helper
echo "Starting Udev..."
/sbin/udevd --daemon
mkdir -p /dev/.udev/queue
/sbin/udevtrigger
/sbin/udevsettle

# 创建用户使用环境
# 在/SYSTEM中准备目录结构
export SYSTEM=/SYSTEM
mkdir -p ${SYSTEM}
mount -t tmpfs tmpfs ${SYSTEM}
mkdir -p ${SYSTEM}/{system,cdrom,dev,proc,sys,tmp,mnt,initrd,home,root}
chmod 0777 ${SYSTEM}/tmp
chmod 0700 ${SYSTEM}/root

# 搜索LiveCD所在的设备
for i in /proc/ide/hd*
do
if test `cat $i/media` = "cdrom" ; then
mount -t iso9660 /dev/`basename $i` ${SYSTEM}/cdrom 2>/dev/null
if test $? = 0 ; then
if [ -f ${SYSTEM}/cdrom/LABEL ] ; then
if grep -q "Sunhaiyong's LiveCD" ${SYSTEM}/cdrom/LABEL ; then
break;
fi
fi
umount ${SYSTEM}/cdrom
fi
fi
done

# 加载squashfs压缩的主文件系统
mount -o loop -t squashfs ${SYSTEM}/cdrom/SYSTEM ${SYSTEM}/system
ln -s /system/bin ${SYSTEM}
ln -s /system/sbin ${SYSTEM}
ln -s /system/lib ${SYSTEM}
ln -s /system/usr ${SYSTEM}

# 将根目录从initrd转换到主系统
killall /sbin/udevd
echo 0x0100 > /proc/sys/kernel/real-root-dev
pivot_root ${SYSTEM} ${SYSTEM}/initrd
cd /

# 解压缩一些必要的目录和文件
tar xf /cdrom/etc.tar.bz2 -C /

#转移内核文件系统
mount --move /initrd/dev /dev
mount --move /initrd/proc /proc
mount --move /initrd/sys /sys
mkdir -p /var/{run,log,lock}
touch /var/run/utmp /var/log/{btmp,lastlog,wtmp}
chgrp utmp /var/run/utmp /var/log/lastlog
chmod 664 /var/run/utmp /var/log/lastlog

#结束
EOF

现在根据linuxrc用到的命令复制到initrd中
代码:
cp -a /bin/{bash,bunzip,bzcat,bzip2,killall,chmod,cp,grep,mount,tar,ln,cat,mkdir} ${INITRD}/bin
cp -a /usr/bin/basename ${INITRD}/bin
cp -a /sbin/pivot_root ${INITRD}/sbin
cp -a /sbin/{udevd,udevsettle,udevtrigger,modprobe} ${INITRD}/sbin
复制这些命令所需要的各种动态链接库,可通过ldd命令查看。
代码:
cp -a /lib/ld-* ${INITRD}/lib/
cp -a /lib/libc-2.5.1.so ${INITRD}/lib/
cp -a /lib/libc.so.6 ${INITRD}/lib/
cp -a /lib/lib{dl,pthread,rt}-* ${INITRD}/lib/
cp -a /lib/lib{readline,history,ncursesw,dl,bz2,blkid,uuid,rt,pthread}.so* ${INITRD}/lib/

创建一些必要的文件
代码:
touch ${INITRD}/etc/fstab
创建LiveCD标签
代码:
echo "Sunhaiyong's LiveCD" > /opt/iso/LABEL
卸载initrd,并将其压缩
代码:
cd /opt/iso/boot
umount initrd
gzip -9 initrd.img

建立etc.tar.bz2文件
代码:
cd /opt/iso
cp -a /etc ./
可以对etc目录进行特定的修改,然后打包压缩
代码:
tar -cjf etc.tar.bz2 etc
rm -r etc

创建grub及启动选择
代码:
cd /opt/iso
mkdir -p boot/grub
cp -a /usr/lib/grub/i386-pc/stage2_eltorito boot/grub
创建menu.lst
代码:
cd /opt/iso/boot/grub
cat > menu.lst << "EOF"
default 0
timeout 3
color green/black light-green/black
title MyLiveCD 1.0
root (cd)
kernel /boot/kernel
initrd /boot/initrd.img.gz


生成iso文件
代码:
cd /opt
mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot -boot-load-size 4 -boot-info-table -o mylivecd.iso iso

好了,现在在/opt目录下将出现一个mylivecd.iso文件,将这个文件刻录到光盘上,就可以用来引导一台x86的机器了。

注意:
  如果需要刻录光盘,建议您先用虚拟机来测试一下这个iso文件是否工作正常,避免不必要的浪费。:-)

将这个自己制作的LiveCD光盘插入光驱,很快系统就会完成整个LiveCD的引导过程进入Login状态。

本文到现在为止只是完成了一个LiveCD的基本功能,用户可以根据自己的需求增加各种功能,这些都可以在主系统的后续引导过程中增加。

(转载请保持文章的完整性,请注明作者和出处)
作者:孙海勇(冲天飞豹)
Email:youbest@sina.com
2008年2月12日


以上就是整个LiveCD的制作过程,引导完成后的样子如下:



更新日志:
2008年2月12日:本文发布。
类别:Tutorials | 评论(1) | 浏览()
 
2005-12-19 11:02
Step By Step制作软盘上的Linux(V0.04)
By    : 吴垠
Email : lazy_fox#msn.com
Date   : 2006.02.16
Link   : http://blog.csdn.net/wooin/archive/2006/01/16/580922.aspx

写在前面:
    本文的目的是为了不管一切理论和不择一切手段在软盘上做一个Linux系统起来先,
不管"为什么", 只告诉你"怎么做", 制作成功后你自己去研究"为什么", 这样你的兴趣就会
大很多了^_^, 免得整半天整不出来, 又半途而废了(我经常这样:( .......).
    这个东西是我用了大概一周的业余时间琢磨出来的(半途而废了好几次), 期间参考了
岳光的<如何制作软盘Linux>, 该文章在我的blog上也可以找到:
    http://blog.csdn.net/wooin/articles/580666.aspx
    在此谢谢岳光(好美的名字^_^), 转载时请注意他人的版权信息
    本文其实不长, 长的是后面的附录, 附录都是本文需要用到的文件, 将其分别复制粘
贴成几个文件就行了, 在下面的文章中有介绍.
    最后, 本人也是Linux初学者, 文章中的不足之处还请大家不吝赐教, 多提意见, 谢谢!
    版权信息:该文章版权由Wu Yin所有. 可在非商业目的下任意传播和复制. 对于商业
目的下对本文的任何行为需经作者同意. 联系方式:lazy_fox#msn.com

01. 我用到的软件:
    操作系统    : Redhat Linux 9 (2.4.20-8)
    软盘上的内核 : linux-2.4.20.tar.bz2
                这个内核是用来编译后放到软盘上的内核
    buzybox       : busybox-1.01.tar.gz
                提供一些常用的shell命令
02. 将一张空白软盘插入到软驱中, 将其格式化为ext2的空盘. 并创建boot boot/grub目录:
    $ umount /mnt/floppy
    $ mke2fs /dev/fd0
    $ mount /dev/fd0 /mnt/floppy/
    $ cd /mnt/floppy/
    $ mkdir boot boot/grub
03. 拷贝/boot/grub/stage1和stage2到软盘的boot/grub下:
    $ cp /boot/grub/stage1 /mnt/floppy/boot/grub
    $ cp /boot/grub/stage2 /mnt/floppy/boot/grub
04. 在软盘上配置grub:
    $ grub
    $ root (fd0)
    $ setup (fd0)
    $ quit
    至此grub安装成功!
05. 建立一个工作目录mk_flp_linux
    在该目录下建立三个文件: inittab , rc.S 和 grub.conf
    文件内容见本文后面的附录
    修改两个文件的属性
    $ chmod 777 inittab rc.S
06. 配置busybox
    将busybox-1.01.tar.gz拷贝到我们的工作目录mk_flp_linux下, 解压, 改名, 配置, 编译
    $ tar -xzvf busybox-1.01.tar.gz    #解压
    $ mv busybox-1.01 busybox        #改名
    $ cd busybox
    $ make menuconfig                #配置
    $ make                        #编译
    这里要注意的是, 在配置busybox的时候要考虑软盘的大小, 编译出来的文件要尽量小,
    要给内核文件留空间, 并且要编译成静态的. 配置完后会生成一个".config"文件,
    我的".config"文件见附录4, 请用文本比较软件比如kompare与你的文件进行比较查看
07. 编写mk_flp_linux脚本, 并修改文件属性, 文件内容见附录5
    $ chmod 777 mk_flp_linux
    现在可以执行mk_flp_linux脚本了
    $ ./mk_flp_linux
    注意 1: 该脚本有一处需要按照你的系统进行必要的修改, 在mknod时设备号都是安装我
    的机器上进行设置的, 你需要按照你自己机器上的内容进行相应修改
    注意 2: 该脚本还在调试中, 如果无法运行请打开该脚本, 其中有详细的注释, 可以按照
    步骤一步一步的在你的电脑上执行
08. 最后进行内核配置, 这是我认为最麻烦的地方, 想让编译出来的内核尽量小, 但又要是
    个功能齐全可以启动的内核.
    解压tarball:
    $ tar -xjvf linux-2.4.20.tar.bz2
    配置内核:
    $ make menuconfig
    编译内核:
    $ make bzImage
    编译出来的内核文件是: linux/arch/i386/boot/bzImage
    我的Linux-2.4.20的.config文件见附录6, 请用文本比较软件比如kompare与你的文件进行比较查看
    /*将其复制到内核文件夹的根文件夹下, 覆盖原文件*/ 该方法好像不行
*09. 复制bzImage文件到软盘上
*10. 用软盘重启, 进入你的软盘linux系统吧.....! 到此为止我们已经制作好了软盘上的Linux系统,
    下面对前面的操作进行一下说明
11. 总结目录情况
    $ ls -lh /mnt/floppy/
    总用量 1.3M
    drwxr-xr-x    3 root     root    1.0K        1月 12 17:34 boot
    -rw-r--r--    1 root     root    966K    1月 20 14:56 bzImage
    -rw-r--r--    1 root     root    310K    1月 20 14:55 image.gz
   
    文件介绍:
    boot:    这是个文件夹, 是在02, 03, 04步中建立的, 里面是grub用来启动电脑的文件
    bzImage: 这个不用介绍了吧, 是编译好的Linux内核的压缩版, 是在08步产生的
    image.gz: 这个是Linux系统需要用到的文件系统镜像, 是在05, 06, 07步中完成的
            其中包括了启动脚本, 设备节点, shell命令等...
    另外, 有可能还会有一个lost+found文件夹, 但是已经被我删除了, 是在第02步中的
    "mke2fs /dev/fd0"产生的, 此文件夹没有什么用处
*12. 比较粗糙, 还可以优化

=========================================================================
附录1: inittab文件内容
=========================================================================
::sysinit:/etc/rc.S
::askfirst:/bin/sh

=========================================================================
附录2: rc.S文件内容
=========================================================================
#!/bin/sh
mount -t proc /proc /proc

=========================================================================
附录3: grub.conf文件内容
=========================================================================
default=0
timeout=10
title Linux On Floppy
    root (fd0)
    kernel /bzImage
    initrd /image.gz

=========================================================================
附录4: busybox 的.config文件
这个文件有可能不能直接使用, 仅供参考
=========================================================================
#
# Automatically generated make config: don't edit
#
HAVE_DOT_CONFIG=y

#
# General Configuration
#
# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set
CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y
# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
CONFIG_FEATURE_VERBOSE_USAGE=y
# CONFIG_FEATURE_INSTALLER is not set
# CONFIG_LOCALE_SUPPORT is not set
# CONFIG_FEATURE_DEVFS is not set
CONFIG_FEATURE_DEVPTS=y
# CONFIG_FEATURE_CLEAN_UP is not set
CONFIG_FEATURE_SUID=y
# CONFIG_FEATURE_SUID_CONFIG is not set
# CONFIG_SELINUX is not set

#
# Build Options
#
CONFIG_STATIC=y
# CONFIG_LFS is not set
# USING_CROSS_COMPILER is not set
EXTRA_CFLAGS_OPTIONS=""

#
# Installation Options
#
# CONFIG_INSTALL_NO_USR is not set
PREFIX="./_install"

#
# Archival Utilities
#
# CONFIG_AR is not set
CONFIG_BUNZIP2=y
# CONFIG_CPIO is not set
# CONFIG_DPKG is not set
# CONFIG_DPKG_DEB is not set
CONFIG_GUNZIP=y
# CONFIG_FEATURE_GUNZIP_UNCOMPRESS is not set
CONFIG_GZIP=y
# CONFIG_RPM2CPIO is not set
# CONFIG_RPM is not set
CONFIG_TAR=y
CONFIG_FEATURE_TAR_CREATE=y
CONFIG_FEATURE_TAR_BZIP2=y
CONFIG_FEATURE_TAR_FROM=y
CONFIG_FEATURE_TAR_GZIP=y
# CONFIG_FEATURE_TAR_COMPRESS is not set
CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY=y
CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
# CONFIG_UNCOMPRESS is not set
# CONFIG_UNZIP is not set

#
# Common options for cpio and tar
#
# CONFIG_FEATURE_UNARCHIVE_TAPE is not set

#
# Coreutils
#
CONFIG_BASENAME=y
# CONFIG_CAL is not set
CONFIG_CAT=y
CONFIG_CHGRP=y
CONFIG_CHMOD=y
CONFIG_CHOWN=y
CONFIG_CHROOT=y
# CONFIG_CMP is not set
CONFIG_CP=y
CONFIG_CUT=y
CONFIG_DATE=y
CONFIG_FEATURE_DATE_ISOFMT=y
CONFIG_DD=y
CONFIG_DF=y
CONFIG_DIRNAME=y
# CONFIG_DOS2UNIX is not set
CONFIG_DU=y
CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K=y
CONFIG_ECHO=y
CONFIG_FEATURE_FANCY_ECHO=y
CONFIG_ENV=y
# CONFIG_EXPR is not set
# CONFIG_FALSE is not set
# CONFIG_FOLD is not set
# CONFIG_HEAD is not set
# CONFIG_HOSTID is not set
# CONFIG_ID is not set
# CONFIG_INSTALL is not set
# CONFIG_LENGTH is not set
# CONFIG_LN is not set
# CONFIG_LOGNAME is not set
CONFIG_LS=y
CONFIG_FEATURE_LS_FILETYPES=y
CONFIG_FEATURE_LS_FOLLOWLINKS=y
CONFIG_FEATURE_LS_RECURSIVE=y
CONFIG_FEATURE_LS_SORTFILES=y
CONFIG_FEATURE_LS_TIMESTAMPS=y
CONFIG_FEATURE_LS_USERNAME=y
CONFIG_FEATURE_LS_COLOR=y
# CONFIG_MD5SUM is not set
CONFIG_MKDIR=y
# CONFIG_MKFIFO is not set
CONFIG_MKNOD=y
CONFIG_MV=y
# CONFIG_OD is not set
# CONFIG_PRINTF is not set
CONFIG_PWD=y
# CONFIG_REALPATH is not set
CONFIG_RM=y
# CONFIG_RMDIR is not set
# CONFIG_SEQ is not set
# CONFIG_SHA1SUM is not set
# CONFIG_SLEEP is not set
# CONFIG_SORT is not set
# CONFIG_STTY is not set
# CONFIG_SYNC is not set
# CONFIG_TAIL is not set
# CONFIG_TEE is not set
CONFIG_TEST=y

#
# test (forced enabled for use with shell)
#
# CONFIG_FEATURE_TEST_64 is not set
# CONFIG_TOUCH is not set
# CONFIG_TR is not set
# CONFIG_TRUE is not set
# CONFIG_TTY is not set
CONFIG_UNAME=y
# CONFIG_UNIQ is not set
# CONFIG_USLEEP is not set
# CONFIG_UUDECODE is not set
# CONFIG_UUENCODE is not set
# CONFIG_WATCH is not set
# CONFIG_WC is not set
# CONFIG_WHO is not set
# CONFIG_WHOAMI is not set
# CONFIG_YES is not set

#
# Common options for cp and mv
#
CONFIG_FEATURE_PRESERVE_HARDLINKS=y

#
# Common options for ls and more
#
CONFIG_FEATURE_AUTOWIDTH=y

#
# Common options for df, du, ls
#
CONFIG_FEATURE_HUMAN_READABLE=y

#
# Console Utilities
#
CONFIG_CHVT=y
CONFIG_CLEAR=y
# CONFIG_DEALLOCVT is not set
# CONFIG_DUMPKMAP is not set
# CONFIG_LOADFONT is not set
# CONFIG_LOADKMAP is not set
# CONFIG_OPENVT is not set
# CONFIG_RESET is not set
# CONFIG_SETKEYCODES is not set

#
# Debian Utilities
#
# CONFIG_MKTEMP is not set
# CONFIG_PIPE_PROGRESS is not set
# CONFIG_READLINK is not set
# CONFIG_RUN_PARTS is not set
# CONFIG_START_STOP_DAEMON is not set
# CONFIG_WHICH is not set

#
# Editors
#
# CONFIG_AWK is not set
# CONFIG_PATCH is not set
# CONFIG_SED is not set
CONFIG_VI=y
CONFIG_FEATURE_VI_COLON=y
CONFIG_FEATURE_VI_YANKMARK=y
CONFIG_FEATURE_VI_SEARCH=y
CONFIG_FEATURE_VI_USE_SIGNALS=y
CONFIG_FEATURE_VI_DOT_CMD=y
CONFIG_FEATURE_VI_READONLY=y
CONFIG_FEATURE_VI_SETOPTS=y
CONFIG_FEATURE_VI_SET=y
CONFIG_FEATURE_VI_WIN_RESIZE=y
CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y

#
# Finding Utilities
#
# CONFIG_FIND is not set
# CONFIG_GREP is not set
# CONFIG_XARGS is not set

#
# Init Utilities
#
CONFIG_INIT=y
CONFIG_FEATURE_USE_INITTAB=y
CONFIG_FEATURE_INITRD=y
# CONFIG_FEATURE_INIT_COREDUMPS is not set
CONFIG_FEATURE_INIT_SWAPON=y
CONFIG_FEATURE_EXTRA_QUIET=y
CONFIG_HALT=y
CONFIG_POWEROFF=y
CONFIG_REBOOT=y
# CONFIG_MESG is not set

#
# Login/Password Management Utilities
#
# CONFIG_USE_BB_PWD_GRP is not set
# CONFIG_ADDGROUP is not set
# CONFIG_DELGROUP is not set
# CONFIG_ADDUSER is not set
# CONFIG_DELUSER is not set
# CONFIG_GETTY is not set
# CONFIG_LOGIN is not set
# CONFIG_PASSWD is not set
# CONFIG_SU is not set
# CONFIG_SULOGIN is not set
# CONFIG_VLOCK is not set

#
# Miscellaneous Utilities
#
CONFIG_ADJTIMEX=y
# CONFIG_CROND is not set
# CONFIG_CRONTAB is not set
# CONFIG_DC is not set
# CONFIG_DEVFSD is not set
# CONFIG_LAST is not set
# CONFIG_HDPARM is not set
# CONFIG_MAKEDEVS is not set
# CONFIG_MT is not set
# CONFIG_RX is not set
# CONFIG_STRINGS is not set
# CONFIG_TIME is not set
# CONFIG_WATCHDOG is not set

#
# Linux Module Utilities
#
# CONFIG_INSMOD is not set
# CONFIG_LSMOD is not set
# CONFIG_MODPROBE is not set
# CONFIG_RMMOD is not set

#
# Networking Utilities
#
# CONFIG_FEATURE_IPV6 is not set
# CONFIG_ARPING is not set
# CONFIG_FTPGET is not set
# CONFIG_FTPPUT is not set
# CONFIG_HOSTNAME is not set
# CONFIG_HTTPD is not set
# CONFIG_IFCONFIG is not set
# CONFIG_IFUPDOWN is not set
# CONFIG_INETD is not set
# CONFIG_IP is not set
# CONFIG_IPCALC is not set
# CONFIG_IPADDR is not set
# CONFIG_IPLINK is not set
# CONFIG_IPROUTE is not set
# CONFIG_IPTUNNEL is not set
# CONFIG_NAMEIF is not set
# CONFIG_NC is not set
# CONFIG_NETSTAT is not set
# CONFIG_NSLOOKUP is not set
# CONFIG_PING is not set
# CONFIG_ROUTE is not set
# CONFIG_TELNET is not set
# CONFIG_TELNETD is not set
# CONFIG_TFTP is not set
# CONFIG_TRACEROUTE is not set
# CONFIG_VCONFIG is not set
# CONFIG_WGET is not set

#
# udhcp Server/Client
#
# CONFIG_UDHCPD is not set
# CONFIG_UDHCPC is not set

#
# Process Utilities
#
# CONFIG_FREE is not set
# CONFIG_KILL is not set
# CONFIG_PIDOF is not set
# CONFIG_PS is not set
# CONFIG_RENICE is not set
# CONFIG_TOP is not set
# CONFIG_UPTIME is not set
# CONFIG_SYSCTL is not set

#
# Another Bourne-like Shell
#
CONFIG_FEATURE_SH_IS_ASH=y
# CONFIG_FEATURE_SH_IS_HUSH is not set
# CONFIG_FEATURE_SH_IS_LASH is not set
# CONFIG_FEATURE_SH_IS_MSH is not set
# CONFIG_FEATURE_SH_IS_NONE is not set
CONFIG_ASH=y

#
# Ash Shell Options
#
# CONFIG_ASH_JOB_CONTROL is not set
# CONFIG_ASH_ALIAS is not set
# CONFIG_ASH_MATH_SUPPORT is not set
# CONFIG_ASH_GETOPTS is not set
# CONFIG_ASH_CMDCMD is not set
# CONFIG_ASH_MAIL is not set
# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
# CONFIG_ASH_RANDOM_SUPPORT is not set
# CONFIG_HUSH is not set
# CONFIG_LASH is not set
# CONFIG_MSH is not set

#
# Bourne Shell Options
#
# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
# CONFIG_FEATURE_SH_STANDALONE_SHELL is not set
# CONFIG_FEATURE_COMMAND_EDITING is not set

#
# System Logging Utilities
#
# CONFIG_SYSLOGD is not set
# CONFIG_LOGGER is not set

#
# Linux System Utilities
#
# CONFIG_DMESG is not set
# CONFIG_FBSET is not set
# CONFIG_FDFLUSH is not set
# CONFIG_FDFORMAT is not set
# CONFIG_FDISK is not set
# CONFIG_FREERAMDISK is not set
# CONFIG_FSCK_MINIX is not set
# CONFIG_MKFS_MINIX is not set
# CONFIG_GETOPT is not set
# CONFIG_HEXDUMP is not set
# CONFIG_HWCLOCK is not set
# CONFIG_LOSETUP is not set
# CONFIG_MKSWAP is not set
# CONFIG_MORE is not set
# CONFIG_PIVOT_ROOT is not set
# CONFIG_RDATE is not set
# CONFIG_SWAPONOFF is not set
CONFIG_MOUNT=y
# CONFIG_NFSMOUNT is not set
CONFIG_UMOUNT=y
# CONFIG_FEATURE_MOUNT_FORCE is not set

#
# Common options for mount/umount
#
CONFIG_FEATURE_MOUNT_LOOP=y
# CONFIG_FEATURE_MTAB_SUPPORT is not set

#
# Debugging Options
#
# CONFIG_DEBUG is not set

=========================================================================
附录5: mk_flp_linux脚本文件
=========================================================================
#!/bin/sh
##############################################
#下面的操作需要在软驱中有一张已经配置好grub的软盘
##############################################
mount /dev/fd0 /mnt/floppy/

#取得该shell脚本所在路径, 注意是^dirname $0^ 不是 'dirname $0'
WORK_PATH=`dirname $0`
cp $WORK_PATH/grub.conf /mnt/floppy/boot/grub

#清除上次制作时可能残留的痕迹, 如果是第一次制作, 则不会有
rm -rvf /tmp/floppy
rm -rvf /tmp/image
rm -rvf /tmp/image.gz
mkdir /tmp/floppy

#要想下面的脚本正常运行, 首先要配置好busybox, 请按照下面的方法配置
#下载busybox-1.01.tar.gz, 你也可以下载其他版本的, 这里我用的是1.01版
#将其解压到本脚本所在的目录, 并将文件夹名去掉版本号, 改为busybox
#进入busybox目录, 运行make menuconfig, make 配置
#编译好后才能继续下面的操作
cd $WORK_PATH/busybox
make PREFIX=/tmp/floppy install

cd /tmp/floppy
mkdir proc mnt etc dev
#该脚本目录下有两个已经写好的文件inittab, rc.S
cp $WORK_PATH/inittab /tmp/floppy/etc
cp $WORK_PATH/rc.S /tmp/floppy/etc

cd /tmp/floppy/dev
mknod hdc b 22 0
mknod hdc1 b 22 1
mknod hdc2 b 22 2
mknod hdc3 b 22 3
mknod hdc4 b 22 4
mknod hdc5 b 22 5
mknod hdc6 b 22 6

mknod console c 5 1
mknod tty c 5 0
mknod tty0 c 4 0
mknod tty1 c 4 1
mknod tty2 c 4 2
mknod tty3 c 4 3
mknod tty4 c 4 4
mknod tty5 c 4 5
mknod tty6 c 4 6
mknod tty7 c 4 7
mknod tty8 c 4 8
mknod tty9 c 4 9
mknod kmem c 1 2
mknod mem c 1 1
mknod null c 1 3
mknod ram b 1 1
mknod fd0 b 2 0
mknod loop0 b 7 0

#下面的代码会用到/mnt/cdrom目录, 请确保该目录没有挂载光驱, 可以被挂载
cd /tmp
dd if=/dev/zero of=image bs=1k count=2048
losetup /dev/loop0 image
mke2fs -m 0 /dev/loop0
mount -t ext2 /dev/loop0 /mnt/cdrom
cp -R floppy/* /mnt/cdrom
umount /mnt/cdrom
losetup -d /dev/loop0
sync
dd if=image|gzip -9>image.gz
cp image.gz /mnt/floppy/
#以后可以这样查看image.gz中的内容(注意:gzip命令会删除原image.gz文件, 请先做好备份):
#gzip -d image.gz
#mount -o loop image /mnt
#然后查看/mnt目录

umount /mnt/floppy/
类别:Tutorials | 评论(4) | 浏览()
 
2005-10-08 09:28
模式:命令模式,编辑模式,末行模式。
切换方式:命令模式→i→编辑模式,编辑模式→Esc→命令模式,命令模式→:→末行模式。
功能:
命令模式(Command Mode): 控制光标移动,删除字符,段落复制。

编辑模式(Insert Mode): 新增文字及修改文字。

末行模式(Last Line Mode):保存文件,离开vi,以及其他设置。


命令模式命令
命令 说明

h 将光标向左移动一格

l 将光标向右移动一格

j 将光标向下移动一格

k 将光标向上移动一格

0 数字0,将光标移动到该行的行首

$ 将光标移动到该行的行末

H 将光标移动到该屏幕的顶端

M 将光标移动到该屏幕的中间

L 将光标移动到该屏幕的底端

gg 将光标移动到文章的首行

G 将光标移动到文章的尾行

w或W 将光标移动到下一单词

x 删除光标所在处的字符

X 删除光标前的字符

dd 删除光标所在行

*dd 从光标所在行向下删除*行,*为数字

D 删除光标所在处到行尾

r 取代光标处的一个字符

R 从光标处向后替换,按Esc结束

u 取消上步的操作

U 取消目前的所有操作

yy 复制光标所在行

p 将复制的内容放在光标所在行的下行

编辑模式命令
命令 说明

a 在光标后插入文本

A 在光标所在行后插入文本

i 在光标前插入文本

I 在光标所在行前插入文本

o 在光标所在行下插入新行(小写字母o)

O 在光标所在行上插入新行(大写字母O)


末行命令
命令 说明

e 创建新文件

n 加载新文件

w 保存文件

! 强行操作(在其后可输入系统命令)

w! 强行保存文件

q 退出

q! 强行退出

wq 保存退出

wq! 强行保存退出

set nu 显示行号

set nonu 不显示行号

/* /搜索,*任意字符串(在命令模式下n为向下搜索N为向上搜索)

set ic 搜索时忽略大小写

set noic .....区分......

? 同上

x保存退出 X加密保存退出(在新版本中有可能不支持了)
类别:Tutorials | 评论(17) | 浏览()
 
2005-06-11 11:34
本系的 BBS 系统真是多灾多难 (嗯 .... 其实是因为我的疏忽,才会这么多灾多难 ....) ,继这几日系统时间不正确,造成许多人的 ID 被误砍后,又一次因系统设定上的问题,将 BBS 的重要备份档给杀了。这件事是学弟发现后告诉我的,当我上站来一见到他的 mail, 当真是欲哭无泪,差点没去撞墙。

那时已是周六晚 11:00 左右,我一边想着要编一套说辞向大家解释无法替大家进行数据恢复旧信件与设定了,一边还在想是否能够挽回局面。大家知道, UNIX like 的系统是很难像 M$ 的系统一样,做到 undelete 的,所有网管前辈都曾再三警告我们,要小心! 小心! 砍档之前三思而后行,砍了之后再后悔也没用。虽然我已渐渐做到砍档三思而后行,但之次误砍事件是系统在背景中定时执行的,等到我找出原因时已是数据被砍后一个多小时。我凭着一点点的印象,想起在网络上,有人讨论过在 Linux ext2 filesystem中 undelete 的可能性,但我所见到的多半是负面的答案,但好象真的有人做过这件事,于是我第一个所做的,就是马上将该数据原来所在的 partition mount成 read-only, 禁止任何的写入动作,不是怕再有数据被误砍 (因为已没什么可砍的了) ,而是怕有新数据写进来,新资料可能会覆盖到旧资料原本存在的磁区 (block) 。我们现在唯一个指望,就是企图将数据原来存在的磁区一个个找回来,并且「希望」这些磁区上的旧资料都还在,然后将这些磁区串成一个数据。终于被我找到了!! 原来这方面的技术文件就存在我自己的系统中 :-))

/usr/doc/HOWTO/mini/Ext2fs-Undeletion.gz



于是我就按照这份文件的指示一步步来,总算将一个长达 8MB 的压缩档数据恢复了 99%, 还有一个长达 1.1 MB 的压缩档完整无缺地救了回来。感谢上帝、 Linux 的设计者、写那篇文件的作者、曾经讨论过此技术的人、以及 Linux 如此优秀的 ext2 filesystem, 让我有机会抢救过去。现在,我将我的抢救步骤做一个整理让大家参考,希望有派得上用场的时候 (喔! 不,最好是希望大家永远不要有机会用到以下的步数 :-)))

在此严正声明!! 写这篇文章的目的,是给那些处于万不得已情况下的人们,有一个挽回的机会,并不意味着从此我们就可以大意,砍档不需要三思。前面提到,我有一个数据无法 100% 救回,事实上,长达 8MB 的数据能救回 99% 已是幸运中的幸运,一般的情况下若能救回 70% - 80% 已经要愉笑了。所以,不要指望 undelete 能救回一切。预防胜于治疗! 请大家平时就养成好习惯,砍档前请三思!!!

理论分析

我们能救回的机会有多大? 在 kernel-2.0.X 系列中 (本站所用的 kernel 是 2.0.33) ,取决以下两点:

数据原来所在的磁区是否没有被覆写?

数据是否完全连续?

第一点我们可以与时间竞赛数据恢复,就是当一发现数据误砍时,要以最快的速度 umount 该 filesystem, 或将该 filesystem remount 成唯读。就这次的情况而言,数据误砍是在事发一个小时后才发现的,但由于该 filesystem 写入的机会很少 (我几乎可确定一天才只有一次,做 backup),所以第一点算是过关了。

第二点真的是数据恢复要听天由命了,就本站所使用的 kernel, 必须要在假设「长数据」所占的 block 完全连续的情况下,才有可能完全救回来! 一个 block 是 1024 bytes,长达 8 MB 的数据就有超过 8000 个 block。在经常读写的 filesystem 中,可以想见长数据很难完全连续,但在我们的系统中,这一点似乎又多了几分指望。同时,Linux ext2 如此精良的 filesystem, 能做到前 7950 多个 block 都连续,这一点也功不可没。

好了,以下我就讲一下我的步骤。
数据恢复,抢救步骤 I - mount filesystem readonly

该数据的位置原来是在 /var/hda/backup/home/bbs 下,我们系统的 filesystem 组态是:

root@bbs:/home/ftp/rescue# df
Filesystem 1024-blocks Used Available Capacity Mounted on
/dev/sda1 396500 312769 63250 83% /
/dev/sda3 777410 537633 199615 73% /home
/dev/hda1 199047 36927 151840 20% /var/hda
/dev/hda2 1029023 490998 485710 50% /home/ftp



因此 /var/hda 这个 filesystem 要马上 mount 成 readonly (以下请用 root 身份):

mount -o remount,ro /var/hda



当然也可以直接 umount 它,但有时候可能有某些 process 正在此 filesystem下运作,您可能无法直接 umount 它。因此我选择 mount readonly。但您也可以用:

fuser -v -m /usr



看一下目前是那些 process 在用这个 filesystem, 然后一一砍掉,再 umount。
数据恢复,抢救步骤 II

执行

echo lsdel | debugfs /dev/hda1 | less



看一下该 filesystem 最近被砍的 inode (数据) 有那些 (为什么是 /dev/hda1? 请见上头的 df 列表)? 在这奶F数据的重要资讯,如大小、时间、属性等等。就我们的系统而言,其列示如下:

debugfs: 92 deleted inodes found.
Inode Owner Mode Size Blocks Time deleted
....................................................................
29771 0 100644 1255337 14/14 Sat Jan 30 22:37:10 1999
29772 0 100644 5161017 14/14 Sat Jan 30 22:37:10 1999
29773 0 100644 8220922 14/14 Sat Jan 30 22:37:10 1999
29774 0 100644 5431 6/6 Sat Jan 30 22:37:10 1999



请注意!我们必须要在数据大小、被砍时间等资讯中判断出要救回的数据是那一个。在此,我们要救回 29773 这个 inode。
数据恢复,抢救步骤 III

执行

echo "stat <29773>" | debugfs /dev/hda1



列出该 inode 的所有资讯,如下:

debugfs: stat <29773>
Inode: 29773 Type: regular Mode: 0644 Flags: 0x0 Version: 1
User: 0 Group: 0 Size: 8220922
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 16124
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x36b31916 -- Sat Jan 30 22:37:10 1999
atime: 0x36aebee4 -- Wed Jan 27 15:23:16 1999
mtime: 0x36adec25 -- Wed Jan 27 00:24:05 1999
dtime: 0x36b31916 -- Sat Jan 30 22:37:10 1999
BLOCKS:
123134 123136 123137 123138 123140 131404 131405 131406
131407 131408 131409 131 410 131411 131668
TOTAL: 14



现在的重点是,数据恢复必须将该 inode 所指的数据,所指的 block 全部找回来。在这它?14 个 block? 不对啊! 应该要有 8000 多个 block 才对啊! 在这卯ilesystem 的「奥密」了。上头所列的前 12 个 block 是真正指到数据资料的 block, 称之为 direct block 。第 13 个称为第一阶 indirect block, 第 14 个称为第二阶 indirect block 。什么意思? 该档的资料所在的 block 位置如下:

各位明白吗? 第 13 个 (131411) 与第 14 个 block 其实不是 data, 而是 index,它指出接下来的 block 的位置。由于一个 block 的大小是 1024 bytes, 一个 int 在 32 位系统中是 4 bytes, 故一个 block 可以记录 256 笔资料。以 131411 block 为例,它所记录的资料即为 (在数据未砍前):

131412 131413 131414 .... 131667 (共 256 笔)



而这 256 个 block 就真正记录了数据资料,所以我们称为第一阶。同理,第二阶就有两个层 index, 以 131668 来说,它可能记录了:

131669 131926 132182 .... (最多有 256 笔)



而 131669 的 block 记录为:

131670 131671 131672 .... 131925 (共 256 笔)



而这 256 个 block 才是真正储存数据资料的。而我们要的,就是这些真正储存数据资料的 block 。 理论上,我们只要将这些 index block 的内容全部读出来,然后照这些 index 把所有的 block 全部读到手,就能 100% 数据恢复 (假设这些 block 全部没有被新数据覆写的话)。工程很大,但是可行。不幸的是,在 kernel-2.0.33, 其设计是,如果该数据被砍了,则这些 index block 全部会规零,因此我所读到的是

0 0 0 0 0 ..... (共 256 笔)



哇! 没办法知道这些 data block 真正所在的位置。所以,在此我们做了一个很大的假设: 整个数据所在的 block 是连续的! 也就是我上头的例子。这也就是为什么说,只有连续 block (是指后头的 indirect block) 的数据才能完整救回,而这一点就要听天由命了。
数据恢复,抢救步骤 IV

好了,现在我们只好假设所有的数据处于连续的 block 上,现在请用archie.ncu.edu.tw去找这个工具: fsgrab-1.2.tar.gz, 并将它安装起来。因为步骤很简单,故在此我就不多谈。我们要用它将所需的 block 全部抓出来。它的用法如下:

fsgrab -c count -s skip device



其中 count 是只要 (连续) 读几个, skip 是指要从第几个开始读,例如我要从 131670 开始连续读 256 个,就这样下指令:

fsgrab -c 256 -s 131670 /dev/hda1 > recover



现在我们就开始救数据吧! 以上头的资料,我们必须用以下的指令来救: (注意到头开的 12 个 block 并没有完全连续!!!)

fsgrab -c 1 -s 123134 /dev/hda1 > recover
fsgrab -c 3 -s 123136 /dev/hda1 >> recover
fsgrab -c 1 -s 123140 /dev/hda1 >> recover
fsgrab -c 7 -s 131404 /dev/hda1 >> recover



这是开头的 12 个 block, 对于第一阶 indirect, 就资料来看好象是连续的 :-))

fsgrab -c 256 -s 131412 /dev/hda1 >> recover



注意要跳过 131411, 因为它是 index block。对于第二阶 indirect, 我们 *假设* 它们都是连续的:

fsgrab -c 256 -s 131670 /dev/hda1 >> recover
fsgrab -c 256 -s 131927 /dev/hda1 >> recover
fsgrab -c 256 -s 132184 /dev/hda1 >> recover
............................................



要一直做,直到 recover 的大小超过我们所要救回的数据大小 (8220922) 为止。要注意在这市 p心地跳过那些 index block (如 131668, 131669, 131926, 132183, ....) 了。
数据恢复,抢救步骤 V

最后一步,就是把数据「剪」出来,并看看我们救回多少了。在这戊]我们重复上述步骤,弄出来的 recover 档大小为 8294400,而我们要的大小是 8220922, 那就这样下指令:

split -b 8220922 recover rec



则会做出两个档,一个是 recaa, 大小是 8220922, 另一个是 recab 则是剩下的大小,后者是垃圾,扔了即可。现在我们可以检查这个数据是不是「完整」的那个被误砍的数据了。由于我们的那个数据是 .tar.gz 的格式,于是我们这个方法来检查:

mv recaa recaa.tar.gz
zcat recaa.tar.gz > recaa.tar



如果没有错误讯息,那表示成功了! 完全救回来了。但不幸的是,我们没有成功,将弄出的 recaa.tar 改名再 gzip 之后,与原来的 recaa.tar.gz 比一下大小,发现少了 1%, 表示说该档原来所在的 block 中最后有 1% 是不连续的 (或者被新写入的数据覆写了),但这已是不幸中的大幸了。

后记

对于在 undelete 时 *必需* 假设所有 block 连续的问题,那份 HOWTO 文件说 Linus 与其它 kernel 设计者正着手研究,看能否克服这个困难,也就是在数据砍掉时,不要将 index block 规零。我刚刚试一下 kenrel-2.2.0 的环境,发现已做到了!! 以下是一个已砍的数据的 inode data (由 debugfs 所读出):


debugfs: Inode: 36154 Type: regular Mode: 0600 Flags: 0x0 Version: 1
User: 0 Group: 0 Size: 2165945
File ACL: 0 Directory ACL: 0
Links: 0 Blockcount: 4252
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x36b54c3b -- Mon Feb 1 14:39:55 1999
atime: 0x36b54c30 -- Mon Feb 1 14:39:44 1999
mtime: 0x36b54c30 -- Mon Feb 1 14:39:44 1999
dtime: 0x36b54c3b -- Mon Feb 1 14:39:55 1999
BLOCKS:
147740 147741 147742 147743 147744 147745 147746 147747 147748 147769
147770 157642 157643 157644 157645 157646 157647 157648 157649 157650
157651 157652 157653 157654 157655 157656 157657 157658 157659 157660
157661 157662 157663 157664 157665 157666 157667 157668 157669 157670
157671 157672 157673 157674 157675 157676 157677 157678 157679 157680
157681 157682 157683 157684 157685 157686 157687 1...................
.........9745 159746 159747 159748 159749 159750 159751 159752 159753
159754 159755 159756
TOTAL: 2126



真是太完美了!! 这意味着在 kernel-2.2.X 的环境下,我们不必假设所有的 block 都连续,而且可以百分之百找回所有砍掉的 block! 因此上述的第二个风险就不存在了。
类别:Tutorials | 评论(20) | 浏览()
 
     
 
 
文章分类
 
 
 
Apps(56)
 
Config(35)
 
Shell(47)
 
 
 
 
 
 
Others(17)
 
 
 
Emacs(16)
 
 
 
 
 
 
Games(19)
 
Asm(2)
 
Vim(10)
 
 
 
Hack(6)
 
 
Tip(23)
 
Sql(15)
 
 
Gtk(2)
 
Gentoo(35)
 
 
 
 
 
 
Ad(0)
 
     
 
文章存档
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
     
 
最新文章评论
   

信息要互通有无,谢谢分享
 

长见识啦
 

高手
 

汗...
 
 
     


©2008 Baidu