3. 运行 X

启动一个 X 会话通常有两种方式:X 会话通过显示管理器(如 xdm)启动,用户在 GUI 界面登录。或者,用户在登录到文本控制台后手动启动 X。后者通常使用 startx 命令完成,这是一个简单的 xinit shell 脚本封装器。X 在这两种情况下都以 root 权限运行,因为它需要原始访问硬件设备的权限。

通常,使用哪种方法取决于系统“运行级别”。启动时要启动的默认运行级别通常在以下文件中设置:/etc/inittab在 Linux 上

 # Run xdm in runlevel 5
 x:5:respawn:/etc/X11/xdm -nodaemon

 

这将在运行级别 5 启动 xdm,从而启动 X。如果它因任何原因终止或停止,它将“respawn”(重新生成)。您还可以使用 init 命令来更改运行级别,而无需重启(请参阅 man page)。

让我们简要地看一下这两种方法,然后再看一些额外的配置,以设置用户的工作环境。

3.1. startx

startx 将首先调用 xinit 来启动 X。单独使用它,会将您置于一个空白、模糊的、基本桌面,而没有加载窗口管理器。xinit 基本上接受两组命令行参数:客户端规范(要运行的程序等)和服务端规范(X 服务器选项),用 “--” 分隔。如果在命令行上没有指定客户端程序,xinit 将查找一个.xinitrc文件,在用户的主目录中,作为 shell 脚本运行。如果找到,它将依次运行用户指定的任何命令来设置环境,或启动该文件包含的程序。如果此文件不存在,xinit 将使用以下初始命令

 
 xterm -geometry +1+1 -n login -display :0
 
 

如果没有.xserverrc在用户的主目录中找到,X 本身将使用以下命令启动

 X :0

 

如您所见,这并没有太大的帮助,因为它只是启动了一个 xtermstartx shell 封装器为 xinit 提供了额外的功能和灵活性。startx 将为我们调用 xinit,并提供一些简单的配置选项。您还可以发出如下命令,例如

 
 startx -- -dpi 100 -depth 16   #force X to 100 dots per inch
                                #and colordepth of 16 (X v4 syntax)
 
 

双破折号后的任何内容都作为参数直接通过 xinit 传递给 X 服务器。在本例中,您可以强制 X 使用您偏好的分辨率,并且仍然可以使用我们将在本文档后面介绍的配置文件。有关更多命令行选项,请参阅 Xserver man page。

与其每次都发出相同的命令行,不如使用配置文件来为我们存储此类信息更容易。

如果您查看 startx 脚本(/usr/X11R6/bin/startx在我的系统上),您会看到它使用两个默认配置文件来帮助设置 X 环境xinitrcxserverrc。它首先在/etc/X11/xinit/中查找系统范围的文件。然后,它检查用户的主目录中是否有类似的文件,如果找到,这些文件将优先。请注意,后者是 Unix 风格的“点”文件(例如~/.xinitrc),并且是可执行的 shell 脚本。

您通常不希望编辑系统范围的文件,但是您可以自由地将这些文件复制到您的主目录作为起点,或者从头开始。正如您从名称中可以看出的那样,一个文件帮助设置 X 服务器,另一个文件通过执行命令、准备环境并可能启动客户端程序(如 xterm 或窗口管理器)来设置 xinit(是的,它也是一个客户端)。

3.1.1. xserverrc

与所有 XFree86 配置文件一样,这是一个纯文本文件,通常是一个简单的单行语句,用于启动 X 服务器。它可以包含您的 X 安装支持的任何有效命令行选项。如果您始终使用自己的选项启动 X,这将比每次都键入选项更容易。一个可能的~/.xserverrc:

 exec X :0 -dpi 100 -nolisten tcp

 

这将在显示器 :0(第一个“显示器”)上以每英寸 100 点的分辨率启动 X,并禁用 TCP 连接。有关其他有效选项,请参阅 Xserver man page。这只是一个例子。

3.1.2. xinitrc

