使用 Red Hat 的 chkconfig 管理 Initscripts

作者:Jimmy Ball

我喜欢发现新的 UNIX 命令,尤其是那些具有系统管理特性的命令。当我了解到 Red Hat 发行了 chkconfig 实用程序时,它让我想起了 IRIX 下的 chkconfig,IRIX 是 Silicon Graphics, Inc. 的 UNIX 变体。IRIX 的 chkconfig 旨在启用/禁用服务,以便在系统初始化期间自动启动,而无需编辑、重命名或移动 /etc 中的 initscripts。

同样,Red Hat 设计 chkconfig 旨在帮助管理系统初始化期间启动的服务。但是,在仔细阅读了手册页并进行了一些测试后,我很快发现 Red Hat 扩展了 chkconfig,通过管理指向 initscripts 的符号链接,可以更精细地控制系统启动/关闭任务。这真是节省时间!

启动基础知识

当您的 Linux 机器启动时,出现的第一个进程是 init。如果您以前没有见过 init,请花点时间键入 ps -ef | grep init 来查看 init 的 PID。简而言之,init 执行 /etc/inittab 中概述的任务。

/etc/inittab 中概述的一些任务将在 init 之后不久启动,而另一些任务只是设置好。例如,默认的 Red Hat /etc/inittab 为键序列 Ctrl-Alt-Delete 设置了一个陷阱。当在控制台提示符(非 xdm)下同时按下这些键时,将执行 shutdown 命令。在启动时,init 会根据 /etc/inittab 中的配置选项设置此功能,但执行会推迟到键序列发生时。

inittab 的格式允许以 “#” 符号开头的注释行,而普通条目是 “:” 分隔的。它们遵循 id:runlevel:action:process 模式,其中 id 表示用户定义且唯一的标识符,runlevel 可以是数字 0-6 的组合或留空,action 来自描述 init 应如何处理进程的关键字,而 process 是要执行的命令。

操作字段的各种关键字的描述通常可以在 inittab 的手册页中找到。大多数(如果不是全部)UNIX 平台上的常用关键字包括

  • initdefault—定义系统启动后要进入的运行级别。

  • wait—一个将在运行级别进入时执行一次的进程。init 进程将等待此进程终止。

  • boot—定义在启动时执行的进程。

  • bootwait—类似于 boot,但 init 会等待进程终止后再继续。

  • sysinit—定义在任何 boot 或 bootwait inittab 条目之前在启动时执行的进程。

运行级别字段指定系统状态。例如,运行级别 0 对应于已停止的系统,而运行级别 6 对应于系统重启。不幸的是,并非所有 Linux 发行版都遵循相同的运行级别定义。在 Red Hat 下,支持以下默认值

   0.   System halt
   1.   Single-user mode
   2.   Multiuser, without NFS
   3.   Complete multiuser mode
   4.   User defined
   5.   X11 (XDM login)
   6.   Reboot

对于每个运行级别,/etc/rc.d 中都有一个相应的目录。对于运行级别 5,存在目录 /etc/rc.d/rc5.d,其中包含与启动到该运行级别时需要执行的任务相关的文件。在 Red Hat 下,这些文件通常是指向 /etc/rc.d/init.d 中 shell 脚本的符号链接。

让我们用一个简单的例子将所有这些放在一起。以下是我们 inittab 文件中的两个示例行

id:3:initdefault:
l3:3:wait:/etc/rc.d/rc 3

以下是在 Red Hat 下发生的典型场景。一旦 init 启动,它会读取 /etc/inittab(见上文)。从第一行,我们知道 init 将在系统启动后最终进入运行级别 3。一旦我们达到该运行级别,第二行告诉 init 运行脚本 /etc/rc.d/rc three 并等待它终止后再继续。

