QQ空间地址

5:25:00 PM 0 Comments

日志版的地址是http://user.qzone.qq.com/×××××××/blog
音乐盒的地址是http://user.qzone.qq.com/×××××××/music
相册的的地址是http://user.qzone.qq.com/×××××××/photo
迷你屋的地址是http://user.qzone.qq.com/×××××××/home
个人档的地址是http://user.qzone.qq.com/×××××××/admin
留言版 msgboard
好友圈interact

Unix sockets vs Internet sockets

2:03:00 PM 0 Comments

There are a few differences that might be of interest, in addition to the
already pointed out difference that if you start out using IP sockets, you
don't have to migrate to them later when you want inter-machine
connectivity:

- UNIX domain sockets use the file system as the address name space. This
means you can use UNIX file permissions to control access to communicate
with them. I.e., you can limit what other processes can connect to the
daemon -- maybe one user can, but the web server can't, or the like.
With IP sockets, the ability to connect to your daemon is exposed off
the current system, so additional steps may have to be taken for
security. On the other hand, you get network transparency. With UNIX
domain sockets, you can actually retrieve the credential of the process
that created the remote socket, and use that for access control also,
which can be quite convenient on multi-user systems.

- IP sockets over localhost are basically looped back network on-the-wire
IP. There is intentionally "no special knowledge" of the fact that the
connection is to the same system, so no effort is made to bypass the
normal IP stack mechanisms for performance reasons. For example,
transmission over TCP will always involve two context switches to get to
the remote socket, as you have to switch through the netisr, which
occurs following the "loopback" of the packet through the synthetic
loopback interface. Likewise, you get all the overhead of ACKs, TCP
flow control, encapsulation/decapsulation, etc. Routing will be
performed in order to decide if the packets go to the localhost.
Large sends will have to be broken down into MTU-size datagrams, which
also adds overhead for large writes. It's really TCP, it just goes over
a loopback interface by virtue of a special address, or discovering that
the address requested is served locally rather than over an ethernet
(etc).

- UNIX domain sockets have explicit knowledge that they're executing on
the same system. They avoid the extra context switch through the
netisr, and a sending thread will write the stream or datagrams directly
into the receiving socket buffer. No checksums are calculated, no
headers are inserted, no routing is performed, etc. Because they have
access to the remote socket buffer, they can also directly provide
feedback to the sender when it is filling, or more importantly,
emptying, rather than having the added overhead of explicit
acknowledgement and window changes. The one piece of functionality that
UNIX domain sockets don't provide that TCP does is out-of-band data. In
practice, this is an issue for almost noone.

In general, the argument for implementing over TCP is that it gives you
location independence and immediate portability -- you can move the client
or the daemon, update an address, and it will "just work". The sockets
layer provides a reasonable abstraction of communications services, so
it's not hard to write an application so that the connection/binding
portion knows about TCP and UNIX domain sockets, and all the rest just
uses the socket it's given. So if you're looking for performance locally,
I think UNIX domain sockets probably best meet your need. Many people
will code to TCP anyway because performance is often less critical, and
the network portability benefit is substantial.

Right now, the UNIX domain socket code is covered by a subsystem lock; I
have a version that used more fine-grain locking, but have not yet
evaluated the performance impact of those changes. I've you're running in
an SMP environment with four processors, it could be that those changes
might positively impact performance, so if you'd like the patches, let me
know. Right now they're on my schedule to start testing, but not on the
path for inclusion in FreeBSD 5.4. The primary benefit of greater
granularity would be if you had many pairs of threads/processes
communicating across processors using UNIX domain sockets, and as a result
there was substantial contention on the UNIX domain socket subsystem lock.
The patches don't increase the cost of normal send/receive operations, but
due add extra mutex operations in the listen/accept/connect/bind paths.

光盘刻录的五种模式

12:25:00 PM 0 Comments

TAO:
  即Track-At-Once,是在一个刻录过程中逐个刻录所有轨道,如果多于一个轨道,则在上一轨道刻录结束后再刻录下一轨道,且上一轨道刻录结束后不关闭区段。
  因为是用这种模式刻录各个轨道,也就是说刻录前一轨道结束后,激光头要关闭,刻录下一轨道时再将其打开。因此,以TAO模式刻录的轨道之间有间隔缝隙。如果是数据轨道和音轨之间,则间隔为2到3秒,如果是音轨之间则间隔为2秒。这一点对于刻录数据光盘没有影响。
  以TAO模式刻录时,可以选择不关闭区段,以后还可以添加轨道到光盘的这一区段,一般用于音乐CD的刻录,而对数据光盘无效。没有关闭区段的音乐CD 不能在CD或VCD播放机上播放,没有关闭的区段可以在刻录软件中进行关闭,关闭后就可以在CD或VCD播放机上播放了。
  以TAO模式刻录时,除选择是否关闭区段与否外还可以选择是否关闭光盘。如果不关闭光盘,以后还可以继续追加刻录下一区段,如果选择关闭光盘,则无论光盘是否还有剩余空间,以后都不能再进行追加刻录,相当于给光盘进行了写保护。

DAO:
  即Disc-At-Once,是在一个刻录过程中在一片光盘中刻入全部数据的模式,无讼有多少轨道都一气呵成。整张光盘可以刻满数据,也可以不刻满。
  DAO模式在刻录录结束时自动关闭光盘,即使还有剩余空间也不能再进行追加刻录。DAO模式在刻录多轨道时,在转换轨道之间不打开和关闭写激光头,可以清除轨道间的2秒间隔,这是与TAO模式的不用之处。

SAO:
  即Session-At-Once,是在一个刻录过程中只刻录一个区段,且关闭区段并保持光盘不关闭,以后还可以继续追加刻录下一区段。

MS:
  即Multi-Session,这是多区段刻录模式。每个刻录过程只刻录并且关闭一个区段,剩余空间下次可以继续刻录下一区段。因此,往往光盘上存在 多个区段,称为多区段光盘。如果光盘中只有一个区段,但光盘没有关闭,也可成为多区段光盘。这种模式多用于数据光盘的刻录,方便之处在于不必一次刻满整 盘。

PW:
  即Packet Writing,CD-RW盘片的刻录模式,是增量包写模式,是以64KB的数据包为写入单位进行写操作,这也就是CD-RW刻录类型所采取的惟一刻录模式。

guest OS

10:58:00 PM 0 Comments

A guest OS is an operating system that is installed in a virtual machine or disk partition in addition to the host or main OS. In virtualization, a single computer can run more than one OS at the same time. In disk partitioning, a guest OS must be the same as the host OS. In a virtualization solution, a guest OS can be different from the host OS.

XP下Qemu模拟器上OpenSolaris的安装

4:25:00 PM 0 Comments

