BBS水木清华站∶精华区

 
 
                       Linux 开机程序之研讨(2) 
                                                        CCCA 资工86 许景华 
 
   在上次的介绍中 , 我们已经看完了 rc.S 及 rc.serial 这两个 shell script . 
   现在 , 我们将把剩下的 shell script 再作一个介绍 . 
   首先还是看看全部的流程 : 
 
 
            init[1] 
            rc.S   begin 
              rc.serial   begin 
              rc.serial   end 
            rc.S   end                  <-- 上一次我们说明到这里 
            init[1] enter runlevel 5 
            rc.M   begin 
              rc.inet1    begin 
              rc.inet1    end 
              rc.inet2    begin 
              rc.inet2    end 
              rc.font     begin 
              rc.font     end 
              rc.local    begin 
              rc.local    end 
            rc.M   end 
            login 
 
 
   这次主要的部份可分为两项 : 因为 init 将会去读取 inittab , 所以 inittab 
   将被列为第一部份的重点 , 而第二部份就是 rc.M , rc.font , rc.local 
   这几个 shell script 的说明 . ( rc.inet1 , rc.inet2 这两个关於网路的 
   shell script 将在以後单独说明 ) 
   好了 , 我们先从 inittab 看起吧 ! 看看上面的流程 , 在第一行 : init[1] 
   也就是 init 这个 process 被启动之後 , 它会去读取 /etc/inittab 这个档案 
   以完成系统的启动 . 从这里 , 我们看到了 LINUX 的确融合了 SVR4 及 SunOS 
   的一些特性 , inittab 这个档案 , 在 SunOS 系统中是不存在的 , 但是它却是 
   SVR4 典型的档案 . init 这个 process 会依据 /etc/inittab 中所记载的内容 
   进入不同的 run-level 并启动不同的 process . 所以 inittab 的重要性 
   可见一斑 . 那什麽叫 run-level 呢 ? 所谓 run-level 就是系统中定义了许多 
   不同的 level , 而系统会随著 level 的不同而去启动不同的资源 . 
   现在就让我们来看一下 /etc/inittab 中的内容 : 
   在 /etc/inittab 这个档案中 , 每一列是一个进入点 , 假如我们仔细观察每一列 
   的话 , 那我们就会很容易的发现 , /etc/inittab 的每一列可以被 " : " 这个 
   字元分成好几个栏位 . 这几个栏位的格式如下 : 
 
           id:runlevels:action:process 
 
   而它们代表的意义分别如下 : 
 
     id : 由两个独特的字元所组成的辨示符号 , 在比较新的 UNIX 系统中 , 已不 
          受只能有两个字元的限制 . 
 
     runlevels : 指出下面一个栏位中的 action 以及 下下个栏位中的 process 
                 会在那些 runlevel 中被执行 . 这一栏的合法值有 0,1,2...6 
                 s 以及 S . 而在正常的启动程序之後 , Superuser 可以使用 
                 telinit 这个指令来改变系统的 runlevel . 又因为在 LINUX 中 
                 , runlevel 的预设值是 5 ( 等一下就会看到 ) 所以 , 只有 
                 那些每一列中 runlevel 那栏有 5 这个值的 , 後面的 process 
                 才会被启动 . 所以 , 我们就可以想像的到 : " 由於系统的 
                 runlevel 不同 , 所起动的 process 也不尽相同 , 所以系统 
                 起动的资源在每个不同的 runlevel 就会有差异存在 . 
 
     action : 这个栏位有一点复杂 , 在这个栏位中记录著 init 在启动相对应的 
              process 时 , 对 process 所采取的动作 , 而合法的动作有下面几项: 
 
              initdefault : 指出系统在启动时 , 预设进入的 run-level 值 , 
                            比如说 , 我们可以在 /etc/inittab 中找到下面这 
                            一列 :  id:5:initdefault: 
                            很明显的 , 系统将在启动时 , 进入 runlevel 为 5 
                            的模式 . 当然 , 你可以把 5 改成 6 试试看 , 如 
                            果你改成了 6 , 那将会执行 /etc/rc.d/rc.6 , 也 
                            就是 run xdm . xdm 在以後有机会的话 , 将为各 
                            位介绍 ...... 
 
              sysinit : 在系统起动时 , 这个 process 会被执行 . 而所有 process 
                        前的 action 中有 boot 及 bootwait 的 process , 必 
                        须等到这些 action 为 sysinit 的 process 执行完之後 
                        它们才能够执行 . 
 
              wait : 在起动一个 process 之後 , 若要再起动另一个 process , 则 
                     必需等到这个 process 结束之後才能继续 . 
 
              respawn : 代表这个 process 即使在结束之後 , 也会重新被启动 , 
                        最典型的例子就是 getty ( 在 LINUX 中为 agetty ) . 
                        看看下面的循环 : 
 
                        --  getty --> login --> shell --> logout -- 
                        ^                                          | 
                        |------------------------------------------ 
 
                        即使在 getty 结束之後 , 它也会重新被启动 . 
 
              ctrlaltdel : 想必有人会以键盘上的 Ctrl , Alt , 及 Del 这三个 
                           键来达到使系统 shutdown 的目的 , 现在我们果然在 
                           /etc/inittab 中看到了这一列 : 
 
                              ca::ctrlaltdel:/sbin/shutdown -t3 -rf now 
 
                           所以说 , 当我们按下这三个键的时候 , init 会收到 
                           SIGINT 这个 signal , 接著就执行 shutdown 的动作 
                           不过 , 我们最好不要养成按 Ctrl-Alt-Del 来使系统 
                           shutdown 的习惯 , 尤其在单人多工的作业系统 , 像 
                           OS/2 , 甚至 Windows 95 , shutdown 几乎都是标准 
                           的关机程序了 , 更何况是多人多工的 LINUX , 所以 , 
                           shutdown 这个指令是一定要熟悉的 . 
 
              除了上面的几个 action 之外 , 另外还有一些合法的 action , 但这 
              些 action 并不需要太注意 , 要用的时候再利用 man init 去查询就 
              可以了 . 
 
     process : 这一栏中可以是 shell script 或是可执行的程式 . 
 
   好了 , 当我们了解 /etc/inittab 中每一栏的意义之後 , 要看懂 /etc/inittab 
   就是一件轻松愉快的工作了 . 在 /etc/inittab 档中 , 我们可以看到下面这一段 
 
     c1:12345:respawn:/sbin/agetty 38400 tty1 
     c2:12345:respawn:/sbin/agetty 38400 tty2 
     c3:45:respawn:/sbin/agetty 38400 tty3 
     c4:45:respawn:/sbin/agetty 38400 tty4 
     c5:45:respawn:/sbin/agetty 38400 tty5 
     c6:456:respawn:/sbin/agetty 38400 tty6 
 
   简单来说 , 系统在起动之後会制造出六个虚拟的 console . 我想大家应该有试过 
   用 Ctrl-Alt + F1 - F6 可在这六个 console 之间切换 ; 若你使用 XWindows 时 
   想暂时回到 console 下时 , 可用 Ctrl-Alt + F1 - F6 这三个键来选择 , 若想 
   回到 XWindows 下时 , 只要以 Ctrl-Alt-F7 就可以回到 XWindows 下了 . 基本 
   上 , 对於 memory 比较少的人 , 可以不要开那麽多的虚拟 console , 那麽就可 
   以去掉上面的几列 . 还有 , 在前面我们也提过 , 可以把预设的 runlevel 从 5 
   改成 6 , 对於 beginner 来说 , 系统一启动完就直接进入 XWindows 也许是一个 
   不错的设定方法 ...... 
 
   介绍完 /etc/inittab 之後 , 我们接著看 rc.M ! 由前面的流程当中 , 我们看到 
   rc.M 中又包含了四个 shell script , 其中 rc.inet1 及 rc.inet2 是有关於网路 
   的设定 ; rc.font 是作字型的设定 , 而 rc.local 中可以放一些想要起动的 
   daemon . 
 
   我们现在就来看看 rc.M , 依照往例 , 前面有两个 "#" 的为加上去的注解 . 
   只有一个 "#" 的为原来的注解 : 
 