/etc/rc.d 中的脚本 rc 接收 3 作为参数。此 3 对应于运行级别 3。因此,rc 脚本执行 /etc/rc.d/rc3.d 目录中的所有脚本。它首先执行所有以字母 K 开头的脚本(表示“kill”进程或服务),参数为 “stop”。接下来,它运行所有以字母 S 开头的脚本,参数为 “start” 以启动进程或服务。最后需要注意的是,K 和 S 脚本的执行顺序基于排序顺序;名为 S90mysql 的脚本将在名为 S95httpd 的脚本之前执行。

事实证明,/etc/rc.d/rc3.d 中的脚本实际上是指向位于 /etc/rc.d/init.d 中的脚本的符号链接。虽然 UNIX 管理员可以将脚本放在 rc3.d 中,但 Red Hat 下的常见做法是首先将所有脚本放在 init.d 中,然后创建到 rc*.d 目录的逻辑链接。很快就会发现,创建和维护这些脚本和符号链接可能是一项非常繁琐的任务。这正是 chkconfig 介入的地方!Red Hat chkconfig 实用程序专门设计用于管理 /etc/rc.d/rc[0-6].d 中的符号链接。

查看 chkconfig 条目

chkconfig 二进制文件位于 /sbin 中,默认权限允许任何用户执行它,尽管没有 root 权限的用户只能查看当前的 chkconfig 配置。因此,键入

[root]# chkconfig --list | grep on

输出的部分列表如下所示

amd 0:off 1:off 2:off 3:off 4:on 5:on 6:off
apmd 0:off 1:off 2:on 3:off 4:on 5:off 6:off
arpwatch 0:off 1:off 2:off 3:off 4:off 5:off 6:off
atd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
autofs 0:off 1:off 2:off 3:off 4:off 5:off 6:off
named 0:off 1:off 2:off 3:off 4:off 5:off 6:off
bootparamd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
keytable 0:off 1:off 2:on 3:on 4:on 5:on 6:off
crond 0:off 1:off 2:on 3:on 4:on 5:on 6:off
syslog 0:off 1:off 2:on 3:on 4:on 5:on 6:off
netfs 0:off 1:off 2:off 3:on 4:on 5:on 6:off
network 0:off 1:off 2:on 3:on 4:on 5:on 6:off
在输出的每一行中,第一个字段表示 /etc/rc.d/init.d 中 initscript 的名称。其余字段对应于运行级别 0-6 以及进入该运行级别时脚本的状态。例如,crond 将在进入运行级别 2、3、4 和 5 时启动,并在进入运行级别 0、1 和 6 时停止。我们可以使用 find 命令来搜索 /etc/rc.d 中所有以 crond 结尾的文件,以确认这些设置是否正确
[root]# find /etc/rc.d -name '*crond' -print
/etc/rc.d/init.d/crond
/etc/rc.d/rc0.d/K60crond
/etc/rc.d/rc1.d/K60crond
/etc/rc.d/rc2.d/S40crond
/etc/rc.d/rc3.d/S40crond
/etc/rc.d/rc4.d/S40crond
/etc/rc.d/rc5.d/S40crond
/etc/rc.d/rc6.d/K60crond
请注意,对于 chkconfig 报告的每个 “off” 部分(0、1、6),都有一个 kill 脚本到位,对于报告的每个 “on” 部分(2、3、4、5),都存在一个 start 脚本。接下来,执行不同的 find 命令来确定找到的每个文件的类型
[root]# find /etc/rc.d -name '*crond' -exec file {} \;
/etc/rc.d/init.d/crond: Bourne shell script text
/etc/rc.d/rc0.d/K60crond: symbolic link to
  ../init.d/crond
/etc/rc.d/rc1.d/K60crond: symbolic link to
  ../init.d/crond
/etc/rc.d/rc2.d/S40crond: symbolic link to
  ../init.d/crond
/etc/rc.d/rc3.d/S40crond: symbolic link to
  ../init.d/crond
/etc/rc.d/rc4.d/S40crond: symbolic link to
  ../init.d/crond
/etc/rc.d/rc5.d/S40crond: symbolic link to
  ../init.d/crond