简单地说, Qemu是一款能运行在多种操作系统上的模拟器, 能够模拟各种体系结构环境. 它既能运行各种体系结构下的各种操作系统, 也能直接模拟运行各种体系结构下的可执行文件。

  操作系统平台:Windows XP。

  模拟器:Qemu-0.9.0-windows。

  其他软件:若已经有OpenSolaris可启动(bootable)ISO镜像就OK了;若没有, 则可用免费的OpenSolaris宝典DVD,和ISO镜像制作软件制做一个。这些软件如 WinImage,UltraISO,WinISO,Alcohol,或开源的cdrtools(可在http://smithii.com /cdrtools下载编译好的cdrtools-latest.zip,解压后直接使用)等都可以,笔者用的是WinImage。

  步骤:

  ◆1. 从Qemu官方网站(http://www.h7.dion.ne.jp/~qemu-win/)下载qemu-0.9.0-windows.zip, 解压后就可以用了. 而Kqemu加速之类的自个儿下下来试试就知了。

  这里解压目录为c:/qemu/qemu-0.9.0-windows 。

  ◆2. 把ISO镜像放到Qemu目录(c:qemuqemu-0.9.0-windows)下. 若自己制作, 则只要把DVD中的全部内容做成ISO镜像即可, 无需其他动作, 因为该DVD本身就是可启动的. 不过这里需要注意的扩展名必须是小写的iso, 否则qemu可能不认识. 这里镜像名为solaris.iso。

  ◆3. 用qemu-img.exe制作一个硬盘镜像文件(solaris.img), 大小设为10G, 因为笔者空间太多了.:)

  不过实际上并非如些, 因为虽然该文件逻辑大小为10G, 但在硬盘中实际存储只有4k. solaris.img是Qemu用来安装OpenSolaris的地方, 10G只是它最大能使用的空间, 在硬盘上存储的是真实使用的大小。

  命令如下(注意下面的">"为DOS提示符):

  >cd c:/qemu/qemu-0.9.0-windows

  >qemu-img.exe create solaris.img 10G

  ◆4. 准备就绪, 用下面命令下安装:

  >qemu.exe -L . -m 512 -boot d -hda solaris.img -cdrom solaris.iso

  相关选项说明:

  -L : bios位置

  -m : 内存大小(单位是Mbyte)

  -boot : 启动设备(boot device), 包括三种, 分别为 floppy(a), hard disk(c), CD-ROM(d)

  -hda : 硬盘镜像(hard disk image)

  -cdrom : 光盘镜像(CD-ROM image)

  -fda : 软盘镜像(floppy image), 这里没用到

  ◆5. 接下来的安装就跟直接装在硬盘上一样了. 不过Qemu安装的确有点慢, 不知使用加速器(Kqemu)之后会怎样.:)

  在慢长的安装之后, 需按Enter重启. 重启后仍会从光盘启动. 此时按Ctrl+Alt+2到Qemu提示符下, 再输入Quit退出. 然后在Dos提示符下输入如下命令从硬盘启动:

  >qemu.exe -L . -m 512 -boot c -hda solaris.img

  此时就可以进入安装好的OpenSolaris, 注意这也是个比较慢的过程.:)

  ◆6. 登录时用户名和密码都是root. 这是该DVD自动安装盘在制作时配置好的. 用吧. 截个图先:)

Howto : GfxBoot ( Grub like suse )

11:13:00 PM 0 Comments

Howto : GfxBoot ( Grub like suse )

Gfxboot makes grub look nicer but with the same features
In this howto you will install gfxboot and a suse theme for it, soon I'll make an ubuntu one
Ok, let's start

Download the grub-gfxboot.deb
And the message.suse

First remove your old grub
Code:
sudo apt-get remove grub
Then Install the gfxboot-grub
Code:
sudo dpkg -i grub-gfxboot_0.97-5_i386.deb
then we're going to move the message
Code:
sudo cp message.suse /boot/grub/ # the suse can be replaced by the one you downloaded
Then edit your menu.lst

Code:
sudo cp /boot/grub/menu.lst /boot/grub/menu.lst_backup
sudo gedit /boot/grub/menu.lst
and make it use gfxboot
Code:
gfxmenu /boot/grub/message.suse # the suse can be replaced

Then do :
Code:
sudo grub

grub> find /boot/grub/stage1
(hdx,y) # this will be the output
grub> root (hdx,y)
grub> setup (hdx)
-- Howto make you own theme --


Code:
mkdir /home/name/whatever
cpio -i < /boot/grub/message.suse # replace it by the name of you message
edit the pictures
sudo ls . |cpio -o > /boot/grub/message.new
Reboot and enjoy

制作一个可启动的Debian Installer+Damn Small Linux 2合1 U 盘

1:38:00 PM 0 Comments

说明 & 免责声明:

  • U 盘的可引导性同时依赖于 U 盘本身和计算机主板,较早主板一律不支持
  • 作者不对读者因为参照本文所引起的一切后果负责

一、引导程序概述

任何一个操作系统在任何一个硬件平台上的运行都需要一个引导的过程,即,初始化软件环境、把内核从存储介质放到内存当中去,并开始运行。当然对于某些简单软硬件系统,这个过程可能及其简单,而对于 PC 就要略微复杂一些了。

PC 的引导程序上承 BIOS,下接内核的初始化代码,虽然开一次机只运行一次后就不留痕迹了,不过还是相当重要的。所有的引导程序都在做类似的事情:

  • 驻留在存贮介质的特殊位置可以被 BIOS 启动,或是自己是某一系统的可执行文件,可以被用户显式或隐式在该系统(宿主系统)内启动;
  • 了解要被启动的必要启动文件的位置,包括系统内核、ramdisk 等,并把它们读取出来、装载到内存之中;
  • 构造环境、运行操作系统的内核,自己则就此退出历史舞台。

历 史上,用于 Linux 的最著名的引导程序莫过于 LILO 和 Grub 了,作为通用的引导程序,二者用途广泛,但对于一些特殊的场合,譬如引导程序可利用的空间比较有限的可移动存储介质 (通俗地说,包括光盘、软盘、u 盘等),它们有些过于厚重了,这就引出了我们今天的主角 --- SYSLINUX/ISOLINUX,现在,你只要知道他们是引导程序就足够了,接下来,我们还要插入一些废话。

二、initrd

initrd = init ramdisk, 顾名思义,就是在启动时使用的一个内存虚拟磁盘,它是系统广泛的硬件支持性的必需品。

我 们知道,Linux 的驱动程序是内核的一部分,它们提供了硬件向上层的抽象接口,Linux 内核的核心子系统 --- 虚拟文件系统部分的工作强烈依赖于底层硬件驱动程序的支持,在启动过程当中,当某些必备的驱动程序无法使用的时候,比如 EXT2 文件系统、IDE 硬盘适配器等无法工作的时候,系统启动将就此中止,发生所谓的``Kernel Panic'',这也是初学者编译内核最常遇到的困难。

然而,我们当然不能将所有的驱动都编译到内核当中去,因为

  • 我们不能无限制地加大内核的尺寸,这对于系统资源,尤其是引导过程中非常有限的可用存储资源是难以承受的
  • 我们可以把很多驱动程序编译成模块,随用随加载
  • 极少数情况,某些模块是相互冲突的,比如 2.4 内核的某些版本之中,reiserfs 和 ext3 两种驱动不能同时被编译到内核当中。

所以,我们只能在内核中放入必要的驱动程序,其余的不那么需要的部分编译成模块放到 /lib/modules/`uname -r`/ 之中,在需要的时候会被加载。

但 是,对于具有通用性的内核,是很难论断出哪几种驱动程序才是真正必须的,究竟是 Intel 的 IDE 磁盘控制器还是 AMD/nVidia 的,抑或是 VIA 的,乃至光纤通道SCSI 磁盘……是阿,这真是个很困扰人的问题,没有一个驱动可以在占用绝对少的空间的前提下应付所有的设备,于是,我们退而求其次,寻求一个中间介质 --- ramdisk

在内核启动前,引导程序首先在内存之中构建一个 ramdisk,成为一个基本文件系统,然后 Linux 内核以此为自己的根文件系统启动,这样的好处是可以不必理会磁盘驱动的问题,只要能驱动 ramdisk 就可以了。

