LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1051|回复: 4

Linux下XWindow系统启动脚本分析

[复制链接]
发表于 2006-3-21 17:33:32 | 显示全部楼层 |阅读模式
关键词: Linux    XWindow    启动    xinit    startx                                          

本文论述基于如下环境:
Debian版本为:Debian GNU/Linux 3.1
Linux内核版本为:2.6.15.6
中文输入法:fcitx
本文参考:man手册里的Xsession(5)

安装了Linux后当然希望能进入XWindow,象在Windows一样方便地工作,于是大家都可能用过startx命令,也可能是直接在XWindow登录界面进入XWindow.
这两种方式的XWindow启动过程有没有区别呢?如果你没有做过个性化设置可能体会不到,但如果你设置过中文输入法,不管是用SCIM还是fcitx,可能都有过设置输入法为随XWindow启动的经验。
朋友们开始修改各种启动脚本,经常可能会修改到的方法有:

  1. 1、修改/etc/X11/xinit/xinitrc
  2. 2、修改/etc/X11/Xsession
  3. 3、在/etc/X11/Xsession.d目录下增加一个自定义的脚本
  4. 4、修改$HOME/.xsession
  5. 5、修改$HOME/.xinitrc
  6. 6、修改/etc/X11/xdm/Xsession
  7. ……
复制代码

总之,看起来是八仙过海各有各的神通了。这些方法有没有不同?为什么有时候明明设置好了,startx起来可以用了,但重启在XWindow管理界面登录后却不能用了?为什么有时从XWindow管理界面登录后可用,但startx后却用不了?
下面我们一起来分析一下吧。
关于本文档:
/*********************************************************************
*filename: Debian Linux下XWindow系统启动脚本分析
*purpose: XWindow启动过程研究
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2006-03-20 23:22:00
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*********************************************************************/
先看一下/etc/X11/Xsession脚本文件内容,原文内容如下:

  1. #!/bin/sh
  2. #
  3. # /etc/X11/Xsession
  4. #
  5. # global Xsession file -- used by display managers and xinit (startx)

  6. # $Id: Xsession 2186 2005-02-11 07:11:05Z branden $

  7. set -e

  8. PROGNAME=Xsession

  9. message () {
  10.   # pretty-print messages of arbitrary length; use xmessage if it
  11.   # is available and $DISPLAY is set
  12.   MESSAGE="$PROGNAME: $*"
  13.   echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2
  14.   if [ -n "$DISPLAY" ] && which xmessage > /dev/null 2>&1; then
  15.     echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file -
  16.   fi
  17. }

  18. message_nonl () {
  19.   # pretty-print messages of arbitrary length (no trailing newline); use
  20.   # xmessage if it is available and $DISPLAY is set
  21.   MESSAGE="$PROGNAME: $*"
  22.   echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2;
  23.   if [ -n "$DISPLAY" ] && which xmessage > /dev/null 2>&1; then
  24.     echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file -
  25.   fi
  26. }

  27. errormsg () {
  28.   # exit script with error
  29.   message "$*"
  30.   exit 1
  31. }

  32. internal_errormsg () {
  33.   # exit script with error; essentially a "THIS SHOULD NEVER HAPPEN" message
  34.   # One big call to message() for the sake of xmessage; if we had two then
  35.   # the user would have dismissed the error we want reported before seeing the
  36.   # request to report it.
  37.   errormsg "$*" \
  38.            "Please report the installed version of the "xfree86-common"" \
  39.            "package and the complete text of this error message to" \
  40.            "<debian-x@lists.debian.org>."
  41. }

  42. # initialize variables for use by all session scripts

  43. OPTIONFILE=/etc/X11/Xsession.options

  44. SYSRESOURCES=/etc/X11/Xresources
  45. USRRESOURCES=$HOME/.Xresources

  46. SYSSESSIONDIR=/etc/X11/Xsession.d
  47. USERXSESSION=$HOME/.xsession
  48. ALTUSERXSESSION=$HOME/.Xsession
  49. ERRFILE=$HOME/.xsession-errors

  50. # attempt to create an error file; abort if we cannot
  51. if touch "$ERRFILE" 2> /dev/null && [ -w "$ERRFILE" ] &&
  52.   [ ! -L "$ERRFILE" ]; then
  53.   chmod 600 "$ERRFILE"
  54. elif ERRFILE=$(tempfile 2> /dev/null); then
  55.   if ! ln -sf "$ERRFILE" "${TMPDIR:=/tmp}/xsession-$USER"; then
  56.     message "warning: unable to symlink "$TMPDIR/xsession-$USER" to" \
  57.              ""$ERRFILE"; look for session log/errors in" \
  58.              ""$TMPDIR/xsession-$USER"."
  59.   fi
  60. else
  61.   errormsg "unable to create X session log/error file; aborting."
  62. fi

  63. exec >>"$ERRFILE" 2>&1

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

  65. # sanity check; is our session script directory present?
  66. if [ ! -d "$SYSSESSIONDIR" ]; then
  67.   errormsg "no "$SYSSESSIONDIR" directory found; aborting."
  68. fi

  69. # Attempt to create a file of non-zero length in /tmp; a full filesystem can
  70. # cause mysterious X session failures.  We do not use touch, :, or test -w
  71. # because they won't actually create a file with contents.  We also let standard
  72. # error from tempfile and echo go to the error file to aid the user in
  73. # determining what went wrong.
  74. WRITE_TEST=$(tempfile)
  75. if ! echo "*" >>"$WRITE_TEST"; then
  76.   message "warning: unable to write to ${WRITE_TEST%/*}; X session may exit" \
  77.           "with an error"
  78. fi
  79. rm -f "$WRITE_TEST"

  80. # Use run-parts to source every file in the session directory; we source
  81. # instead of executing so that the variables and functions defined above
  82. # are available to the scripts, and so that they can pass variables to each
  83. # other.
  84. SESSIONFILES=$(run-parts --list $SYSSESSIONDIR)
  85. if [ -n "$SESSIONFILES" ]; then
  86.   for SESSIONFILE in $SESSIONFILES; do
  87.     . $SESSIONFILE
  88.   done
  89. fi

  90. exit 0