/etc/rc.d/rc6.d/K60crond: symbolic link to
  ../init.d/crond
这表明 init.d 中找到的 crond 是一个 shell 脚本,而找到的所有其余文件都是指向 crond 脚本的符号链接。
修改 chkconfig 条目

修改 chkconfig 条目几乎与列出现有配置一样容易。形式是

chkconfig [--level <levels>] <name> <on|off|reset>

例如,如果我们决定禁用运行级别 2 的 crond,则 chkconfig --level 2 crond off 命令(由 root 执行)将关闭运行级别 2 的 crond。运行 chkconfig --list 将确认 crond 的配置已修改。此外,下面的 find 命令显示 kill 脚本已替换 rc2.d 目录中的 start 脚本

[root]# find /etc/rc.d -name '*crond' -print
/etc/rc.d/init.d/crond
/etc/rc.d/rc0.d/K60crond
/etc/rc.d/rc1.d/K60crond
/etc/rc.d/rc2.d/K60crond
/etc/rc.d/rc3.d/S40crond
/etc/rc.d/rc4.d/S40crond
/etc/rc.d/rc5.d/S40crond
/etc/rc.d/rc6.d/K60crond
请记住,chkconfig 不会自动立即禁用或启用服务。它只是更改符号链接。超级用户可以使用命令 /etc/rc.d/init.d/crond stop 立即禁用 crond 服务。最后,您可以使用一个 chkconfig 命令启用/禁用多个运行级别的命令。例如,输入
chkconfig --levels 2345 crond on
会将 crond 设置为在运行级别 2、3、4 和 5 中启动。
删除条目

有时,完全删除服务可能是必要的。以 sendmail 为例。在不需要本地帐户接收传入邮件的客户端计算机上,可能不需要将 sendmail 作为守护程序运行。在这种情况下,我发现禁用 sendmail 是可取的,因为它降低了潜在的安全风险。要从 chkconfig 中删除 sendmail,请键入

chkconfig --del sendmail

下面,我们的 find 命令显示没有符号链接到位,而 sendmail 的 initscript 仍然存在

[root]# find /etc/rc.d -name '*sendmail' -print
/etc/rc.d/init.d/sendmail
在我看来,这非常完美。脚本被保留下来,以防 sendmail 需要重新建立为服务,但所有符号链接都已消失。虽然我们可以禁用所有运行级别的 sendmail,但这会在每个 rc*.d 子目录中放置 kill 脚本,这是一项不必要的任务,因为 sendmail 从未在初始化阶段启动过。但是,我见过系统管理员会在某些情况下手动启动服务的情况。为该服务放置 kill 脚本可确保干净地杀死服务。因此,您自己决定。
添加 chkconfig 条目

到目前为止,一切都很好。我们已经了解了如何使用 chkconfig 查看、修改和删除服务。现在是添加新服务的时候了。以名为 oracle 的脚本为例(参见列表 1)。

列表 1. Oracle 脚本

使用此脚本,可以使用 “start” 参数启动 Oracle 8,并使用 “stop” 参数终止。这满足了可以与启动脚本 /etc/rc.d/rc 结合使用的 initscript 的最低要求。

将脚本放在 /etc/rc.d/init.d 中并运行(以 root 身份)

chmod +x /etc/rc.d/init.d/oracle

使脚本可执行。如果您担心普通用户看到该脚本,您可以尝试更严格的文件权限,只要该脚本作为独立脚本可由 root 执行即可。

请注意脚本中的两行注释

#chkconfig: 2345 80 05
#description: Oracle 8 Server

chkconfig 需要这些行来确定如何建立初始运行级别以添加服务,以及设置启动和停止脚本执行顺序的优先级。这些行表示脚本将在运行级别 2、3、4 和 5 中启动 Oracle 8 服务器。此外,启动优先级将设置为 80,而停止优先级将设置为 05。