用 ramdisk 启动之后,在 ramdisk 的启动脚本 (一般叫 /linuxrc) 之中,针对硬件尝试 ramdisk 里面的 /lib/modules/`uname -r`/,加载恰当的驱动,这时系统已经具备了切换到硬盘或其他介质上的文件系统的条件了。

机不 可失,这时,我们首先加载硬盘或光盘、u 盘等启动介质,然后设该介质为根分区,并运行其 init 进程为 1 进程,之后,在 init 脚本中,释放掉 initrd 的空间,这就是借助 initrd 的引导过程。在这个过程之中 引导程序帮我们多做了一件事 --- 构建 ramdisk, 把 initrd 放入内存。

三、用 SYSLINUX/ISOLINUX 引导软盘和光盘

上文已经 说过了,SYSLINUX/ISOLINUX 是专门用来引导可移动介质的轻量级引导程序,因为这样的介质通常不会固定只针对一种硬件,initrd 当然是 SYSLINUX/ISOLINUX 必须支持的功能了。这两种引导程序其实是一样的,没有多大区别,只是放在不同的设备的引导区罢了。

3.1 配置 SYSLINUX/ISOLINUX

对于这两种引导程序,都会有一段引导代码,写入引导代码的时候,还同时需要一个配置文件: syslinux.cfg/isolinux.cfg,同样,这两个文件也是一样的,唯一的区别在于文件名,其各个字段的写法如下:

DISPLAY xxx.txt
这指定了一个文件名,会在启动的时候显示的内容,该文件甚至可以包含一个 RLE 编码的图形文件,也就是大家在安装光盘启动时看到的那个;不过这个字段不甚重要,我们就略过了。

DEFAULT linux
指定 label 是 linux 的启动选项为缺省,当然也可以是别的。

LABEL linux
kernel vmlinuz
append initrd=initrd26.gz ramdisk_size=1000000 vga=791
这 就是一个启动描述,前面的 label 大家都认识了,之后分别是指定 kernel 和内核参数,其中重要的参数就是 initrd= 指定 initrd 的文件和 ramdisk_size= 指定 initrd 的尺寸上限。其余的内核参数还可能有很多,不过这里的参数我们一般都可以抄过来。这样的启动选项描述是可以有若干个的。

PROMPT=1
这是说,向用户提示输入选择,直接回车就是缺省选项了

TIMEOUT=0
没有时间限制,当然也可以指定一定时间之后自动进入缺省选项。

好了,就这么多,如果你会用 LILO 的话,用这个一定得心应手,说实话 grub 也差不了太多。

3.2 安装 SYSLINUX/ISOLINUX

配置文件写完了,现在进入实质阶段,这里,两种引导程序还是略有差别的,首先介绍SYSLINUX:

首先格式化引导介质为 FAT16 格式 (软盘似乎应该是 FAT12),我们的例子里面是 U 盘,
mkdosfs -F16 -I /dev/sda
我们是操作整个 U 盘,而不是里面的唯一分区,这种情况不是很多见,只是手上的 U 盘比较特殊,大部分情况下,我们也可以
mkdosfs -F16 /dev/sda1
然后挂在该 U 盘,放入我们的 syslinux.cfg 以及 kernel 和 initrd.gz,还有其他启动所需要的东东,之后 umount 该 U 盘。

* 执行下面操作之前,必须 umount U 盘!*

然后写引导区:
syslinux /dev/sda (或 syslinux /dev/sda1,如果是格式化的 /dev/sda1 的话)
至此就完成了。

对于光盘,同样不复杂,我们用 ISOLINUX:

在 准备制作 ISO 的目录里添加一个子目录,比如 boot/isolinux/ ,然后放入 isolinux.cfg 和一个对所有光盘都一样的 isolinux 提供的引导介质 isolinux.bin,当然还要放入相应的 kernel, initrd 等等,然后,制作 iso 的时候要使用 -b 参数:
mkisofs -o output.iso \
-b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
-no-emul-boot -boot-load-size 4 -boot-info-table \
for-iso-dir/
最 后的参数就是指定的光盘的目录了,-c 参数的那个文件是自动生成的,不用太担心,其余参数都是固定的。事实上,也常常有人用 isolinux/ 而不是 boot/isolinux/ ,这都是约定俗成的,你完全可以用自己的。这里的路径都是相对于光盘的根的,而和制作光盘时的工作目录没有关系。

至此,你也会用 SYSLINUX/ISOLINUX 了。 :)

四、实战 --- damn small linux + debian installer, 2 in 1 usb disk

  • 1 下载 di 的 hd-image 里的 kernel image 和 initrd,放入 U 盘,同时把 businesscard iso 也放进去,从 iso 里找到 isolinux.cfg,记下里面的启设置
  • 2 下载 dsl,把 KNOPPIX 目录搬到我们的 U 盘里,把 boot/isolinux/ 里面的 kernel image 和 initrd 也放入 U 盘的根目录,这时,U 盘根目录里同时有二者的启动文件了,也记住 dsl 里面的 isolinux.cfg 的启动选项。
  • 3 以其中一个的 isolinux.cfg 为基础,加入另一个的启动参数,注意 label 命名不要冲突了就可以了。
  • 4 umount U盘,然后对 U 盘运行 syslinux,写引导区,大功告成。

如前面帖子说过,dsl 的 initrd 之中,只搜索 /dev/sda[1-9] 而不搜索
/dev/sda,所以,如果如果像我们一样被迫用 /dev/sda 的话,就不得不修改一下 dsl 的 initrd 里面的 linuxrc 了,除此之外,没有什么其它值得大书特书的了。

Enjoy it!

使用sed处理多行数据

1:32:00 PM 0 Comments

使用sed处理多行数据


数据文件txt: 一列,N行. 现在要把前m行摊开,剩下的依次跟上,另外保证精度不变。

比如8行:
0.15
0.28
0.36
0.42
5.12
43.5
234.1
3.14
变成
0.15 0.28 0.36 0.42
5.12 43.5 234.1 3.14

现在,我使用 sed来实现这个功能,当然,题目有点不清楚,不知是只处理前m行,还是每m行处理一次,前者似乎正是题目描述的,虽然后者更像真的。不过,我们都实现一下。我的解决方案似乎不是很精巧,不过确实有效。

首先科普两个sed概念:

  • hold space: 是一个保留空间,在一次 sed 处理里面,这个东东是唯一的,感觉有点像 static 变量,呵呵
  • pattern space: 是当前处理的空间,正常的讲,就是当前处理的行,不过,因为有了hold space,加上一些处理命令,就可以把多个行一起处理了

有了这两个概念,下面讲着就不费劲了。

只处理前m行

以 t 为你的测试数据文件,如果你只想以第m行为分隔输出的话,假设m为4

~$ sed -ne 'H;1h;4{x;s/\n/\ /gp};5h;${x;s/\n/\ /gp}' t
0.15 0.28 0.36 0.42
5.12 43.5 234.1 3.14