复制代码

此文件的第五行“# global Xsession file -- used by display managers and xinit (startx)”已经说明/etc/X11/Xsession脚本是大家公用的,无论你是用XWindow管理器(比如kdm、gdm、xdm)进入还是通过命令行输入startx(即xinit方式)进入XWindow,都会调用此脚本程序。
再看看这个脚本程序做了些什么吧。
这一行“SYSSESSIONDIR=/etc/X11/Xsession.d”定义了一个变量指向了目录/etc/X11/Xsession.d,后面又出现一段代码:

  1. SESSIONFILES=$(run-parts --list $SYSSESSIONDIR)
  2. if [ -n "$SESSIONFILES" ]; then
  3.   for SESSIONFILE in $SESSIONFILES; do
  4.     . $SESSIONFILE
  5.   done
  6. fi
复制代码

显然这里是搜索了目录/etc/X11/Xsession.d里面所有的脚本并一一执行完毕。
同时请注意有这么两行:

  1. USERXSESSION=$HOME/.xsession
  2. ALTUSERXSESSION=$HOME/.Xsession
复制代码

在这里并没有看到使用这两个变量,那么在这个脚本里定义来做什么?
下面再看一下脚本/etc/X11/Xsession.d/50xfree86-common_determine-startup里的内容,原文如下:

  1. # $Id: 50xfree86-common_determine-startup 1437 2004-05-23 03:18:32Z branden $

  2. # This file is sourced by Xsession(5), not executed.

  3. # If no X session startup program was passed to the Xsession script as an
  4. # argument (e.g., by the display manager), or if that program was not
  5. # executable, fall back to looking for a user's custom X session script, if
  6. # allowed by the options file.
  7. if [ -z "$STARTUP" ]; then
  8.   if grep -qs ^allow-user-xsession "$OPTIONFILE"; then
  9.     for STARTUPFILE in "$USERXSESSION" "$ALTUSERXSESSION"; do
  10.       if [ -e "$STARTUPFILE" ]; then
  11.         if [ -x "$STARTUPFILE" ]; then
  12.           STARTUP="$STARTUPFILE"
  13.         else
  14.           STARTUP="sh $STARTUPFILE"
  15.         fi
  16.         break
  17.       fi
  18.     done
  19.   fi
  20. fi

  21. # If there is still nothing to use for a startup program, try the system
  22. # default session manager, window manager, and terminal emulator.
  23. if [ -z "$STARTUP" ]; then
  24.   if [ -x /usr/bin/x-session-manager ]; then
  25.     STARTUP=x-session-manager
  26.   elif [ -x /usr/bin/x-window-manager ]; then
  27.     STARTUP=x-window-manager
  28.   elif [ -x /usr/bin/x-terminal-emulator ]; then
  29.     STARTUP=x-terminal-emulator
  30.   fi
  31. fi

  32. # If we still have not found a startup program, give up.
  33. if [ -z "$STARTUP" ]; then
  34.   ERRMSG="unable to start X session ---"
  35.   if grep -qs ^allow-user-xsession "$OPTIONFILE"; then
  36.     ERRMSG="$ERRMSG no "$USERXSESSION" file, no "$ALTUSERXSESSION" file,"
  37.   fi
  38.   errormsg "$ERRMSG no session managers, no window managers, and no terminal" \
  39.            "emulators found; aborting."
  40. fi

  41. # vim:set ai et sts=2 sw=2 tw=80:
复制代码

