使用 Red Hat 的 chkconfig 管理 Initscripts
我喜欢发现新的 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 二进制文件位于 /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 [--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 查看、修改和删除服务。现在是添加新服务的时候了。以名为 oracle 的脚本为例(参见列表 1)。
使用此脚本,可以使用 “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 中,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 实用程序进行管理。太棒了!