这个处理的思路是,每次都把当前行放到 hold space 中去,到了第m行或最后一行,一起取出来打印,中间有一点小波折,就显得比较长,是这样的:

  • H -- 这条命令对所有行生效,功能是对 hold space 附加一个回车,然后把
    pattern space 中的内容,也就是当前行附加进 hold space;
  • 1h -- 这条命令对第一行有效,把第一行的 pattern space,也就是第一行的内容直接覆盖进 hold space,对第一行来说,与 H 相比,仅仅是去掉了一个回车,因为后面我们要替换回车为空格,这个多余的回车就显得有一点讨厌了,呵呵。
  • 4{x;s/\n/\ /gp} -- 这个仅对第四行生效,也就是第 m 行,当前的 pattern space就是当前行,而当前的 hold space 已经执行过又一次 H 了,所以内容应该是
    line#1
    line#2
    ...
    line#m
    现在做如下处理:
    x -- 交换 pattern space 和 hold space,这样,上述内容就在 pattern space 里面了,这时就可以进行替换了
    s/\n/\ /gp -- 把 pattern space 中所有(g=globle) \n(\n=newline) 替换(s=
    substitute) 为空格(\ ),并打印(p=print)。如此就完成了前m行的输出。
  • 5h -- 把第5行,也就是 m+1 行写入 hold space,经过第m行的上述交换,hold space里面是第 m 行的内容,现在写入第 m+1 行,就清除了里面的前一行的内容。
  • ${x;s/\n/\ /gp} -- 在最后一行 ($) 进入的时候收拾残局,处理和第m行是一样的。

此外,关于 sed 的选项开关, -n 是没有明确指示(p)不输出,-e 就是执行后面的匹配操作

继续测试,假设m为3

~$ sed -ne 'H;1h;3{x;s/\n/\ /gp};4h;${x;s/\n/\ /gp}' t
0.15 0.28 0.36
0.42 5.12 43.5 234.1 3.14

看来m不是4也可以 :)

每隔m行处理一次

如果你想以m的倍数分隔,假设m为4

~$ sed -ne 'H;1h;4~4{x;s/\n/\ /gp};5~4h;${x;s/\n/\ /gp}' t
0.15 0.28 0.36 0.42
5.12 43.5 234.1 3.14

这里仅有两处需要追加解释的:

  • 4~4,也就是 m~m,是处理从 m 开始,间距为 m 的所有行,也就是 n*m
  • 5~4,是 m+1~m,是处理从 m+1 开始,间距为 m 的所有行,也就是 n*m +1

下面测试,假设m为3

~$ sed -ne 'H;1h;3~3{x;s/\n/\ /gp};4~3h;${x;s/\n/\ /gp}' t
0.15 0.28 0.36
0.42 5.12 43.5
234.1 3.14

证明 N/m 有余数也是可以的

假设m为2

~$ sed -ne 'H;1h;2~2{x;s/\n/\ /gp};3~2h;${x;s/\n/\ /gp}' t
0.15 0.28
0.36 0.42
5.12 43.5
234.1 3.14

证明 N 是 m 的大于2的整数倍 (N/m=4) 也是可以的。

大家可以考虑优化一下处理 :P

从文件中提取代理服务器信息

原始数据中包含若干 nn.nnn.nn.nnn:pp@HTTP 这样的信息,当然,一行可能有多个,也可能只有一个,现在要提取出来其中的代理信息,变成每行一个, nn.nnn.nn.nnn:pp的形式。

首先

sed -e 's/\@HTTP/\n/g'

确保每行一个,然后

sed -n -e 's/.*[^0-9]\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)
\.\([0-9]*\):\([0-9]*\)[[:space:]]*$/\1\.\2\.\3\.\4:\5/gp'

提取地址,并输出。

The Syslinux Project

9:17:00 PM 0 Comments

http://syslinux.zytor.com/wiki/index.php/The_Syslinux_Project

The Syslinux Project

The Syslinux Project covers lightweight bootloaders for
  • MS-DOS FAT filesystems (SYSLINUX),
  • network booting (PXELINUX),
  • bootable "El Torito" CD-ROMs (ISOLINUX),
  • Linux ext2/ext3 filesystems (EXTLINUX).
  • The project also includes MEMDISK, a tool to boot legacy operating systems (such as DOS) from nontraditional media; it is usually used in conjunction with PXELINUX and ISOLINUX.



SYSLINUX
SYSLINUX is a boot loader for the Linux operating system which operates off an MS-DOS/Windows FAT filesystem.
Installing syslinux to the disk will alter the boot sector on the disk and copy a file named LDLINUX.SYS into its root directory.
Options

These are the options common to all versions of Syslinux:

 -s Safe, slow, stupid; uses simpler code that boots better.
This version may work on some very buggy BIOSes on which SYSLINUX would otherwise fail.
If you find a machine on which the -s option is required to make it boot reliably,
please send as much info about your machine as you can, and include the failure mode.
-f Force installing

These are only in the Windows version:
-m MBR; install a bootable MBR sector to the beginning of the
drive.
-a Active; marks the partition used active (=bootable)

NT/2K/XP

syslinux.exe [-sfma][-d directory] [driveletter:]
-d directory: the directory that syslinux.cfg would be expected to be.

DOS

syslinux.com [-sf][-d directory] [driveletter:]

Linux

syslinux [-s] [-o offset] [DeviceOrImage]
The -o option (if specified) is used with a disk image file and specifies the byte offset of the filesystem image in the file.



ISOLINUX

ISOLINUX is a boot loader for Linux/i386 that operates off ISO 9660/El Torito CD-ROMs in "no emulation" mode. This avoids the need to create an "emulation disk image" with limited space (for "floppy emulation") or compatibility problems (for "hard disk emulation".)



To create an image, create a directory called "/isolinux" (or, if you
prefer, "/boot/isolinux") underneath the root directory of your ISO
image master file tree. Copy isolinux.bin, a config file called
"isolinux.cfg" , and all necessary files (kernels, initrd, display files, etc.)
into this directory, then use the following command to create your ISO
image (add additional options as appropriate, such as -J or -R):
mkisofs -o output.iso \
-b isolinux.bin -c isolinux/boot.cat \
-no-emul-boot -boot-load-size 4 -boot-info-table \
root-of-iso-tree

中国网民的四个“顽固”习惯

8:59:00 PM 0 Comments

四个极具中国特色的网民上网习惯:
一、IE6
IE8已经发行,却没能拯救IE逐年下降的市场占有率。然而在中国这片“世外桃源”上IE春光依旧,IE6依然占据着主流市场。


某个中文网站的浏览器使用概况

随着升级版的发布,IE6越来越受到用户,尤其是网页设计者的诟病。其缺点在这就不一一列举,只探讨为何仍有如此多用户固守IE6:

1.不合标准的网页
以中文网页为甚,仍有无数网页是IE Only。而这带给用户的错觉就是:既然IE6能正确显示网页,我为何还要升级到那些“还不能正常显示网页”的浏览器?

2.网银和网络支付系统的固守
几乎绝大部分非IE用户死就死在网银上,从而难以彻底摆脱IE。网银总是借口安全问题只允许IE用户登录,但是这些庞大而不敢出一点岔子的系统对IE7和IE8的兼容也并不理想。或许,同样陈旧的IE6是登录网银的最佳选择。

3.公共计算机升级成本

网吧、学校机房这类上网场所不得不考虑成本问题,他们是否有必要为了浏览器而升级。而对网页显示没有严苛要求的初等用户,IE6也是能凑合用的,尽管相当凑合。

二、收藏夹

似乎很多年以前,用户们就爱上了收藏夹功能。于是那些年的网站上必然有明显的“添加到收藏夹”标志。

收藏夹似乎是个很不错的功能,只要有喜欢的网页,点击两下就能让浏览器记住。实际上它并非是落后,但是现在确实有许多更高效的替代方法,比如RSS聚合阅 读、网摘等服务。不幸的是这些风靡国外的服务在国内似乎并不被普遍接受。这从那些知名中文博客可怜的订阅量就能明显看出。

三、密码保存

保存密码看起来是个不错的功能,但这却与设置密码的初衷有矛盾。许多用户使用的还是IE中简陋的“记住密码”功能。尽管这免去了输入密码的麻烦,却带来了极大的不安全因素。同时,长期保存可能会让你根本忘记密码甚至账户名。

