SysVinit 脚本

Posted on Posted in linux

参考openSUSE:Packaging init scripts

基本逻辑

包括 SysVinit 和 Systemd 在内的几乎全部引导系统,其程序逻辑均为:

  • 判断是否处于某种状态来决定是否启动服务,所谓“启用”/“禁用”,意即是否允许这种判断。SysVinit 中的状态即运行级别。
  • 进入某种状态后,执行服务的启动(start),离开某种状态前,执行服务的停止(stop)。只有这一种逻辑,只存在达到状态后启动、离开状态前停止,不存在达到状态后停止、离开状态前启动、达到状态前启动/停止、离开状态后启动/停止等合理想象。
  • 启动和停止总是成对出现。你可以没有对应的实现,但必须有这些关键字。
  • 状态下的执行,不保证执行成功。所以单纯依赖状态来启动/停止服务是错误的。因为状态本身并不意味着你的服务依赖的其他引导设施都是可用的。比如运行级别 5 意味着有网络和图形界面,但是你拔了网线就没图形界面了吗?显然不是。即达到状态后会执行联网,但不保证联网成功。
  • 特殊状态如关机、重启下并不执行任何东西。关机状态即为断电,断电还怎么执行?正确的做法是依赖于进入该特殊状态之后的状态来启动,依赖于离开该特殊状态之前的状态来停止。------批注:开关机可视为在不同状态间的转换,比如开机为运行级别 0->1->2->3->5,关机为 5->3->2->1->0,重启为 5->3->2->1->6->1->2->3->5。所以比如想要实现关机自动关闭,开机自动启动,并不需要依赖 0 或 6 状态,只要保证进入 5 状态后启动,离开 5 状态前停止就能达到目的。
  • 服务的启动/停止是有次序的。可以是并发、可以是排队。并不是随机的。但是未知次序等于没有次序。你需要利用服务之间的依赖关系覆盖系统自动的排序,保证你的服务所需引导设施在其启动前均是可用的,在其停止前不能先行停止。

制作任何引导脚本必须遵守其程序逻辑。

命名

引导脚本的命名必须与 LSB 兼容,它必须被列示在 http://www.lanana.org/lsbreg/init/init.txthttp://www.lanana.org/lsbreg/instructions.html 描述了如何注册新名称。

openSUSE 除非是基础核心包,用户软件没必要去注册这种名称,一般命名就是包名,守护程序是包名 + 字母d(daemon)。

结构

/etc/init.d/skeleton 文件是一个空白的引导脚本,体现了引导脚本的结构。该文件也可以作为引导脚本的模板。

LSB 规则

以/etc/init.d/skeleton 为例

#!/bin/sh
# kFreeBSD do not accept scripts as interpreters, using #!/bin/sh and sourcing.
if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then
    set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script
fi
### BEGIN INIT INFO
# Provides:          skeleton
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.  This example start a
#                    single forking daemon capable of writing a pid
#                    file.  To get other behavoirs, implemend
#                    do_start(), do_stop() or other functions to
#                    override the defaults in /lib/init/init-d-script.
### END INIT INFO

# Author: Foo Bar <foobar@baz.org>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.

DESC="Description of the service"
DAEMON=/usr/sbin/daemonexecutablename

Provides: 行

行列出了该脚本服务能提供的全部引导设施,通常与脚本名字相同

Required-Start: 行

列出了启动此脚本服务必须的全部引导设施。本行是必须的,可以为空。系统引导设施在下面

Required-Stop: 行

列出了在停止该脚本服务之前必须不能被先行停止的全部引导设施。本行是可选的,如果一个引导脚本不需要任何在它停止前不能被停止的引导设施,那么就不需要该行。

Should-Start: 行

列出了一旦可用就应该在启动该脚本服务前被启动的全部引导设施。目的是允许额外的即使不可用也不会造成该脚本服务失败的依赖。本行为可选,如果一个引导脚本不需要启动任何可选依赖,那么可以没有本行。

Should-Stop: 行

列出了一旦可用就不能在停止该脚本服务前停止的全部引导设施。目的是允许额外的即使不可用也不会造成该脚本服务失败的依赖。本行为可选,如果一个引导脚本不需要任何在它停止前不能停止的额外依赖,本行可以没有。

Default-Start: 行

行列出了一些运行级别,在这些运行级别下,该脚本服务应该默认启用。运行级别间以空格分隔。