xinitrc用于设置合适的 X 环境,并启动其他程序,也称为 “客户端”,我们可能希望在 X 启动后立即可用。您可能有一个系统范围的xinitrc用于启动一组预定义的程序。要自定义此设置,请在您的主目录中创建您自己的文件。将其命名为.xinitrc,确保它是一个可执行脚本,并使用 chmod +x。一个例子(略微修改自我系统上的原始文件)

#!/bin/sh
# $XConsortium: xinitrc.cpp,v 1.4 91/08/22 11:41:34 rws Exp $

userresources=$HOME/.Xresources
usermodmap=$HOME/.Xmodmap

# merge in defaults and keymaps
if [ -f $userresources ]; then
    xrdb -merge $userresources
fi

if [ -f $usermodmap ]; then
    xmodmap $usermodmap
fi

if [ -z "$BROWSER" ] ; then
	# we need to find a browser on this system
	BROWSER=`which netscape`
	if [ -z "$BROWSER" ] || [ ! -e "$BROWSER" ] ; then
	# not found yet
		BROWSER=
	fi
fi
if [ -z "$BROWSER" ] ; then
	# we need to find a browser on this system
	BROWSER=`which lynx`
	if [ -z "$BROWSER" ] || [ ! -e "$BROWSER" ] ; then
	# not found yet
		BROWSER=
	else
		BROWSER="xterm -font 9x15 -e lynx"
	fi
fi

export BROWSER

# start some nice programs
if [ -f $HOME/.Xclients ]; then
    exec $HOME/.Xclients
else
    xclock -geometry 50x50-1+1 &
    xterm -geometry 80x50+494+51 &
    if [ -f /usr/X11R6/bin/fvwm ]; then
        exec fvwm
    else
        exec twm
    fi
fi

#eof

 

简而言之,此脚本的作用是使用 xmodmap(键盘)和 xrdb(应用程序资源设置)来设置我们的工作环境。下面将详细介绍这些。然后是 shell 变量$BROWSER为 GUI 环境(本例中为 Netscape)设置,以便任何可能期望此设置的应用程序都有一个合理的选择。然后是文件Xclients的存在性被检查,包括作为系统范围的文件和用户主目录中的文件。在这个特定的例子中,这是启动任何客户端应用程序的地方,包括窗口管理器(见下文)。如果我们愿意,这些应用程序也可以很容易地在这里启动。如果Xclients文件找不到,那么将为我们启动一个窗口管理器。如果 fvwm 可用,则启动它,否则启动 XFree86 的极简 twm。如果由于某种原因,这两个都无法启动,脚本将退出,并且 X 将无法启动。

3.1.3. Xclients

到目前为止,一切都遵循了一个相当标准和可预测的事件序列。总结一下,我们调用了 startx,它又调用了 xinit,后者解析了xinitrc以获取初始设置。大多数 Linux 系统都应遵循此相同的序列,尽管各种值和设置可能会有所不同。

我们现在处于链条的最后一环,用户通常会在其中指定他或她的偏好,包括要使用的窗口管理器和/或桌面环境。如果用户没有这样做,系统将提供合理但可能不那么有趣的默认设置。想必,这就是您来这里的原因 ;-)

窗口管理器或桌面环境通常是最后一个启动的应用程序。如果您希望启动其他程序(如 xterm),则应在窗口管理器之前启动它们,并使用 “&” 将其“backgrounded”(后台运行)。这一切都可以在用户的~/.xinitrc中完成。或者,如上面的示例所示,实际的应用程序是从另一个脚本启动的。让我们看一个简短的、假设的此类脚本,.Xclients:

 
#!/bin/bash
# ~/.Xclients, start my programs.

xset s off s noblank
xset m 30/10 4
xset r rate 200 40

xscreensaver & 
rxvt -geometry 80x50-50+150 &

echo Starting Window Manager...

if [ -x /usr/X11R6/bin/wmaker ]; then
  echo `date`: Trying /usr/X11R6/bin/wmaker... |tee -a ~/.wm-errors 2>&1
  exec /usr/X11R6/bin/wmaker >> ~/.wm-errors 2>&1
fi 

echo `date`: Failed, trying fvwm... |tee -a ~/.wm-errors 2>&1