最典型的例子就是:记得QQ密码,却把QQ号给忘了。

四、绿色软件

许多见识过中国互联网的用户都喜欢使用绿色软件。但是你们是否想过版权问题?打包组以未经原作者授权的方式传播着软件。这无疑侵害了作者的权利。

但是这并不是软件使用者的错,事实上经过重新打包的绿色软件常常比原软件更可信,因为原版的安装文件往往会“附赠”一些“实用小工具”,它们甚至会优秀到不用你点击安装就把“附赠软件”装进你的电脑。

最近就有这样的例子:迅雷安装包内捆绑的百度工具条被McAfee查杀

我承认软件作者也要养家糊口,但或许这样赚钱的方式太不受人欢迎。为什么大批国外的程序员就能免费提供ZIP格式压缩的软件,而国内的免费软件却要捆绑有这么多“莫名其妙”的东西?

Fedora 9 - how to replace gdm with kdm

11:48:00 AM 0 Comments

It took me some time googling to find out how to do this on F9, so I
thought I'd share it - how to configure the system to use kdm as the
display manager instead of gdm - in case it saves time for someone else.

In Fedora 9 there appears to be no GUI-based way of configuring this
(e.g., via 'System Settings'). Nevertheless, it is pretty easy.

You do need to become root to do it (e.g., 'sudo su').

The script:

/etc/X11/prefdm

is run at startup time; it looks for /etc/sysconfig/desktop and if
it exists, 'sources' it. It then checks to see if the DISPLAYMANAGER
variable is set and, if so, uses its value to try to determine which
display manager to use (expecting it to be one of: GNOME, KDE, WDM,
XDM). If this variable is not set, it tries to execute, in this order:

gdm
kdm
wdm
xdm

So the first of these that runs successfully is the one that will be
used, if the DISPLAYMANAGER variable is not set.

On my system /etc/sysconfig/desktop did not exist, so prefdm was
executing gdm. The solution, of course, is to create
/etc/sysconfig/desktop and simply put this line in it:

DISPLAYMANAGER=KDE

If the file exists, of course, just make sure DISPLAYMANAGER is set as
above.

(Reference:

http://mail.gnome.org/archives/garnome-list/2002-September/msg00028.html
)

Note: I used this solution to solve another irritating problem: gdm on
F9 always defaults to gnome - you have to explicitly tell it to use kde
each time if you're a KDE user.

远程桌面连接Fedora8

10:29:00 AM 0 Comments

远程桌面连接Fedora8

出自:http://gjx.com.blog.163.com/
从开始了解Linux就知道用VNC作为远程桌面连接,常见的几种远程管理Linux的方法,基本上都是利用SecureCRT,F-Secure SSH或是PUTTY等客户端工具通过ssh服务来实现的,这些客户端工具几乎不需要什么配置,使用简单,但是它们都无法启动窗口服务的程序或进程,在Linux桌面也同样发达的今天,直接对Linux进行桌面控制的管理也同样方便和必要了。想到了管理Solaris时用的X显示管理器(X display manager)或者说xdm。索性把Fedora8上把这2种远程桌面服务都配置。

一.VNC的配置
VNC在Fedora系列Linux上配置很简单,首先确认有安装vnc组件。我在此用的GNOME桌面,打开系统→首选项→Internet和网络→远程桌面 ,分别勾选"允许其他人查看您的桌面"和"允许其他用户控制您的桌面",在安全方面,可以设置两种方式,输入密码或前台确认。最后放开防火墙和访问列表上tcp协议5900端口或主机,即可在允许访问的主机上通过VNC客户端远程控制了。

二.xdm的配置
xdm是一个显示管理器,提供了灵活的任务管理功能。然而xdm通常被认为是"GUI的登陆屏幕,可以自动启动我的X任务",xdm使用X联盟的X显示管理控制协议,即XDMCP,来和X服务器通信。它允许X服务器从运行xdm服务的服务器上获得会话服务。

确认用于X显示管理器的组件,具体需要哪几个我也懒得一个个试了。在命令行下,进入xdm配置目录,修改Xaccess和xdm-config两个文件
[lxuser@fedora8 xdm]$ ls
GiveConsole Xaccess Xreset Xservers Xsetup_0 Xwilling
TakeConsole xdm-config Xresources Xsession Xstartup
首先su切换到root下,复制两个文件作为备份
[root@fedora8 xdm]# cp Xaccess Xaccess.orig
[root@fedora8 xdm]# cp xdm-config xdm-config.orig
[root@fedora8 xdm]# vi Xaccess
打开Xaccess找到下列一行,去掉注释
#* #any host can get a login window

保存退出再打开xdm-config,找到下行
DisplayManager.requestPort: 0

在前面加 !
!DisplayManager.requestPort: 0

保存退出,在图形窗口终端上配置
[root@fedora8 lxuser]#gdmsetup
弹 出图形设置工具"登陆窗口首选项",在"常规"选项卡里,可以设置默认回话,是KDE或GNOME;在"远程"选项卡里,样式选为"与本地相同",默认为 禁止远程登陆,在其下方"配置XDMCP..."里可以修改默认端口等设置;在"安全"选项卡里,勾选"允许本地系统管理员登陆",至于"允许远程管理员 登陆"则根据自己实际安全需要决定是否勾了,此选项意味是否允许远程直接以root用户登陆。最后放开防火墙和访问列表上udp协议177端口或主机,重 启Linux或xdm对应的服务,即可在允许访问的主机上通过Xmanager客户端远程控制了。

三.区别
通过VNC服务登陆的桌面,必须有用户在前台登陆,并且是在该用户下设置了vnc。通过vnc桌面共享,可以在远程客户端里看到3D桌面的效果,和用户在 实际主机上操作没有区别;通过X显示管理器登陆,类似Windows的终端服务,是后台守护程序,和远端主机不用共享一个桌面控制,但xdm下只有一个虚 拟桌面,看不到其他效果,只是单纯的一个终端环境,用户管理服务器比较方便。

startx启动过程分析

4:44:00 PM 0 Comments

1 xinit 4

1.1 功能 4

1.2 用法 4

1.3 例子 4

1.4 分析 5

2 startx脚本 6

2.1 功能 6

2.2 用法 6

2.3 例子 6

2.4 分析 6

2.5 总结 11

3 startx默认启动过程 12

3.1 startx的几种启动方式 12

3.2 Xsession 13

4 startx启动过程小结 18


  • 前言

在制作Live CD项目中,我想自己编写一个基于GTK的类似桌面的简单的应用程序,在这个应用程序中,只有几个简单的按钮,和一个全屏的背景,每个按钮代表一个功能,例如其中一个按钮就是mplayer,只要按下这个按钮就启动mplayer播放器。但是在这个过程中,我发现如果我仅仅启动一个X ServerX、一个窗口管理器(metacity)和我的应用程序,当点击按钮启动xine播放器的时候,选择一个文件的时候会出现xine播放器消失的状况,并且应用程序响应的时间会变得很慢,但是如果我通过startx启动X Server,再启动我的应用程序,将不会有这个问题。因此,我就学习了一下startx的启动过程。写此文的目的就是把我学到的和大家分享一下。本文主要是基于Ubuntu8.04操作系统,其它类Unix操作系统可能会有细微的差别。


1xinit

在说明startx之前,我想我们应该先了解一下xinit。因为startx就是通过调用xinit启动X的。

1.1功能