#!/bin/sh 

# rc.M          This file is executed by init(8) when the system is being 
#               initialized for one of the "multi user" run levels (i.e. 
#               levels 1 through 6).  It usually does mounting of file 
#               systems et al. 

# Version:      @(#)/etc/rc.d/rc.M      2.02    02/26/93 

# Author:       Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> 
#               Heavily modified by Patrick Volkerding <volkerdi@ftp.cdrom.com> 

 
  ## 显示进入多人模式 
 
  echo "Going multiuser..." 
 
 
  ## 下面一列的意思是 : 假如你在文字模式的 console 下 , 在15分钟内都没有动作 
  ## 的话 , 萤幕就会自动暗下来 , 简单的说 , 就是 screen saver 的功能 . 
 
  /bin/setterm -blank 15 
 
 
  ## 执行 crond 这个 daemon . 不用说 , crond 在系统中扮演了很重要的角色 , 
  ## 它负责每过一段时间後 , 就去看看 /var/spool/cron/crontabs 中有那些 file 
  ## 要 run , 这些 file 往往有一个固定的时间 , 比如说 : 每个月的 1 号 , 每 
  ## 天凌晨等 ...... 我们可以用平常的编辑器编好一个档案 , 里面的格式如下 : 
  ## 
  ##                    分 时 日 月 星期 命令 
  ## 
  ## 举例来说 ,         59 23 31 12  *   /etc/wall happy_new_year 
  ## 在每年的 12 月 31 号晚上 11 点 59 分 会对每个系统上的 user 送出 
  ## happy_new_year 中的内容 
  ## 
  ## 接著我们可以利用 crontab <档案名> 这个指令来把此档案放到 
  ## /var/spool/cron/crontabs中□. 我们可以看看 /var/spool/cron/crontab 下 
  ## 有一个 root 的档案 , 看看里面的内容 : 
  ## 
  ##   0,5,10,15,20,25,30,35,40,45,50,55 * * * *       /usr/lib/atrun 
  ## 
  ## 所以各位看到了 , 在前两期提到的 at 命令是五分钟才被 run 一次的 
  ## 
  ## 再举一个简单的例子好了 : 我们先用一般的文书编辑器造出一个名为 crontest 
  ## 的档案 , 内容如下 : 
  ## 
  ##   5 * * * * ls -la ~/ >> ~/hehehaha 
  ## 
  ## 接著 , 我们键入下面的命令 :  crontab crontest 
  ## 此时 , 从内容得知 , 每五分钟 crond 就会执行 ls -la , 把你 home directory 
  ## 的内容加入 hehehaha 这个档案中 . 
  ## 
  ## 当然啦 ! 这个例子简直是毫无意义可言 :)  但是 , 大家既然知道了基本原理 , 
  ## 利用 crontab , at 这些指令 , 就可以简化一些系统管理的动作 , 同时在执行 
  ## 一些工作时 , 也会比较有弹性 . 
 
  /usr/sbin/crond -l10 >>/var/adm/cron 2>&1 
 
 
  ## 假如 /etc/HOSTNAME 不能读取的话 , 就把 darkstar.frop.org 当成 HOSTNAME 
  ## 中的内容 . 老实说 , 下面这三列去掉也不打紧 ...... 
 
  if [ ! -r /etc/HOSTNAME ]; then 
   echo "darkstar.frop.org" > /etc/HOSTNAME 
  fi 
 
 
  ## 下面从 if 到 fi 夹起来的部份 , 主要就是在执行 rc.inet1 , rc.inet2 . 这 
  ## 些都是网路设定的工作 , 尤其是 rc.inet2 , 启动了一大堆 daemon , 这部份 
  ## 要牵扯到的东西太多了 . 像 subnet 与 netmask 等 ...... 类似这种观念 , 
  ## 都不是三言两语就可以玩完的 , 所以就留待以後再说 . 
 
  if [ -x /etc/rc.d/rc.inet1 ]; 
  then 
        /bin/hostname `cat /etc/HOSTNAME | cut -f1 -d .` 
        /bin/sh /etc/rc.d/rc.inet1 
        /bin/sh /etc/rc.d/rc.inet2 
  else 
        /sbin/hostname_notcp `cat /etc/HOSTNAME | cut -f1 -d .` 
        /usr/sbin/syslogd 
        /usr/sbin/klogd 
        /usr/sbin/lpd 
  fi 
 
 
  ## 在某些资源独占的情况下 , 一些应用程式往往会制造出 lock 档 . 假如这些 
  ## lock 档在重新开机以後还是存在的话 , 那就很不好了 . 所以 , 下面就是在 
  ## 作这些删除 lock 档的动作 , 并把一些输出的讯息丢到 /dev/null 去 . 
  ## 在上一期的内容中 , 我们就有提到 /dev/null 了 , 也有提到抑制讯息输出的 
  ## 方法 . 现在我们果然看到了一个实例 ...... 
 
  /bin/rm -f /var/spool/locks/* /var/spool/uucp/LCK..* /tmp/.X*lock 1> /dev/null 2> /dev/null 
 
 
  ## 假如你有玩 hunt 这个 game 的话 , 那在 /tmp 下会有一个 socket 型态的档案 
  ## 我们要把它删除之後才能开始另一个 game ...... 
 
  if [ -r /tmp/hunt -o -r /tmp/hunt.stats ]; then 
    echo "Removing your stale hunt sockets from /tmp..." 
    /bin/rm -f /tmp/hunt* 
  fi 
 
 
  ## 设定 share library 的 link 及 cache . 这个指令只有 Superuser 才能使用 
  ## 的 , 它也相当的重要 . 万一你的 /etc/ld.so.cache 很不幸的 corrupt 了 , 
  ## 那我们也可以利用这个指令来让它重新 link , 先删除 /etc/ld.so.cache , 
  ## 再以 ldconfig -v 重新制造就可以了 . 
 
  /sbin/ldconfig 
 
 
  ## 起动 sendmail daemon , 并且让它 15 分钟就去看一看 spool , 处理收发信件 
 
  if [ -x /usr/sbin/sendmail ]; then 
   echo "Starting sendmail daemon (/usr/sbin/sendmail -bd -q 15m)..." 
   /usr/sbin/sendmail -bd -q 15m 
  fi 
 
 
  ## 假如 /etc/rc.d/rc.font 是可读的话 , 就执行 rc.font 这个 shell script , 
  ## 而这个 shell script 主要是设定 text mode 下萤幕的字型 
 
  if [ -r /etc/rc.d/rc.font ]; then 
    /etc/rc.d/rc.font 
  fi 
 
 
  ## 在系统管理中 , 我们常常把一些 local 的东西另外放在一个地方 , 这样才不 
  ## 会与原来的东西混淆 . 同时 , 因为 local 的东西更新版本的速度总是也比较 
  ## 快 , 在这种情况下 , 常常会变动的东西也可以放在 local 的区域中 , 这样 
  ## 管理起来比较方便 . 也许各位也注意到了 : 为什麽会有 /usr/bin 及 
  ## /usr/local/bin 之分 . 就个人认为 , 像自己 compile 出来的东西 , 假如 
  ## 觉得还不错 , 就可以把它放在 /usr/local/bin , 因为它是新增的 , 所以我 
  ## 把它放在 /usr/local/bin . 当然啦 , 这只是个人喜好罢了 , 你要放那里 
  ## 都是可以的 , 只要找得到 , 易於使用及管理就好 . 
  ## 同样的 , 若我们要起动一些新增的 daemon 或 shell script , 那放在 
  ## 是不错的选择 . 
  ## 下面一列就是去执行 rc.local 中的设定 , 通常是一些 daemon 或是 shell 
  ## script 
 
  /etc/rc.d/rc.local 
 
 
  # All done. 
 
 
  到这里 , rc.M 已经结束了 , 我们来看看从 rc.M 之中执行的 rc.font 及 
 
  rc.local ...... 
 
  下面是 rc.font 的内容 : 
 
#!/bin/sh 

# This selects your default screen font from among the ones in 
# /usr/lib/kbd/consolefonts. 

 
  ## 我想下面这一列的命令非常明显了 , 就是设定 console 中的字型 , 你可以 
  ## 改成自己喜欢的字 . 或者你也可以利用 fontconfig 这个指令来改变 . 
 
  setfont /usr/lib/kbd/consolefonts/default8x16 
 
 
 
  看完了 rc.font 後 , 我们来看看 rc.local 的内容 . 我所要说的是 : rc.local 
 
  毕竟是自己设定的区域 , 所以每个人的可能都不一样 , 就我而言 , 因为我多 run 
 
  了一些 daemon , 所以与大家的可能不太相同 . 所以 , rc.local 作参考就可以了. 
 
  下面是我的 rc.local : 
 
#! /bin/sh 
# Put any local setup commands in here 
# Running selection 
 
 
## lpd 是控制印表机的 daemon , 要想在 LINUX 下用印表机 , 这个 daemon 必需 
## 要被起动 , 此外还要修改 /etc/printcap . 详细的情况要去看 PRINT-HOWTO 
 
echo -n "lpd" 
/etc/lpd 
 
 
## httpd 就是 WWW server 的 daemon . 想必大家都用过 Mosaic , Netscape 等 
## 的浏览器 . 但假如我们想建立自己的 WWW server , httpd 必须要执行 . 
 
echo -n " httpd" 
/usr/local/etc/httpd/src/httpd 
 
 
## 在 WWW 的时代还没来临以前 , gopher 可说是具有最方便的资料索引功能 , 即使 
## 到了现在 , gopher 仍然占有一席之地 , 在这里 , 因为我有建立自己的 gopher 
## server , 所以 gopherd 必需被起动 . 
 
echo -n " gopherd" 
/usr/local/sbin/gopherd -u nobody 
 
 
## 下面这个指令是 mouse 在 console 下做 cut & paste 
 
echo -n "Running selection..." 
selection -t ms & 
echo '                                                                  ' 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.. 
 

BBS水木清华站∶精华区