# let's try regular fvwm (AnotherLevel doesn't work with fvwm1).
if [ -n "$(type -path fvwm)" ]; then
  # if this works, we stop here
  exec fvwm >> ~/.wm-errors 2>&1
fi

echo `date`: Failed, trying twm... |tee -a ~/.wm-errors 2>&1

# wow, fvwm isn't here either ... 
# use twm as a last resort.
exec twm >> ~/.wm-errors 2>&1

# Dead in the water here, X will exit as well, sigh...
echo `date`: Unable to start a Window Manager ... |tee -a ~/.wm-errors 2>&1

# eof

 

这与xinitrc所做的并没有太大的不同。我们添加了一些细节,包括启动屏幕保护程序、用户首选的不同终端模拟器 (rxvt),这次使用 xset 进行了更多的环境设置(显示器、鼠标和键盘),以及与系统默认设置提供的窗口管理器不同的窗口管理器。这在用户的主目录中,因此在升级期间也不会被覆盖。

实际上,X 此时已经启动,我们只是在对配置进行最后的润色。请注意,窗口管理器在这里没有用 “&” “backgrounded”。这很重要!必须有东西在前台运行,否则 X 将退出。在本例中,我们没有启动桌面环境,如 KDEGNOME,但如果我们启动了,则最后一个应用程序必须是 gnome-sessionstartkde。由于我们在这里是自己配置,如果我们想更改窗口管理器,我们所要做的就是编辑此文件,然后重启 X。供应商提供的配置可能比这更复杂,但基本原理是相同的。

作为后记,不要认为任何初始客户端应用程序必须像我们在这里所做的那样启动。这是传统的做法,有些人可能更喜欢这种方法。大多数窗口管理器都有自己的内置方法来启动初始程序,KDEGNOME 也是如此。请参阅各自的文档。

3.2. 显示管理器

另一种更常见的方法是 “GUI 登录”,其中 X 在登录之前运行。这是在 “显示管理器” 的帮助下完成的,显示管理器有各种实现。XFree86 为此目的包括 xdm (X Display Manager),尽管您的发行版可能使用其他显示管理器之一,如 gdm (GNOME) 或 kdm (KDE)。

显示管理器实际上不仅仅是启用 GUI 风格的登录。它们还用于管理网络上的本地以及远程“显示器”。我们在此不深入讨论细节,但在 Remote X Apps Mini HOWTOXDMCP HOWTO 中对此进行了很好的介绍(请参阅 链接部分)。就我们这里的目的而言,它们提供类似于 gettylogin 的服务,这些服务允许用户登录到系统并启动其默认 shell,但在 GUI 环境中。

这是一个来自 Diego Zamboni 的示例,说明显示管理器还可以用于哪些更高级的用途

我有两个 X 会话以不同的分辨率运行。我根据我的笔记本电脑是连接到外部显示器还是使用其自身的 LCD 显示器在它们之间切换。

这是我的/usr/lib/X11/xdm/Xservers文件,用于启动两个显示器

 :1 local /usr/X11R6/bin/X :1 -layout 1024x768
 :0 local /usr/X11R6/bin/X :0 -layout 1600x1200

 

然后我在我的/etc/X11/XF86Config-4中将 “1024x768”“1600x1200” 定义为 “服务器布局”,如下所示

 Section "ServerLayout"
         Identifier     "1600x1200"
         Screen         "Screen0" 0 0
         InputDevice    "Mouse0" "CorePointer"
         InputDevice    "Keyboard0" "CoreKeyboard"
 EndSection
 
 Section "ServerLayout"
         Identifier     "1024x768"
         Screen         "Screen1" 0 0
         InputDevice    "Mouse0" "CorePointer"
         InputDevice    "Keyboard0" "CoreKeyboard"
 EndSection
 
 ## snip ...
 
 Section "Screen"
         Identifier   "Screen0"
         Device       "S3 Savage/MX"
         Monitor      "Monitor0"
         DefaultDepth 16
         
         Subsection "Display"
                 Depth  16
                 Modes  "1600x1200" "1280x1024" "1024x768"
         EndSubsection
 EndSection
 
 Section "Screen"
         Identifier   "Screen1"
         Device       "S3 Savage/MX"
         Monitor      "Monitor0"
         DefaultDepth 16

         Subsection "Display"
                 Depth  16
                 Modes  "1024x768" "800x600"
         EndSubsection
 EndSection

 