当我们安装了Ubuntu后,默认就已经安装了xinit,它位于/usr/bin下。xinit是一个二进制文件,并非是一个脚本。它的主要功能是启动一个X服务器,同时启动一个基于X的应用程序。

1.2用法

xinit的用法为:xinit [[client] options ] [-- [server] [display] options]。其中client用于指定一个基于X的应用程序,client后面的options是传给这个应用程序的参数,server是用于指定启动哪个X服务器,一般为/usr/bin/X/usr/bin/Xorgdisplay用于指定display number,一般为0,表示第一个displayoption为传给server的参数。


如果不指定clientxinit会查找HOME(环境变量)目录下的.xinitrc文件,如果存在这个文件,xinit直接调用execvp函数执行该文件。如果这个文件不存在,那么client及其options为: xterm -geometry +1+1 -n login -display :0


如果不指定serverxinit会查找HOME(环境变量)目录下的.xserverrc文件,如果存在这个文件,xinit直接调用execvp函数执行该文件。如果这个文件不存在,那么server及其display为: X :0 。如果系统目录中不存在X命令,那么我们需要在系统目录下建立一个名为X的链接,使其指向真正的X server命令(Ubuntu下为Xorg)。


1.3例子

下面是几个关于xinit应用的例子:

  1. xinit /usr/bin/xclock -- /usr/bin/X :0

该例子将启动X server, 同时将会启动xclock。请注意指定clientserver时,需要用绝对路径,否则xinit将因无法区别是传给xtermserver的参数还是指定的clientserver而直接当成是参数处理。

  1. HOME下新建.xinitrc文件,并加入以下几行:

xsetroot -solid gray &

xclock -g 50x50-0+0 -bw 0 &

xterm -g 80x24+0+0 &

xterm -g 80x24+0-0 &

twm

xinit启动时,它会先启动X server,然后启动一个clock,两个xterm,最后启动窗口管理器twm

请注意:

最后一个命令不能后台运行,否则所有命令都后台运行的话xinit就会返回退出,同样的,除最后一个命令外都必须后台运行,否则后面的命令将只有在该命令退出后才能运行。


1.4分析

看到这里,眼尖的人或许早以看出xinit的功能完全可以由脚本来实现,例如要启动X Server 和一个xterm,就像xinit默认启动的那样,只需要在新建一个脚本或在rc.local中加入:

X&

export DISPLAY=:0.0

xterm

这个实现完全正确,然而却并没有完全实现xinit所具有的功能,xinit所有的一项功能就是当最后一个启动的client(如上面第二个例子中的twm窗口管理器)退出后,X服务器也会退出。而我们的脚本实现中当我们退出xterm后并不会退出X server


2startx脚本

用过linux的人基本上都知道linux下有个命令叫做startx,那么它到底是怎么实现的呢?

2.1功能

当我们在终端下想启动图形界面时,我们都会通过输入startx来实现,该命令可以启动一个X server,而且可以启动一个漂亮的图形界面(Ubuntu下,我装的是gnome)。

2.2用法

Startx的用法和xinit的基本一样:startx [ [ client ] options ... ] [ -- [ server ] options ... ]。为什么呢?这是因为startx其实就是一个脚本,它启动X server就是通过调用xinit命令实现的,startx的参数将全部传给xinit。因此,这些参数的意义和xinit的参数是一样的。

2.3例子

下面是两个关于startx命令的简单例子:

  1. startx -- -depth 16

该例子主要是以16位色启动X 服务器。

  1. startx -- -dpi 100

该例子主要是以100dpi启动X 服务器。

2.4分析

下面我们来分析一下startx脚本。startx脚本位于/usr/bin下,直接用vim打开我们可以看到它的具体实现如下:


#!/bin/bash #注意:该脚本用的是bash shell解析的


# $Xorg: startx.cpp,v 1.3 2000/08/17 19:54:29 cpqbld Exp $

#

# This is just a sample implementation of a slightly less primitive

# interface than xinit. It looks for user .xinitrc and .xserverrc

# files, then system xinitrc and xserverrc files, else lets xinit choose

# its default. The system xinitrc should probably do things like check

# for .Xresources files and merge them in, startup up a window manager,

# and pop a clock and serveral xterms.

#

# Site administrators are STRONGLY urged to write nicer versions.

#

# $XFree86: xc/programs/xinit/startx.cpp,v 3.16tsi Exp $


#下面主要是对一些变量进行赋值。

userclientrc=$HOME/.xinitrc

sysclientrc=/etc/X11/xinit/xinitrc



userserverrc=$HOME/.xserverrc

sysserverrc=/etc/X11/xinit/xserverrc

defaultclient=xterm

defaultserver=/usr/bin/X

defaultclientargs=""

defaultserverargs=""

clientargs=""

serverargs=""


#下面的语句主要是说:如果$HOME/.xinitrc文件存在,并且不是一个目录,那么就将defaultclientargs赋值为$HOME/.xinitrc,否则,如果/etc/X11/xinit/xinitrc存在并且不是一个目录,就将defaultclientargs赋值为/etc/X11/xinit/xinitrc


if [ -f $userclientrc ]; then

defaultclientargs=$userclientrc

elif [ -f $sysclientrc ]; then

defaultclientargs=$sysclientrc







fi


#下面的语句主要是说:如果$HOME/.xserverrc文件存在,并且不是一个目录,那么就将defaultclientargs赋值为$HOME/.xserverrc,否则,如果/etc/X11/xinit/xserverrc存在并且不是一个目录,就将defaultclientargs赋值为/etc/X11/xinit/xserverrc


if [ -f $userserverrc ]; then

defaultserverargs=$userserverrc

elif [ -f $sysserverrc ]; then

defaultserverargs=$sysserverrc

fi

#whoseargs变量赋值为字符串“client”,表示当前解析的指定client的参数。

whoseargs="client"

#startx的一个参数不为空时就进入while循环。

while [ x"$1" != x ]; do

case "$1" in

# '' required to prevent cpp from treating "/*" as a C comment.

/''*|\./''*)

if [ "$whoseargs" = "client" ]; then

if [ x"$clientargs" = x ]; then

client="$1" #解析出了用户指定的Client程序

else

clientargs="$clientargs $1" #解析出了Client的参数

fi

else

if [ x"$serverargs" = x ]; then

server="$1" #解析出了用户指定的X Server程序

else

serverargs="$serverargs $1" #解析出了X Server的参数

fi

fi

;;

--) #遇到“- -”就解析server

whoseargs="server"

;;

*)

if [ "$whoseargs" = "client" ]; then

clientargs="$clientargs $1"

else

# display must be the FIRST server argument

if [ x"$serverargs" = x ] && \

expr "$1" : ':[0-9][0-9]*$' > /dev/null 2>&1; then

display="$1" #解析出display

else

serverargs="$serverargs $1"

fi

fi

;;

esac #case语句结束

shift #将参数列表左移一位,即解析下个参数.

done


# process client arguments

if [ x"$client" = x ]; then #如果client变量为空,即用户没有指定client

# if no client arguments either, use rc file instead

if [ x"$clientargs" = x ]; then #如果用户没有指定client参数 就将client设为前面设定的默认的rc文件(为$HOME/.xinitrc,或/etc/X11/xinit/xinitrc

client="$defaultclientargs"

else

client=$defaultclient #如果用户指定了client参数,就将client设定为xterm

fi

fi


# process server arguments

if [ x"$server" = x ]; then #如果server变量为空,即用户没有指定server

# if no server arguments or display either, use rc file instead