运行级别:

  • 0 关机断电。运行不了任何服务。
  • 1 单用户 root 环境。一般只有忘记 root 密码才会想起这个运行级别。
  • 2 多用户环境。但是没有网络文件系统(NFS,比如 /home 可能在云上)。简单说,没网。
  • 3 完全多用户环境。有网。
  • 4 系统未使用。保留。一般等同于 3。
  • 5 有图形界面的多用户环境。多数时候我们都在这个级别下。
  • 6 重启。类似于 0

Default-Stop: 行

列出了脚本服务没有默认启动的运行级别。运行级别间以空格分隔,且必须包含所有 # Default-Start: 行没有使用过的运行级别。

Short-Description: 行

提供了对引导脚本行为的简要介绍。本行只有一行且不能超过 80 个字符。

Description: 行

提供了对引导脚本行为更加完整的描述。它可以是多行,后续的行必须以 '#' 加一个 tab (也就是至少两个空格不能多于四个空格)开头。一旦某行首不满足该条件就意味着多行描述的终止。这也是用来在 YaST 运行级别编辑器里显示的。

系统引导设施

根据 LSB 的要求, openSUSE 的引导脚本已经提供了一些预设的引导设施。它们在 /etc/insserv.conf 里。目前,有以下系统引导设施可供使用:

  • $local_fs — 全部本地文件系统均已挂载。大多数脚本服务都需要这个。
  • $remote_fs — 全部远程文件系统也已挂载。因为 /usr 可能是远程目录,许多脚本服务也应该需要这个。
  • $syslog — 系统日志可用。
  • $network — 底层网络设备(比如有线网卡)可用。
  • $named — 主机名解析可用。
  • $netdaemons — 全部网络守护进程均已运行。这在 LSB 1.2 中被移除了。但目前我们还提供它以便于向后兼容。
  • $time — 系统时间正确。
  • $portmap — SunRPC portmapping 服务可用。
  • $null — 强制性的空依赖。用于 Required-Stop 和 Should-Stop 否则 insserv 会假设依赖关系跟 *-Start 的一样。

除了定义在 /etc/insserv.conf 中的 LSB 兼容的系统引导设施,openSUSE 上还有以下系统引导设施:

  • $all 该引导设施表示服务应被插入到全部服务的最后。显然,全部使用该设施的服务将被分进同一组启动。
  • $null强制的空依赖。用于# Should-Stop: 和 # Required-Stop: 否则 insserv(8) 会假设依赖跟 # Should-Start:
    和 # Required-Start: 中指定的相同。

其他非系统引导设施在 LSB 头部中的 # Provides: 行里定义。

行为

根据 LSB 的定义,所有的引导脚本都必须知道如何处理如下行为:

  • start — 启动脚本服务。
  • stop — 停止脚本服务。
  • restart — 如果脚本服务已在运行,重启它。如果没在运行,启动它。
  • reload — 不重启脚本服务直接重新加载它的配置。
  • force-reload — 如果脚本服务支持的话,就重新加载配置,不然就重启。
  • status — 输出脚本服务目前的状态。
  • usage - 默认如果该引导脚本没有附加任何行为选项,它应该列出所有可用的行为以供用户选择。

所有引导脚本都必须支持 start, stop, restart, force-reload, 和 status 行为。reload 行为是可选支持的。

退出状态代码

  • 0 成功
  • 1 一般或未定义错误
  • 2 无效或多余的参数
  • 3 没有这个行为 (例如 "reload")
  • 4 用户权限不足
  • 5 程序未安装
  • 6 程序未配置
  • 7 程序未运行
  • 8-99 保留,以供 LSB 未来使用
  • 100-149 保留,以供发行版使用
  • 150-199 保留,以供应用程序使用
  • 200-254 保留

状态函数

  • 0 程序运行中或脚本服务没问题。
  • 1 程序僵死,/var/run pid 进程文件仍存在。
  • 2 程序僵死,/var/lock lock 文件仍存在。
  • 3 程序没有运行。
  • 4 程序或脚本服务的状态未知。
  • 5-99 保留,以供 LSB 未来使用
  • 100-149 保留给发行版使用
  • 150-199 保留给应用程序使用
  • 200-254 保留
» 转载请注明来源:若我若鱼 » SysVinit 脚本

Leave a Reply

Your email address will not be published. Required fields are marked *

seven + 7 =