请注意此处 “Identifiers” 的使用。Diego 在这里启动了两个单独的 “显示器”。然后他可以在登录时选择他想要的一个。

大多数显示管理器都派生自 XFree86 著名的 xdm,并添加了自己的增强功能。让我们简要地看一下最流行的几个。

3.2.1. xdm

xdm 可以使用位于以下位置的配置文件进行配置/etc/X11/xdm/, /usr/X11R6/lib/X11/xdm或类似位置,具体取决于您的系统。这些是系统范围的文件。文件xdm-config是主配置文件,主要描述在哪里可以找到辅助配置文件

 ! $XConsortium: xdm-conf.cpp /main/3 1996/01/15 15:17:26 gildea $
 DisplayManager.errorLogFile:	/var/log/xdm-errors
 DisplayManager.servers:		/etc/X11/xdm/Xservers
 DisplayManager.accessFile:	/etc/X11/xdm/Xaccess
 ! All displays should use authorization, but we cannot be sure
 ! X terminals will be configured that way, so by default
 ! use authorization only for local displays :0, :1, etc.
 DisplayManager._0.authorize:	true
 DisplayManager._1.authorize:	true
 ! The following three resources set up display :0 as the console.
 DisplayManager._0.setup:	/etc/X11/xdm/Xsetup_0
 DisplayManager._0.startup:	/etc/X11/xdm/GiveConsole
 DisplayManager._0.reset:	/etc/X11/xdm/TakeConsole
 !
 DisplayManager*resources:	/etc/X11/xdm/Xresources
 DisplayManager*session:		/etc/X11/xdm/Xsession
 !
 ! SECURITY: do not listen for XDMCP or Chooser requests
 ! Comment out this line if you want to manage X terminals with xdm
 DisplayManager.requestPort:	0

 

“!” 表示注释。启动 X 服务器的命令在/etc/X11/xdm/Xservers中,在本例中由 “DisplayManager.servers” 定义,并且等同于xserverrc用于 startx X 服务器启动命令的命令,但这里的语法略有不同。

的内容/etc/X11/xdm/Xservers在我的系统上只是

 :0 local /usr/X11R6/bin/X 

 

这会在第一个本地显示器(由 0 指定)上启动 X。您要添加的任何特殊命令行参数都放在末尾。

下面是一个示例/etc/X11/xdm/Xsetup_0,它仅用于配置登录屏幕。请注意,我们在这里使用 shell 脚本,它调用 xv(一个图形显示程序)将背景设置为漂亮的图像(而不是无聊的黑白背景图案),如果失败,则调用 xsetroot 至少尝试将背景设置为更漂亮的蓝色。这不配置登录小部件本身 - 只是登录期间可能需要在屏幕上的其他内容。

 
 #!/bin/sh
 xconsole -geometry 480x100-0-0 -daemon -notify -verbose -fn \
   '-schumacher-clean-medium-r-*-*-10-*-*-*-*-*-*-*' -exitOnFail  &
 
 /usr/X11R6/bin/xv -quit -root /usr/share/pixmaps/Backgrounds/InDreams.jpg \
   || xsetroot -solid darkblue
 
 

/etc/X11/xdm/Xresources控制登录期间使用的 X “资源”。在此上下文中,“资源”是用户对字体和颜色等项目的偏好(在下面更详细地描述)。下面是设置登录小部件字体的代码片段

 #if WIDTH > 800
 xlogin*greetFont: -adobe-helvetica-bold-o-normal--24-240-75-75-p-138-iso8859-1
 xlogin*font: -adobe-helvetica-medium-r-normal--18-180-75-75-p-103-iso8859-1
 xlogin*promptFont: -adobe-helvetica-bold-r-normal--18-180-75-75-p-103-iso8859-1
 xlogin*failFont: -adobe-helvetica-bold-r-normal--18-180-75-75-p-103-iso8859-1
 #else
 xlogin*greetFont: -adobe-helvetica-bold-o-normal--17-120-100-100-p-92-iso8859-1
 xlogin*font: -adobe-helvetica-medium-r-normal--12-120-75-75-p-69-iso8859-1
 xlogin*promptFont: -adobe-helvetica-bold-r-normal--12-120-75-75-p-69-iso8859-1
 xlogin*failFont: -adobe-helvetica-bold-o-normal--14-140-75-75-p-82-iso8859-1
 #endif

 