if [ x"$serverargs" = x -a x"$display" = x ]; then #如果serverargs为空,并且display为空,就将server设为前面设定的默认的rc文件(为$HOME/. xserverrc,或/etc/X11/xinit/ xserverrc

server="$defaultserverargs"

else

server=$defaultserver #如果用户指定了serverargsdisplay,就将server设定为/usr/bin/X

fi

fi


if [ x"$XAUTHORITY" = x ]; then #如果环境变量XAUTHORITY为空,就设定为$HOME/.Xauthority

XAUTHORITY=$HOME/.Xauthority

export XAUTHORITY

fi


removelist=


# set up default Xauth info for this machine


# check for GNU hostname

if hostname --version > /dev/null 2>&1; then #如果hostname命令存在

if [ -z "`hostname --version 2>&1 | grep GNU`" ]; then #如果hostname –version中不包含GNU 就将hostname变量设定为命令hostname –f返回的字符串。

hostname=`hostname -f`

fi

fi


if [ -z "$hostname" ]; then #如果hostname长度为0,就将hostname变量设定为命令hostname返回的字符串。

hostname=`hostname`

fi


authdisplay=${display:-:0}


mcookie=`/usr/bin/mcookie`








dummy=0


# create a file with auth information for the server. ':0' is a dummy.

xserverauthfile=`mktemp -p /tmp serverauth.XXXXXXXXXX`

trap "rm -f $xserverauthfile" HUP INT QUIT ILL TRAP KILL BUS TERM

xauth -q -f $xserverauthfile <<>

add :$dummy . $mcookie

EOF

serverargs=${serverargs}" -auth "${xserverauthfile}


# now add the same credentials to the client authority file

# if '$displayname' already exists do not overwrite it as another

# server man need it. Add them to the '$xserverauthfile' instead.

for displayname in $authdisplay $hostname$authdisplay; do

authcookie=`xauth list "$displayname" \

| sed -n "s/.*$displayname[[:space:]*].*[[:space:]*]//p"` 2>/dev/null;

if [ "z${authcookie}" = "z" ] ; then

xauth -q <<>

add $displayname . $mcookie

EOF

removelist="$displayname $removelist"

else

dummy=$(($dummy+1));

xauth -q -f $xserverauthfile <<>

add :$dummy . $authcookie

EOF

fi

done

echo "client=$client,clientargs=$clientargs,server= $server, display= $display, serverargs=$serverargs"


#下面的语句通过xinit启动X serverClients

xinit $client $clientargs -- $server $display $serverargs



if [ x"$removelist" != x ]; then

xauth remove $removelist

fi

if [ x"$xserverauthfile" != x ]; then

rm -f $xserverauthfile

fi






if command -v deallocvt > /dev/null 2>&1; then

deallocvt #释放所有未使用的虚拟终端的核心内存和数据结构

fi



2.5总结

由以上对startx脚本的分析,我们可以知道:startx将会先解析用户的参数,如果该用户指定了该参数(即解析结果不为空),那么startx就会以该参数来启动xinit,否则就会解析(与其说是解析,还不如说是执行)$HOME目录下的rc文件,如果该文件不存在,就会解析系统目录下(/etc/X11/xinit/)的rc文件,如果这个文件也不存在,那startx就将以默认的clientxterm)和server/usr/bin/X)为参数来启动xinit


3startx默认启动过程

通过以上对startx脚本的分析,我们知道了startx的基本的启动流程,但是到目前为止,我们还不知道仅仅在终端输入startx是怎么样启动gnome那漂亮的桌面的,下面我们来看一下其启动过程。

3.1startx的几种启动方式

由对startx脚本的分析,我们可以知道startx主要有三种启动方式:

a)、一种是自己指定要启动的clientserver, 例如:startx /usr/bin/xclock -- /usr/bin/X :0

b)、一种是通过在$HOME下新建.xinitrc文件来指定要启动的多个client.xserverrc来指定要启动的server(注意:这两个文件本来是不存在的);

c)、还有一种是直接输入startx而不指定参数,这也就是我们启动gnome桌面的方法。这里


我们主要介绍最后一种启动方法。


c这种启动方法中,我们可以知道,startx脚本会先去看系统目录(/etc/X11/xinit/)下的rc文件是否存在,如果不存在就会用默认的xterm/usr/bin/X来启动xinit。显然,startx启动的不是xterm,而是gnome桌面,因此gnome的启动是通过系统文件/etc/X11/xinit/xinitrc来指定的。


/etc/X11/xinit/xinitrc文件的内容如下所示:


#!/bin/bash #注意:该脚本用的是bash shell解析的


# $Xorg: xinitrc.cpp,v 1.3 2000/08/17 19:54:30 cpqbld Exp $


# /etc/X11/xinit/xinitrc

#

# global xinitrc file, used by all X sessions started by xinit (startx)


# invoke global X session script

. /etc/X11/Xsession #在当前这个shell环境中执行Xsession脚本



因此,gnome的启动应该在Xsession里。


X Server的启动则是通过系统文件/etc/X11/xinit/xserverrc来指定的,这个文件的内容为:


#!/bin/sh #注意:该脚本用的是Bourne shell解析的


# $Id: xserverrc 189 2005-06-11 00:04:27Z branden $


exec /usr/bin/X11/X -nolisten tcp


3.2Xsession

下面是Xsession脚本的内容:

#!/bin/sh #注意:该脚本用的是Bourne shell解析的

#

# /etc/X11/Xsession

#

# global Xsession file -- used by display managers and xinit (startx)


# $Id: Xsession 967 2005-12-27 07:20:55Z dnusinow $


set –e #打开errexit选项,该选项表示:如果下面有命令返回的状态非0,则退出程序。


PROGNAME=Xsession


#下面四个是信息输出函数,可以不管

message () {

# pretty-print messages of arbitrary length; use xmessage if it

# is available and $DISPLAY is set

MESSAGE="$PROGNAME: $*"

echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2

if [ -n "$DISPLAY" ] && which xmessage > /dev/null 2>&1; then

echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file -

fi

}


message_nonl () {

# pretty-print messages of arbitrary length (no trailing newline); use

# xmessage if it is available and $DISPLAY is set

MESSAGE="$PROGNAME: $*"

echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2;

if [ -n "$DISPLAY" ] && which xmessage > /dev/null 2>&1; then

echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file -

fi

}


errormsg () {

# exit script with error

message "$*"

exit 1

}


internal_errormsg () {

# exit script with error; essentially a "THIS SHOULD NEVER HAPPEN" message

# One big call to message() for the sake of xmessage; if we had two then

# the user would have dismissed the error we want reported before seeing the

# request to report it.

errormsg "$*" \

"Please report the installed version of the \"x11-common\"" \

"package and the complete text of this error message to" \

"."

}


# initialize variables for use by all session scripts


OPTIONFILE=/etc/X11/Xsession.options


SYSRESOURCES=/etc/X11/Xresources

USRRESOURCES=$HOME/.Xresources


SYSSESSIONDIR=/etc/X11/Xsession.d

USERXSESSION=$HOME/.xsession

USERXSESSIONRC=$HOME/.xsessionrc

ALTUSERXSESSION=$HOME/.Xsession

ERRFILE=$HOME/.xsession-errors


# attempt to create an error file; abort if we cannot

if (umask 077 && touch "$ERRFILE") 2> /dev/null && [ -w "$ERRFILE" ] &&

[ ! -L "$ERRFILE" ]; then

chmod 600 "$ERRFILE"

elif ERRFILE=$(tempfile 2> /dev/null); then

if ! ln -sf "$ERRFILE" "${TMPDIR:=/tmp}/xsession-$USER"; then