现在脚本已就位,具有适当的执行权限,并且所需的 chkconfig 注释已就位,我们可以通过键入(以 root 身份)chkconfig --add oracle 将 initscript 添加到 chkconfig 配置。

使用 chkconfig 的查询功能,我们可以验证我们的添加

[root]# chkconfig --list | grep oracle
oracle        0:off     1:off   2:on   3:on   4:on   5:on  6:off

此外,我们可以键入我们的标准 find 命令来查看 chkconfig 如何设置符号链接

[root]# find /etc/rc.d -name '*oracle' -print
/etc/rc.d/init.d/oracle
/etc/rc.d/rc0.d/K05oracle
/etc/rc.d/rc1.d/K05oracle
/etc/rc.d/rc2.d/S80oracle
/etc/rc.d/rc3.d/S80oracle
/etc/rc.d/rc4.d/S80oracle
/etc/rc.d/rc5.d/S80oracle
/etc/rc.d/rc6.d/K05oracle
根据请求,kill 链接的名称包含优先级 05,而 start 链接包含 80。如果我们需要调整优先级(例如,我们的停止优先级需要为 03),只需修改 oracle 的 initscript 中的 chkconfig 注释行,并运行 reset 命令,如下所示。生成的符号链接将相应地重命名
[root]# chkconfig oracle reset
[root]# find /etc/rc.d -name '*oracle' -print
/etc/rc.d/init.d/oracle
/etc/rc.d/rc0.d/K03oracle
/etc/rc.d/rc1.d/K03oracle
/etc/rc.d/rc2.d/S80oracle
/etc/rc.d/rc3.d/S80oracle
/etc/rc.d/rc4.d/S80oracle
/etc/rc.d/rc5.d/S80oracle
/etc/rc.d/rc6.d/K03oracle
Red Hat 7 中的增强功能

正如你们中的许多人已经知道的那样,在 Red Hat 7 中,inetd 已被 xinetd 取代。此外,chkconfig 功能已得到扩展,以管理 xinetd 的 Internet 服务的一些功能。示例如下

[root]# chkconfig --list
...
xinetd based services:
      finger:  on
      linuxconf-web:  off
      rexec:  off
      rlogin:  off
      rsh:  off
      ntalk:  off
      talk:  off
      telnet:  on
      tftp:  off
      wu-ftpd:   on

要禁用 xinetd 功能,例如 finger,您可以键入 [root]# chkconfig finger off

很棒,对吧?但是,有一个“陷阱”。当配置更改时,xinetd 会自动收到信号以重新加载新配置,命令为 /etc/init.d/xinetd reload,由 chkconfig 执行。此脚本使用 SIGUSR2 信号执行 kill,该信号指示 xinetd 执行硬重新配置。

这意味着什么?好吧,当我测试它时,通过 xinetd 提供的服务的活动会话(即 Telnet、FTP 等)立即终止。如果您可以计划在系统上禁用/启用 xinetd 服务的最佳时间,那么这可能对您来说不是问题。作为替代方案,您可以修改 /etc/init.d/xinetd 脚本,以便 reload 选项发送 SIGUSR1 信号,这是一种软重新配置。这将重新启动服务,而不会终止现有连接。

为 chkconfig 管理添加 xinetd 服务就像将 xinetd 服务文件添加到 /etc/xinetd.d 目录中一样简单。chkconfig 实用程序将自动拾取它,并使其可通过 chkconfig 实用程序进行管理。太棒了!

结论

希望您已经看到了 Red Hat 的 chkconfig 实用程序在管理 initscripts 方面的优势。虽然其功能看起来很简单,但节省时间的好处使 chkconfig 成为管理员值得记住的命令。

Managing Initscripts with Red Hat's chkconfig
Jimmy Ball 是 Batky-Howell, Inc. 的讲师,他在那里教授 UNIX、Perl 和 Java 课程。可以通过电子邮件 jb@batky-howell.com 与他联系。
加载 Disqus 评论