这一行“# This file is sourced by Xsession(5), not executed.”证明脚本是被之前的/etc/X11/Xsession调用的,而后面这一段:

  1.    for STARTUPFILE in "$USERXSESSION" "$ALTUSERXSESSION"; do
  2.       if [ -e "$STARTUPFILE" ]; then
  3.         if [ -x "$STARTUPFILE" ]; then
  4.           STARTUP="$STARTUPFILE"
  5.         else
  6.           STARTUP="sh $STARTUPFILE"
  7.         fi
  8.         break
  9.       fi
  10.     done
复制代码

更证明了这一点。在这里脚本搜索用户目录$HOME下的.xsession或.Xsession脚本来执行。
(在/etc/X11/Xsession.d目录下还有一些脚本,这里就不再分析了,各位有兴趣可以自己看看)
另外来看看/etc/X11/xinit/xinitrc这个脚本,其原文内容如下:

  1. ##!/bin/sh
  2. ## $Xorg: xinitrc.cpp,v 1.3 2000/08/17 19:54:30 cpqbld Exp $
  3. #
  4. ## /etc/X11/xinit/xinitrc
  5. ##
  6. ## global xinitrc file, used by all X sessions started by xinit (startx)
  7. #
  8. ## invoke global X session script

  9. . /etc/X11/Xsession
复制代码

注意这一句“## global xinitrc file, used by all X sessions started by xinit (startx)”,这说明这个脚本只被xinit调用(即用户输入startx时)。而其执行的最后还是执行了/etc/X11/Xsession脚本。而用户如果用其它XWindow管理界面登录系统时这个脚本里的内容是不会被执行的。
最后再来看看/etc/X11/xdm/Xsession这个脚本吧,其原文内容如下:

  1. #!/bin/sh
  2. #
  3. # $Xorg: Xsession,v 1.4 2000/08/17 19:54:17 cpqbld Exp $
  4. #
  5. #
  6. #
  7. #
  8. # $XFree86: xc/programs/xdm/config/Xsession,v 1.3 2001/01/17 23:45:24 dawes Exp $

  9. # invoke global X session script

  10. . /etc/X11/Xsession
复制代码

从内容来看,也是最终执行了/etc/X11/Xsession。

再看看/etc/X11里面的目录结构:

  1. X             Xsession.d        cursors                  gdm        rstart     xinit
  2. XF86Config-4  Xsession.options  default-display-manager  lbxproxy   sysconfig  xkb
  3. Xresources    Xwrapper.config   fonts                    proxymngr  twm        xserver
  4. Xsession      app-defaults      fs                       rgb.txt    xdm        xsm
复制代码

显然,这里把xinit和xdm、twm及gdm是分开的,在xinit里执行的脚本是不会被xdm里的脚本调用的。

从上面对代码的分析,大家可以看到:其实XWindow执行的关键脚本是/etc/X11/Xsession,这个脚本会去 /etc/X11/Xsession.d目录里搜索脚本执行,也会去$HOME/下搜索脚本运行,而其它目录xinit、xdm等里面的脚本都会去调用 /etc/X11/Xsession这个脚本。
所以,如果你想把中文输入法fcitx、SCIM等设置成随Xwindow启动,比如要加入如下脚本:

  1. export LC_CTYPE=zh_CN.GBK
  2. export XMODIFIERS="@im=fcitx"
  3. export XIM=fcitx
  4. export XIM_PROGRAM=fcitx
  5. fcitx
复制代码

那么可以用如下几种方法:

  1. 1、加到/etc/X11/Xsession。这种方法对所有启动方法都管理
  2. 2、在/etc/X11/Xsession.d目录里自己写一个脚本。这种方法也对所有启动方法都管理
  3. 3、在$HOME目录下生成.xsession或.Xsession脚本。这种方法也对当前登录用户有效
  4. 4、加到/etc/X11/xinit/xinitrc脚本里。这个方法只对xinit方式(即命令行输入startx)管用。
  5. 5、加到/etc/X11/xdm/xsession脚本里,只对用xdm管理界面登录的方式管用。
复制代码

另外,关于如何设置中文输入法,请参看我的文章《Linux中中文输入法随XWindow启动的问题》,还有设置中文字体的应用,可以参见我的文章《在Linux里使用Windows的TrueType字体》。
大家习惯了在Linux下生活了吗?是否遇到过听歌没声音的情况?看看《Linux下/dev/dsp设备文件的作用》吧
发表于 2006-3-21 18:11:37 | 显示全部楼层
鼓励原创。加精。
回复 支持 反对

使用道具 举报

发表于 2006-3-21 19:06:13 | 显示全部楼层
怎么有似曾相识的感觉???

好象以前在哪里看到过??? 希望我感觉错了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-3-21 20:04:46 | 显示全部楼层
多谢版主鼓励!我一定努力,再接再励!

似曾相识是因为这些代码都是在/etc目录下存在的,谁都可能是见过的:)
回复 支持 反对

使用道具 举报

发表于 2006-3-22 03:10:04 | 显示全部楼层
哥们+u 写的很详细,值得学习
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表