message "warning: unable to symlink \"$TMPDIR/xsession-$USER\" to" \

"\"$ERRFILE\"; look for session log/errors in" \

"\"$TMPDIR/xsession-$USER\"."

fi

else

errormsg "unable to create X session log/error file; aborting."

fi

# truncate ERRFILE if it is too big to avoid disk usage DoS

if [ "`stat -c%s \"$ERRFILE\"`" -gt 500000 ]; then

T=`mktemp -p "$HOME"`

tail -c 500000 "$ERRFILE" > "$T" && mv -f "$T" "$ERRFILE" || rm -f "$T"

fi


exec >>"$ERRFILE" 2>&1

echo "$PROGNAME: X session started for $LOGNAME at $(date)"


# sanity check; is our session script directory present?


#如果/etc/X11/Xsession.d不存在或不是一个目录则打印错误信息并退出。

if [ ! -d "$SYSSESSIONDIR" ]; then

errormsg "no \"$SYSSESSIONDIR\" directory found; aborting."

fi

# Attempt to create a file of non-zero length in /tmp; a full filesystem can

# cause mysterious X session failures. We do not use touch, :, or test -w

# because they won't actually create a file with contents. We also let standard

# error from tempfile and echo go to the error file to aid the user in

# determining what went wrong.

WRITE_TEST=$(tempfile)

if ! echo "*" >>"$WRITE_TEST"; then

message "warning: unable to write to ${WRITE_TEST%/*}; X session may exit" \

"with an error"

fi

rm -f "$WRITE_TEST"

# use run-parts to source every file in the session directory; we source

# instead of executing so that the variables and functions defined above

# are available to the scripts, and so that they can pass variables to each

# other


#/etc/X11/Xsession.d目录中的所有文件都读出,并存入SESSIONFILES变量中。

SESSIONFILES=$(run-parts --list $SYSSESSIONDIR)

#如果SESSIONFILES变量中的字符串不为空,即/etc/X11/Xsession.d中有文件存在

if [ -n "$SESSIONFILES" ]; then

set +e #关闭errexit选项

for SESSIONFILE in $SESSIONFILES; do

. $SESSIONFILE #在当前shell环境下执行该文件

done

set –e #打卡errexit选项

fi

exit 0


从以上的对Xsession脚本文件的分析,可以看出,Xsession脚本仅仅是执行了/etc/X11/Xsession.d目录下的所有文件,在该目录下,文件包括:

20x11-common_process-args

30x11-common_xresources

40x11-common_xsessionrc

50x11-common_determine-startup

55gnome-session_gnomerc

60seahorse

60xdg-user-dirs-update

80im-switch

90-console-kit

90x11-common_ssh-agent

99x11-common_start


每个文件名都以数字开头,这主要是为了确保这些脚本的执行顺序,run-parts会将数字小的排在前面,这样就能确保以上文件能按数字由小到大的顺序执行。


120x11-common_process-args

这个文件主要是处理传给/etc/X11/xinit/ xinitrc脚本文件的参数的。该参数个数只能为0或一个,否则将不进行任何处理。如果该参数是failsafe,则该脚本将执行x-terminal-emulator,否则就执行该参数。需要说明的是,x-terminal-emulator是一个符号链接,指向/etc/alternatives/x-terminal-emulator,同时,/etc/alternatives/x-terminal-emulator也是一个符号链接,它指向/usr/bin/gnome-terminal.wrapper,而gnome-terminal.wrapper则是一个perl脚本,它最终是调用了gnome-terminal


230x11-common_xresources

该文件主要是调用xrdb来将/etc/X11/Xresources目录下及$HOME/.Xresources目录下的文件的内容来设置根窗口的屏幕 0 上的RESOURCE_MANAGER属性的内容。


340x11-common_xsessionrc

该文件主要是判断$HOME/.xsessionrc文件是否存在,如果存在则执行该脚本文件。


450x11-common_determine-startup

该文件主要先查看配置文件/etc/X11/Xsession.options中是否允许使用用户的xsession,如果/etc/X11/Xsession.options中存在allow-user-xsession字段,则查看$HOME/.xsession是否存在并有执行权限,如果是,则将STARTUP变量设置为该文件,如果没有执行权限就将STARTUP变量设置为“sh xsession文件”。如果此时STARTUP变量仍然为空,则将其设置为x-session-managerx-window-managerx-terminal-emulator。注意:这个STARTUP将会在后面的脚本中被启动。


555gnome-session_gnomerc

该文件会先得到STARTUPbasename,如:STARTUP=/usr/bin/x-session-manager,则其basenamex-session-manager。再判断该basename 是否为gnome-session,或者为x-session-manager并且x-session-manager是个符号链接,它指向/usr/bin/gnome-session,如果是则执行$HOME/.gnomerc(如果该文件存在并且可读)。


660seahorse

STARTUP重新赋值为“/usr/bin/seahorse-agent $STARTUP”,这个可能只是为安全考虑才这么做的,具体的我也不是很清楚,只是看了一下seahorse-agent的帮助,知道seahorse是一个GNOME的应用程序,它用于为用户的输入进行暂时的安全存储,而seahorse-agent则是seahorse的一个代理而已。


760xdg-user-dirs-update

xdg-user-dirs-update自动生成$HOME下的文件夹,该命令主要是根据/etc/xdg/user-dirs.defaults文件的内容来为用户创建文件夹的。


880im-switch

该文件主要用于设置输入法。具体的请自己参考文件内容。


990-console-kit

如果环境变量$XDG_SESSION_COOKIE为空,并且/usr/bin/ck-launch-session可执行,则将STARTUP重新赋值为” /usr/bin/ck-launch-session $STARTUP”。至于ck-launch-session的功能,我也不是很清楚,估计是和session有关。


1090x11-common_ssh-agent

该文件主要先查看配置文件/etc/X11/Xsession.options中是否使用ssh agent,如果/etc/X11/Xsession.options中存在use-ssh-agent字段,则判断/usr/bin/ssh-agent是否可执行,并且环境变量$SSH_AUTH_SOCK$SSH2_AUTH_SOCK是否都为空,如果是,这将STARTUP重新赋值为” /usr/bin/ssh-agent $STARTUP”


1199x11-common_start

它仅仅是用exec启动$STARTUP。关于exec,在Bourne shell中,它与fork的区别就在于它执行一个新的脚本不需创建sub-shell,而它与SourceDot的区别就在与在这条语句后面的语句将不会再被执行。此时,我们可以发现变量$STARTUP的值为:“startup=/usr/bin/ssh-agent /usr/bin/ck-launch-session /usr/bin/seahorse-agent --execute x-session-manager”, 因此,最终将会被执行的就是这么一条语句。而x-session-managerUbuntu8.04中仅仅是个符号链接,它最终指向的是gnome-session

gnome-session则是启动GNOME桌面环境的,这个程序一般被登入管理器gdmxdm和脚本startx调用。(gnome-session如何启动桌面,待研究)



4startx启动过程小结

综上所述,startx的默认启动过程为:startx调用并将系统文件/etc/X11/xinit/xinitrc /etc/X11/xinit/xserverrc 作为参数传给xinitxinit就会先执行系统文件/etc/X11/xinit/xserverrc以启动X Server,然后执行/etc/X11/xinit/xinitrc,而xinitrc则会执行脚本/etc/X11/Xsession,而Xsession则会按顺序调用执行/etc/X11/Xsession.d目录下的文件,从而最终调用了gnome-session这个用于启动GNOME桌面环境的程序。