零零社区|百姓的网上家园-互动交流平台!(0.0)=^_^=(00社区)

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz

Linux 开机程序之研讨

2013-4-5 12:35| 发布者: 123456000000| 查看: 10| 评论: 0

摘要: 各位是否曾经对电脑整个开机的流程感到好奇呢 ? 这一次 , 我们所要讨论的 主题 , 就是 linux 从开机的一瞬间到 login 为止 , 到底发生了什麽事情 ? 想必各位都知道 , 在刚开机时 , 由於 80x86 的特性 , CS ( Code Se ...
各位是否曾经对电脑整个开机的流程感到好奇呢 ? 这一次 , 我们所要讨论的
   主题 , 就是 linux 从开机的一瞬间到 login 为止 , 到底发生了什麽事情 ?

   想必各位都知道 , 在刚开机时 , 由於 80x86 的特性 , CS ( Code Segment )
   这个暂存器中全部都放著 1 , 而 ip ( Instruction Pointer ) 这个暂存器
   中全部都放著 0 , 换句话说 , CS=FFFF 而 IP=0000 , 此时 , CPU 就依据
   CS 及 IP 的值 , 到 FFFF0H 去执行那个地方所放的指令 . 这时候 , 由於
   FFFF0H 已经到了高位址的顶端 , 所以 , FFFF0H 这个地方 , 总是会放一个
   JMP 指令 , 跳到比较低的位址 . 接著 , ROM BIOS 就会作一些检查的动作
   像记忆体 , 键盘 等...... 并在我们俗称的 UMB ( Upper Memory Block )
   之中扫描 , 看看是否有合法的 ROM 存在 ( 比如 SCSI 卡上的 ROM ) .
   假如有 , 就到里面去执行一些东西 , 执行完之後再继续刚才的行程 . 到了
   最後 , 读取磁碟机上的第一个 sector . 在这里 , 我假设各位由硬碟启动
   因此 , 就硬碟的构造而言 , 它的第一个 sector 称为 MBR ( Master Boot
   Record ) . 因为一个 sector 是 512 bytes , 而 MBR 这 512 bytes 可分
   为两个部份 , 第一个部份为 PRe-Boot 区 , 占了 446 bytes ; 第二部份
   是 Partition Table , 占了 66 bytes . Pre-Boot 区的作用之一 , 就是
   去看看那个 Partition 被标成 Active , 然後去读那个 Partition 的 Boot
   区 .

      在 Linux 的启动方面 , 一般人最常把 LILO 放在 MBR 或 Superblock
   假如你把 LILO 放在 MBR , 那很明显的 , 当读取到 MBR 的时候 , LILO
   就被执行 , 此时 , 你的萤幕上会出现  boot: 接著 , 就进行 Load Kernel
   的动作 . 在另一方面来说 , 假如你把 LILO 安装在 Superblock , 通常你
   还会有一个管理开机的程式 , 也许是住在 MBR ( 像 OSBS ) 或者是放在一
   个单独的 Partition ( 像 OS/2 的 Boot Manager ) . 再由这个管理开机
   的程式去读取 LILO , 进而做 Load Kernel 的动作 .

   好了 , 到了目前为止 , 我们已经讲到 Load Kernel 的动作 . Kernel 被
   load 到 memory 中之後 , 接著进行一连串 probe 周边的动作 , 像串联埠
   并联埠 , 软碟 , 音效卡 , 硬碟 , 光碟机 等 ...... 接著 mount root
   partition . 在这之後 , kernel 会起动 init 这个 process . init 这
   个 process 的 PID 为 1 , 它是所有 process 的祖先 .

   接下来呢 ? 系统就开始执行  /rc.d/rc.S  , 在这里 , 我们暂时打住 ,
   先对大概的 initialization 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

   上面的流程清楚的指出 , 在 rc.S 这个 shell script 中 , 会去执行 rc.serial
   接著再执行 rc.M , rc.M 中又包含了 rc.inet1 , rc.inet2 , rc.font , rc.local
   最後执行 login . 在下面的内容中 , 将为各位介绍这几个 shell script
   从下面开始 , 凡是每一列之前有一个 # 的 , 为原来 shell script 中的注解
   有两个 # 的 , 为笔者加上的注解 , 当然啦 , 没有任何 # 的为 shell script
   的内容 , 而对命令或内容的解释 , 一律都写在命令或内容的前面 .
   首先由 rc.S 开始 :

***************************** rc.S **********************************

#!/bin/sh
#
# /etc/rc
#
# These commands are executed at boot time by init(8).
# User customization should go in /etc/rc.local.

echo '======== rc.S is running !  System Initializing Now !!! ========'
PATH=/sbin:/usr/sbin:/bin:/usr/bin

## 打开所有 swap ! 下面 /sbin/swapon -a 的意思是 : 使得 /etc/fstab 中被记录
## 成 swap 的 device 全部启动 .

/sbin/swapon -a


## 喔 ! 下面这个指令 update 就很重要了 , 它负责每隔一段固定的时间 , 就将
## buffer 中的资料 , 利用 sync 写回磁碟机上 , 并将 superblock 做 update
## 的动作 . 使用 ps 这个指令看看有那些 process , 就可看到 update 还有一个
## bdflush , 这两个 process 都是必然要存在的 , 可不要随便砍掉 , 要不然 ,
## 万一系统 crash 了 , 那磁碟机里面的资料就不是最新的了 ......

/sbin/update &


## 利用 echo -n >> 制造一个档案 , 并用 rm -f 这个档案来测试 root partition
## 是不是 read-only 或者是可读写

READWRITE=no
if echo -n >> "Testing filesystem status"; then
rm -f "Testing filesystem status"
READWRITE=yes
fi


## 假如 root partition 是 read-only 就作 fsck 的动作 , 假如不是 read-only
## 而是 read-write 的话 , 就做下面 else 之後的动作

if [ ! $READWRITE = yes ]; then
## 利用 fsck 做检查及修复档案系统的工作 , 後面接的两个参数 -A , -a .
## -A 的意思是 : fsck 会依据 /etc/fstab 中的记录 , 去检查所有的档案
## 系统 ; 而 -a 就是 auto 的意思 , 当 fsck 有修复的动作时 , 它不会问
## 你问题 , 而直接修复 .

/sbin/fsck -A -a


## 假如 fsck 有 error , [ $? -gt 1 ] 括号里面的意思是 : 若上个命令的
## 传回值大於 1 , 而上个命令就是 fsck . 让我们看看 fsck 的传回值 :
##           0    - No errors
##           1    - File system errors corrected
##           2    - File system errors corrected, system should
##                  be rebooted if file system was mounted
##           4    - File system errors left uncorrected
##           8    - Operational error
##           16   - Usage or syntax error
##           128  - Shared library error
## 很明显的 , 若有任何错误产生的话 , 那 fsck 的传回值都大於 1 . 其实
## 就我的观点认为 , 应该写成 if [ $? -ge 1 ] 比较好 . 既然有错呢 , 系统
## 应该就要跳至单人模式 , 在单人模式中主要就是 /etc/rc.d/rc.K
## 中的两件事 : 关掉 swap 及 卸下所有的档案系统 , 而最後重新 login .
## 一般正常的情况下 ,  if 下面这一大段是不会执行的 , 而会跳至下面
## 标有 *************************  Normal 1  ************************* 处

if [ $? -gt 1 ] ; then
  echo
  echo
  echo "**************************************"
  echo "fsck returned error code - REBOOT NOW!"
  echo "**************************************"
  echo
  echo
  /bin/login
fi

## ******************************  Normal 1  **************************
## 当 fsck 检查没有错误之後 , 就把 root partition 重新 mount 上来
## 下面指令的参数有三个 , -w 代表mount 成可读写 , -n 代表把一个 file-
## system mount 上来 , 但不会把记录写到 /etc/mtab 中 , 在上次对 /etc/mtab
## 介绍时有提到 , 当我们使用 mount 这个指令把一个 filesystem mount 上来
## 的时候 , /etc/mtab 就会记录 ! 利用 -n 这个 option 可使得做 mount 的动
## 作 , 却不会记录 . -o 後面可以接许多的选项 , 在这里 , 我们给它的选项是
## remount . remount 的意思是 : 重新 mount 一个已经被 mount 的 filesystem
## 这个选项通常被用来改变该 filesystem 的读写旗号 ,尤其是把 filesystem
## 从 read-only 的状态 , 改变成 read-write 的状态 .

echo "Remounting root device with read-write enabled."
/sbin/mount -w -n -o remount /


## 在前面的情况中 , 都是 root partition 为 read-only 的状态下 , 所做的一些
## 工作 , 到了最後一个指令 /sbin/mount -w -n -o remount / , 才把 root
## partition mount 成 read-write . 各位有没有看到前面那行 :
## if [ ! $READWRITE = yes ]; then ..... 下面这个 else 就是与这个 if 对应
## 也就是说 , 前面那个 if 的区块中 , 所作的工作都是在 root partition 为
## read-only 的条件成立下所作的事 , 那很明显的 , 下面这个 else 就是 root
## partition 为 read-write 的条件下所作的工作 . 假如你的 root partition
## 为 read-writeable 的话 , 那麽系统就会显示下面的讯息 . cat << EOF 所作的
## 事 , 就是把 EOF 之前的讯息全部显示在萤幕上 :
## 我想 , 下面的讯息写得很明显了 , 它说 : 你的 root partition 被 mount 成
## read-write , 没有办法检查 , 要使检查的动作能够顺利的进行 , 你必须把
## root partition mount 成 read-only ! 那要怎麽做呢 ? 很容易 , 只要利用
## rdev -R /<your_kernel_name> 1  就可以了 ......

else
cat << EOF

*** Root partition has already been mounted read-write. Cannot check!
For filesystem checking to work properly, your system must initially mount
the root partition as read
PORTS=`echo cua? cua??`
echo -n "Configuring serial ports...."


## 下面这行 , 没有学过 shell programming 的人很可能会看不懂 , 不过没有
## 关系 , 这行中的 ${SETSERIAL} 会被换成 /bin/setserial -b , 而 ${PORTS}
## 会被换成 cua0 cua1 cua2 ....... cua31 , 所以整句翻译就是 :
## /bin/setserial -b -W cua0 cua1 cua2 cua3 cua4 cua5 cua6 ...... cua31
## 那这行指令到底在做什麽呢 ? 其实只是在做中断侦测的工作 .

${SETSERIAL} -W ${PORTS}


## 各位看到下面原来的注解了吧 . 当你有一些特殊的卡时 , 你可以把相对应部
## 份前面的 '#' 去掉 , 以便能做自动设定的工作 . 其实呢 , 这种情况实在
## 不多 , 大部份人的设备都差不了多少 , 说到关於串连埠 , 差异就更少了 .
#
# AUTOMATIC CONFIGURATION
#
# Uncomment the appropriate lines below to enable auto-configuration
# of a particular board.  Or comment them out to disable them....
#


## 好了 , 这下我们又多了一个变数 : AUTO_IRQ , 这在下面会用到 .

AUTO_IRQ=auto_irq


## 下面几行非常整齐 , 它们可以分别被换成 :
## /bin/setserial -b /dev/cua? auto_irq skip_test autoconfig
## setserial 说穿了也没什麽 , 这个指令可以让你对 serial port 做设定及回报
## 的动作 , 像 IRQ , I/O port 啦等等的事情 . 一般的情况下 , 大家的电脑中
## 通常只有 COM1-COM4 , 但假如你想增加新的 port , 那 setserial 就派上用
## 场了 .

# These are the standard COM1 through COM4 devices
#
# If you have an internal modeme with a Rockwell Chipset, add a "skip_test"
# to the /dev/cua3 line below.  (It's not added by default because it will
# screw up people with 8514 displays).
#
${SETSERIAL} /dev/cua0 ${AUTO_IRQ} skip_test autoconfig
${SETSERIAL} /dev/cua1 ${AUTO_IRQ} skip_test autoconfig
${SETSERIAL} /dev/cua2 ${AUTO_IRQ} skip_test autoconfig
${SETSERIAL} /dev/cua3 ${AUTO_IRQ} autoconfig

# These are for the first AST Fourport board (base address 0x1A0)
#
${SETSERIAL} /dev/cua4 ${AUTO_IRQ} autoconfig
${SETSERIAL} /dev/cua5 ${AUTO_IRQ} autoconfig
${SETSERIAL} /dev/cua6 ${AUTO_IRQ} autoconfig
${SETSERIAL} /dev/cua7 ${AUTO_IRQ} autoconfig

# These are for the second AST Fourport board (base address 0x2A0)
#
${SETSERIAL} /dev/cua8 ${AUTO_IRQ} autoconfig
${SETSERIAL} /dev/cua9 ${AUTO_IRQ} autoconfig
${SETSERIAL} /dev/cua10 ${AUTO_IRQ} autoconfig
${SETSERIAL} /dev/cua11 ${AUTO_IRQ} autoconfig


## 从这里以下 , 我省略了一大段 , 因为这一大段都是支援特殊的卡

# These are the 3rd and 4th ports on the Accent Async board.
#
#${SETSERIAL} /dev/cua12 ${AUTO_IRQ} autoconfig
#${SETSERIAL} /dev/cua13 ${AUTO_IRQ} autoconfig
#


           .
           .
           .
           .
           .
           .
           .


## 好了 , 我们跳掉了一大段 , 直到这里 . 各位看到下面的注解了 .
## 假如你想用手动的方法指定 IRQ , I/O port , 及指定 chip 的型别
## 那你可以拿掉下面对应那行前面的 '#' 并作适当的修改 , 比如说
## 你用的是比较新的 16550 或 16550A , 而不是 16450 , 那你就可以
## 在下面用手动的方法指定 . 实际上 , 用 autoconfig 及 autoirq
## 的选项就可以了 , 没有必要用手动的方式 . 除非侦测不到 .

###############################################################
#
# MANUAL CONFIGURATION
#
# If you want to do manual configuration of one or more of your
# serial ports, uncomment and modify the relevant lines.
#
###############################################################

# These are the standard COM1 through COM4 devices
#
#${SETSERIAL} /dev/cua0 uart 16450 port 0x3F8 irq 4
#${SETSERIAL} /dev/cua1 uart 16450 port 0x2F8 irq 3
#${SETSERIAL} /dev/cua2 uart 16450 port 0x3E8 irq 4
#${SETSERIAL} /dev/cua3 uart 16450 port 0x2E8 irq 3

           .
           .
           .
           .
           .
           .
           .
           .

## Ok , 到此 , rc.S 及 rc.serial 已经结束 , 因为截稿时间的关系 , rc.M
## rc.inet1 , rc.inet2 , rc.font , rc.local 将在以後为各位介绍 .

echo "done."
${SETSERIAL} -bg ${PORTS}

echo ' ====================== rc.serial is complete !!! ==================='



  * 关於 Shell Programming 的书单 :

  Title: The Unix C Shell Field Guide
  Authors: Gail Anderson and Paul Anderson
  Publisher: Prentice Hall
  Edition: 1986
  ISBN: 0-13-937468-X

  这本是 C-Shell 的 Bible , 想学 C-Shell 的人 , 可以去看这本书 .


  Title: Unix Shell Programming
  Authors: Stephen Kochan and Patrick Wood
  Publisher: Hayden
  Edition: 1990
  ISBN: 0-672-48448-X

  喔 ! 这本书以 Bourne Shell 为主 , 内容深入浅出 , 读者很容易就可以了解
  这本书的内容 , 进而掌握 Bourne Shell 的精髓 . 此外 , 这本书也有提到
  Korn Shell , 大体上来说 , 是一本值得看的好书 .


  *如何连络作者 :

   E-Mail Address : jhhsu@csie.nctu.edu.tw
                    u8217017@cc.nctu.edu.tw

   Dormitory : 交通大学十舍 317R

..



                       Linux 开机程序之研讨
                                                        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 '                                                                  '






















..

32

路过

雷人

握手

鲜花

鸡蛋

相关阅读

发表评论

最新评论

相关分类


Archiver|手机版|小黑屋|00社区

GMT+8, 2023-1-31 10:51 , Processed in 0.044238 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部