如您所见,这使用 helvetica 作为首选字体,具有不同的磅值大小和每英寸点数,具体取决于屏幕尺寸。这是可定制的,以满足个人需求。(有关理解 X 字体命名约定的更多信息,请参见下文。)其他各个方面也可以类似地配置。

/etc/X11/xdm/Xsession大致等同于xinitrc对于 startx。它将类似地为键盘等设置默认环境。并且还可以启动 KDEGNOME 以及其他 X 客户端程序。这是系统范围的配置文件。它还应检查用户的主目录中是否有~/.xsession,以及可能的~/.Xclients,它将包含用户首选的环境和启动程序,就像~/.xinitrc使用 startx 所做的那样。同样,用户主目录中的文件可以由用户随时创建或修改,并且必须是可执行的 shell 脚本。

我们不包含一个~/.xsession示例,因为它与~/.xinitrc~/.Xclients上面的示例非常相似。

我们只是简要地查看了主要的 xdm 配置文件。请务必阅读 man page,并查看本地安装的内容以获取更多信息。现在让我们看一下 gdmkdm。我们将只强调显着差异,因为它们本质上提供相同的功能。

3.2.2. gdm

gdmGNOME 的默认显示管理器。gdm 是从头开始编写的,但功能类似于 xdm。主配置文件是gdm.conf,通常位于/etc/X11/gdm/gdm.conf。这与xdm-config看起来大不相同。

注释用 “#” 表示,文件有 sections(节),节标题用方括号括起来。启动 X 的命令在 “[servers]” 节中

 [servers]
 0=/usr/bin/X11/X
 #1=/usr/bin/X11/X

 

请注意,这可能设置了两个显示器,但第二个显示器被注释掉了。在此处添加任何其他 X 启动选项,例如 “-dpi 100”。登录屏幕和登录小部件在 “[greeter]” 节中配置。

启动客户端和程序由 “[daemon]” 节中的 “SessionDir” 语句确定。在我的安装中,这指向/etc/X11/gdm/Sessions/,其中包含几个简短的脚本。如果我看一下我的Default脚本,它实际上执行/etc/X11/xdm/Xsession,这反过来会执行~/.xsession,如果存在。因此,在最后阶段,gdm 的行为非常像 xdm

GNOME 包含 gdmconfig 实用程序,用于控制 gdm 行为的许多方面。

3.2.3. kdm

kdm 是来自 KDE 的显示管理器。kdm 的主配置文件是kdmrc,通常安装为/etc/kde/kdm/kdmrc。与gdm.conf, kdmrc的情况一样,

使用 “#” 进行注释,并且具有 sections(节),节标题位于类似的方括号中。kdm 配置也可以使用 kcontrol 实用程序进行编辑。

可见桌面在 “[Desktop*]” section(s) 中配置,并通过 “Setup” 指令配置,该指令应指向类似的文件/usr/share/config/kdm/Xsetup/etc/X11/xdm/Xsetup_0。这将完成与 xdmXsetup_0相同的事情:即运行用户可能想要的任何程序,例如 xconsole

启动 X 服务器的命令是 “[General]” 中的 “Xservers” 指令。同样,这应指向类似的文件/etc/X11/xdm/Xservers,并使用与 xdm 相同的语法

 :0 local /usr/X11R6/bin/X 

 

X 服务器的任何命令行选项都放在这里。

登录小部件本身在 “[X-*-Greeter]” section(s) 中配置。如果用户未指定任何内容,则使用编译时默认值。

KDE 包含 kdmdesktop 实用程序,用于控制 kdm 行为的某些方面,主要只是登录背景。