linux添加启动服务,以及chkconfig命令使用

什么是LSB

    LSB,即Linux标准规范(英语:Linux Standard Base)是一个在Linux基金会结构下对Linux发行版的联合项目,使Linux操作系统符合软件系统架构,或文件系统架构标准的规范及标准。LSB基于POSIX,统一UNIX规范及其他开放标准,共在某些领域扩展它们。详细情况请参考相关链接。

LSB脚本动作

    由LSB应用程序提供的脚本应该需要接受一个指示其动作(action)的参数,目前包括:

  • start 启动服务
  • stop 停止服务
  • restart 如果服务在运行,则先停止,再启动,否则启动服务
  • try-restart 如果服务正在运行,重启服务
  • reload 不通过重启服务的方式重新加载配置文件
  • force-reload 如果服务支持的话,重新加载配置文件,否则重启服务
  • status 打印服务的当前状态

    start,stop,restart,force-reload 和status是所有lsb脚本必须支持的;reload和try-restart是可选的。当然自己也可以定义别的一些动作。

    在下列情况下,lsb脚本要求确保对其接受的动作(action)有其明确且合理的行为

  • 服务已经启动,然后调用start
  • 服务已经停止,然后调用stop

    对于这些行为,为了满足其一致性,最好使用/lib/lsb/init-functions脚本(后面分析)

    在主流的Linux发行版版本中,一个软件包卸载(remove)时,并不会讲一些脚本,配置文件同时删除,除非你强制指定为清除(purge).因此,在你的lsb脚本最前面应该包括一个判断真正的可执行文件是否存在,类似于下面这个样子:

    [ -x /usr/sbin/ifconfig ] || exit 5

    如果调用status动作,lsb脚本应该根据其状态返回下面的值:

  • 0 程序正在运行,或者服务正常
  • 1 程序已死,但/var/run/下的pid文件还存在(或者在别的位置)
  • 2 程序已死,但/var/lock/下的锁文件还存在(或者在别的位置)
  • 3 程序没有运行
  • 4 程序或者服务状态未知
  • 5-99 LSB为扩展保留
  • 100-149 为发行版本使用保留
  • 150-199 为应用程序使用保留
  • 200-254 保留

    除status动作外,指定其他动作,lsb脚本必须返回状态值(exit $?),如果完成动作其他的结果,返回为0,否则应该根据动作情况,返回下列值之一:

  • 1 通用(generic)错误或者非规范化错误
  • 2 无效参数,或者参数过多
  • 3 未实现的特性(比如reload)
  • 4 用户权限不够
  • 5 程序没有安装
  • 6 程序没有配置
  • 7 程序没有运行
  • 8-99 LSB为扩展保留
  • 100-149 为发行版本保留
  • 150-199 为应用程序使用保留
  • 200-254 保留

    错误和状态消息应该通过日志函数来输出,比如lsb提供的log_failure_msg。

    因为lsb脚本有可能是由系统管理员在非标准的环境下手工运行,比如没有PATH,USER,LOGNAME等环境变量.因此lsb脚本不能依赖环境变量,它需要自己设定自己需要的变量或者使用缺省值.

LSB脚本注释约定

    在init.d目录的lsb脚本,其脚本描述信息应该用### BEGIN INIT INFO 和 ### INIT INFO来分隔。分隔行可以包行尾部空白,脚本会忽略它。在分隔行之间包围区域其描述信息需要遵循这样的格式: # {keyword}: [arg1] [arg2] ...。,在#和keyword之间只能而且必须有一个空格,类似下面的例子:

1
2
3
4
5
6
7
8
9
# Provides: boot_facility_1 [ boot_facility_2 ...]
# Required-Start: boot_facility_1 [ boot_facility_2 ...]
# Required-Stop: boot_facility_1 [ boot_facility_2 ...]
# Should-Start: boot_facility_1 [ boot_facility_2 ...]
# Should-Stop: boot_facility_1 [ boot_facility_2 ...]
# Default-Start: run_level_1 [ run_level_2 ...]
# Default-Stop: run_level_1 [ run_level_2 ...]
# Short-Description: short_description
# Description: multiline_description

    init.d下的lsb脚本可以用Required-Start关键字来申明在运行该脚本之前应该需要先运行哪些脚本,这些信息一般是由安装程序或者启动脚本工具根据相互依赖关系来生成其正确的顺序(比如所有依赖网络的服务都应该应该在network脚本启动之后运行)。当lsb脚本带start参数运行时,在Provides指定的设施(facility)应该存在,而且lsb脚本也要求这些设施能够正确运行.

    类似的,Required-Stop里定义的启动设施应该在该脚本停止时都有效.

    Should-Start关键字和Should-Stop关键字的概念和Required-Start及Required-Stop类似,只是对其后面定义的设施是希望而不是必须。

    Default-Start和Default-Stop 定义了缺省情况下该脚本在哪些运行级别下启动和停止,它可以通过init脚本来控制。

    Short-Description和Description关键字是描述该脚本的行为,如关键字说描述的那样,Short-Description希望是简洁的介绍该脚本,而Description则可以更详细一点。如果描述信息多余一行,从描述信息的第二行起,每一行都必须以#符号开头,然后接一个tab键,或者至少两个空格。

安装和移除(removal)init.d脚本

    通过将脚本拷贝到init.d目录或者符号链接到该目录,就完成了脚本的安装工作,在执行安装包的postinstall脚本阶段(RPM包管理),/usr/lib/lsb/install_initd程序调用安装程序的init.d脚本文件来安装/usr/lib/lsb/inistall_initd程序可以带一个参数,类似如下:

    /usr/lib/lsb/install_initd /etc/init.d/foo

    如果脚本已经安装或者安装程序,该程序均返回为0,其他情况返回为非0值。

    卸载软件包时,通过preuninstall脚本来调用/usr/lib/lsb/remove_initd程序来移走init.d目录对应的文件,类似如下:

    /usr/lib/lsb/remove_initd /etc/init.d/foo

    如果脚本已经移除或者移除成功,则返回为0,否则返回为非0值。

    系统发行版本应该提供一个有效的工具(比如红帽的chkconfig)来提供给系统管理员来管理多运行级别下,脚本的启动停止控制。

运行级别

    绝大部分通用Linux发行版都提供了多种启动级别,前面说到的Default-Start,Default-Stop也表明了这点。系统init脚本通过调用对应运行级别目录(rc?.d)下的脚本(符号链接)来控制哪些脚本应该在该级别启动和停止。/usr/lib/lsb/inistall_initd程序通过查询脚本的Default-Start和Default-Stop的定义来创建对应运行级别目录的符号链接。系统启动级别及描述如下:

  • 0 停机
  • 1 单用户模式
  • 2 多用户无网络模式(很少使用)
  • 3 完整的多用户终端模式(无图形界面)
  • 4 保留
  • 5 多用户带GUI模式
  • 6 重启

设施(facility)名称

    启动设施用来指示init脚本之间的依赖性。以$符号开头设施名都是系统设施,它由LSB定义,发行版吧必须提供。符合LSB规范的应用程序不能提供以$开头的设施名称。 当前LSB定义下面的几种设施名称:

  • $local_fs 所有的本地文件系统已经挂载
  • $network 底层网络已经有效(指网卡,IP地址,PCMCI之类的)
  • named 域名解析后台服务(DNS)正在运行
  • portmap 提供SunRPC/ONCRPC端口映射的服务(如果存在的话)正在运行
  • remote_fs 所有远程文件系统已经挂载
  • syslog 系统日志服务可用
  • time 系统时钟已经设置

    其他(非系统)的设施可以由LSB应用程序来定义,这些设施名称应该采取脚本名同名的命名约定,通常情况下,发行版版本都是如此.

脚本名称

    所有的init脚本都在同一个目录,因此名字不能冲突,LSB规范提供了三种有效命名空间方式:

  •     Assigned namespace 这种命令只能由[a-z0-9]类的字符组成(没有大写字母).为了避免名字冲突,应该去Linux Assigned Names and Numbers Authority(LANANA)去申请你需要的名字.

  •     Hierarchical namespace 这种命名空间由类似[hier1]-[hier2]-...-[name]组成,其中name由[a-z0-9]内的字符组成.[hier-n]可以有一个或者多个,[hier1]的名字要不是LANANA分配给LSB的名字,要不就是脚本拥有者的DNS小写名称,至少包含一个.符号,比如debian.org,kingbase.com. LSB提供的名字只能由[a-z0-9]内的ASCII码组成.

  •     Reserved namespace 这种命令空间以_符号开头,仅提供给版本发行商使用,而且这种命令空间也应该只用在核心软件包上.其他软件包绝不推荐这种命名方式.

init脚本函数

    每一个LSB兼容的init.d脚本必须包含/lib/lsb/init-functions,使用方式如下: source /lib/lsb/init-functions LSB自带的脚本应该仅仅依赖/bin/sh(/bin/sh并不总是符号链接到/bin/bash)

  •     start_daemon [-f] [-n nicelevel] [-p pidfile] pathname [args] 将指定的程序运行为守护进程(daemon).start_daemon会检查对应的程序是否已经在运行,如果是,它不会再运行一次,除非使用-f参数.如果使用-n参数指定了nicelevel(参考nice(1)),start_daemon 应该返回LSB定义的退出代码. 如果程序运行成功,该函数返回为0,否则返回为非0.

  •     killproc [-p pidfile] pathname [signal] 停止指定的程序.该程序应该通过pidofproc函数找到(下面描述).如果指定了signal,则通过给kill指令传递-signal_name或-signal_number参数来终止程序,如果没有,则先使用SIGTERM信号,如果无法终止,再使用SIGKILL信号.LSB兼容的应用程序可以使用basename而不一定是pathname. killproc应该返回LSB预定义的退出码.调用时,如果没有使用signal参数,该函数返回为0,假如程序已经停止,否则返回为非0.如果指定了signal参数,只有在程序还在运行的情况下,函数返回为0.

  •     pidofproc [-p pidfile] pathname 该函数返回特定守护进程的一个活多个pid号.如果能找到/var/run/basename.pid文件,则返回该文件的值.如果-p参数指定,则返回该参数指定文件的内容. LSB兼容的程序可以使用basename而不非得是pathname.pidofproc应该返回LSB预定义的的退出码,以便给status动作使用.如果程序正在运行,他应该返回为0,否则为非0.

  •     log_success_msg "message" 打印一条成功消息,消息长度最好控制在60个字符内

  •     log_failure_msg "mesage" 打印一条失败消息,消息长度最好控制在60个字符内

  •     log_warning_msg "message" 打印一条警告消息,消息长度最好控制在60个字符内

chkconfig

    为了使得chkconfig能识别并能管理init脚本,需要在脚本第二行(第一行是#!/bin/bash)其增加下面这样几行:

#
# chkconfig: 35 80 5
# description: some description about this script
# processname: foo

检测LSB兼容性

  •     服务没有启动时,执行start操作 /etc/init.d/some_service start; echo $? 预期结果服务启动;start操作的返回值为0。

  •     服务已经启动,执行status操作 /etc/init.d/some_server status; echo $? 预期结果服务仍在运行,status操作显示服务正在运行并且返回值为0。

  •     服务已经启动,执行start操作 /etc/init.d/some_service start; echo $? 预期结果服务仍在运行,start操作返回值为0。

  •     服务已经启动,执行stop操作 /etc/init.d/some_service stop; echo $? 预期结果服务停止,stop操作的返回值为0。

  •     服务已经停止,执行status操作 /etc/init.d/some_service status; echo $? 预期结果服务保持停止,status操作显示服务已经停止并且返回值为3。

  •     服务已经停止,执行stop操作 /etc/init.d/some_service stop; echo $? 预期结果服务保持停止,stop操作返回值为0。

  •  

加载内核 执行init程序

  /etc/rc.d/rc.sysinit # 由init执行的第一个脚本

  /etc/rc.d/rc $RUNLEVEL # $RUNLEVEL为缺省的运行模式

  /etc/rc.d/rc.local #相应级别服务启动之后、在执行该文件(其实也可以把需要执行的命令写到该文件中) /sbin/mingetty # 等待用户登录

  在Redhat中,/etc/rc.d/rc.sysinit主要做在各个运行模式中相同的初始化工作,包括: 调入keymap以及系统字体 启动swapping 设置主机名 设置NIS域名

  检查(fsck)并mount文件系统打开quota 装载声卡模块设置系统时钟等等。

  /etc/rc.d/rc则根据其参数指定的运行模式(运行级别,你在inittab文件中可以设置)来执行相应目录下的脚本。

  凡是以Kxx开头的 ,都以stop为参数来调用;凡是以Sxx开头的,都以start为参数来调用。

  调用的顺序按xx 从小到大来执行。

  (其中xx是数字、表示的是启动顺序)例如,假设缺省的运行模式是3,/etc/rc.d/rc就会按上述方式调用

  /etc/rc.d/rc3.d/下的脚本。

  值得一提的是,Redhat中的运行模式2、3、5都把/etc/rc.d/rc.local做为初始化脚本中

  的最后一个,所以用户可以自己在这个文件中添加一些需要在其他初始化工作之后,登录之前执行的命令。 init在等待/etc/rc.d/rc执行完毕之后(因为在/etc/inittab中/etc/rc.d/rc的

  action是wait),将在指定的各个虚拟终端上运行/sbin/mingetty,等待用户的登录。 至此,LINUX的启动结束。

  2)init运行级别及指令 一、什么是INIT:

  init是Linux系统操作中不可缺少的程序之一。

  所谓的init进程,它是一个由内核启动的用户级进程。

  内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。所以,init始终是第一个进程(其进程编号始终为1)。

  内核会在过去曾使用过init的几个地方查找它,它的正确位置(对Linux系统来说)是/sbin/init。如果内核找不到init,它就会试着运行/bin/sh,如果运行失败,系统的启动也会失败。

  二、运行级别

  那么,到底什么是运行级呢?

  简单的说,运行级就是操作系统当前正在运行的功能级别。

  这个级别从1到6 ,具有不同的功能。 不同的运行级定义如下

  # 0 -停机(千万不能把initdefault 设置为0 )

  # 1 -单用户模式 # s init s = init 1

  # 2 -多用户,没有 NFS

  # 3 -完全多用户模式(标准的运行级)

  # 4 -没有用到

  # 5 -X11 多用户图形模式(xwindow)

  # 6 -重新启动 (千万不要把initdefault 设置为6 )

  这些级别在/etc/inittab 文件里指定。

  这个文件是init 程序寻找的主要文件,最先运行的服务是放

  在/etc/rc.d 目录下的文件。

  在大多数的Linux 发行版本中,启动脚本都是位于 /etc/rc.d/init.d中的。

  这些脚本被用ln 命令连接到 /etc/rc.d/rcn.d 目录。(这里的n 就是运行级0-6) 3):

  ---------------------------

  chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息。谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接。

  使用语法:

  chkconfig [--add][--del][--list][系统服务] 或 chkconfig [--level <等级代号>][系统服务][on/off/reset]

  chkconfig在没有参数运行时,显示用法。如果加上服务名,那么就检查这个服务是否在当前运行级启动。如果是,返回true,否则返回false。如果在服务名后面指定了on,off或者reset,那么chkconfi 会改变指定服务的启动信息。on和off分别指服务被启动和停止,reset指重置服务的启动信息,无论有问题的初始化脚本指定了什么。on和off开关,系统默认只对运行级3,4,5有效,但是reset可以对所有运行级有效。

  参数用法:

  --add  增加所指定的系统服务,让chkconfig指令得以管理它,并同时在系统启动的叙述文件内增加相关数据。

  --del  删除所指定的系统服务,不再由chkconfig指令管理,并同时在系统启动的叙述文件内删除相关数据。

  --level<等级代号>  指定读系统服务要在哪一个执行等级中开启或关毕。

  等级0表示:表示关机

  等级1表示:单用户模式

  等级2表示:无网络连接的多用户命令行模式

  等级3表示:有网络连接的多用户命令行模式

  等级4表示:不可用

  等级5表示:带图形界面的多用户模式

  等级6表示:重新启动

  需要说明的是,level选项可以指定要查看的运行级而不一定是当前运行级。对于每个运行级,只能有一个启动脚本或者停止脚本。当切换运行级时,init不会重新启动已经启动的服务,也不会再次去停止已经停止的服务。

  chkconfig --list [name]:显示所有运行级系统服务的运行状态信息(on或off)。如果指定了name,那么只显示指定的服务在不同运行级的状态。

  chkconfig --add name:增加一项新的服务。chkconfig确保每个运行级有一项启动(S)或者杀死(K)入口。如有缺少,则会从缺省的init脚本自动建立。

  chkconfig --del name:删除服务,并把相关符号连接从/etc/rc[0-6].d删除。

  chkconfig [--level levels] name:设置某一服务在指定的运行级是被启动,停止还是重置。

  运行级文件:

  每个被chkconfig管理的服务需要在对应的init.d下的脚本加上两行或者更多行的注释。第一行告诉chkconfig缺省启动的运行级以及启动和停止的优先级。如果某服务缺省不在任何运行级启动,那么使用 - 代替运行级。第二行对服务进行描述,可以用 跨行注释。

  例如,random.init包含三行:

  # chkconfig: 2345 20 80

  # description: Saves and restores system entropy pool for

  # higher quality random number generation.

  使用范例:

  chkconfig --list #列出所有的系统服务

  chkconfig --add httpd #增加httpd服务

  chkconfig --del httpd #删除httpd服务

  chkconfig --level httpd 2345 on #设置httpd在运行级别为2、3、4、5的情况下都是on(开启)的状态

  chkconfig --list #列出系统所有的服务启动情况

  chkconfig --list mysqld #列出mysqld服务设置情况

  chkconfig --level 35 mysqld on #设定mysqld在等级3和5为开机运行服务,--level 35表示操作只在等级3和5执行,on表示启动,off表示关闭

  chkconfig mysqld on #设定mysqld在各等级为on,“各等级”包括2、3、4、5等级

  如何增加一个服务:

  1.服务脚本必须存放在/etc/ini.d/目录下;

  2.chkconfig --add servicename

  在chkconfig工具服务列表中增加此服务,此时服务会被在/etc/rc.d/rcN.d中赋予K/S入口了;

  3.chkconfig --level 35 mysqld on

  修改服务的默认启动等级。

 

#!/bin/bash
#nginx Start script for the Nginx HTTP Server
# chkconfig: – 99 50
#虽然前面带#号,是注释,但要用chkconfig命令注册开机启动服务器的话,该句必不可少,格式也不能错!# chkconfig: – 99 50 冒号的3个参数的含义:
(第一位(X):是指定该脚本在哪个系统启动级别下运行(关于linux启动级别将在别的博文中介绍),比如你需要在3,4,5上运行,那么第二位就设置成345,我这里用的是”-”,代表在2,3,4,5上都运行。
第二位(Y):系统启动时,服务启动顺序。(需要注意的是,有的程序依赖与别的程序的话,启动顺序就要注意了,比如A程序的启动依赖于B程序的启动,那么A程序的这个值一定要比B程序大。)
第三位(Z):系统终止时,服务终止顺序。)
# description: Nginx is a high-performance web and proxy server.
#该句也必不可少,理由同上,你程序的描述和间接,而非本启动脚本。
#设置变量
nginxd=/usr/local/nginx/sbin/nginx
nginx_config=/usr/local/nginx/conf/nginx.conf
nginx_pid=/usr/local/nginx/logs/nginx.pid
#保存退出状态的变量,初始值为0(在linux一般0表示成功,表示OK,非0表示异常,不OK)
RETYAL=0
prog="nginx"
#程序的启动参数,这个很重要哦,那个–dameon参数是必不可少的,-4表示只在ipv4上监听,如果你要加更多参数,你需要参照/usr/bin/rsyncd –daemon –help后的帮助信息
OPTIONS="--daemon -4"
#Source function library.在当前shell中运行的函数库文件(在functions中定义了很多函数,在这里可以调用,系统提供的函数文件,这里面实现了很多函数和环境变量,比如start的时候,红色的字显示OK就是这个文件的功劳。)
. /etc/rc.d/init.d/functions
#Source network configuration.
. /etc/sysconfig/network
#Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -x $nginxd ] || exit 0
#Start nginx daemons function.定义函数
start() {
#判断程序是否存在,否则异常退出。
[ -x $nginxd ] || \
         { echo “FATAL: No such programme”;exit 4; }
#判断配置文件是否存在,否则异常退出。
[ -f $nginx_config ] || \
         { echo “FATAL:Config file does not exist”;exit 6; }
#判断程序是否运行,否则异常退出。
if [ -e $nginx_pid ];then
         echo "nginx already running...."
         exit 1
fi
#显示信息,依赖于. /etc/rc.d/init.d/functions
         echo -n $"Starting $prog:"
#调用functions里的daemon函数来启动nginx(daemon()函数主要用于希望脱离控制台,以守护进程形式在后台运行的程序。)
         daemon $nginxd -c ${nginx_config} $OPTIONS
#把daemon函数调用的结果保存到RETVAL里
         RETVAL=$?
         echo
#判断RETVALR值,如果是0执行成功,则生成锁文件(锁文件主要用来判断程序是否运行)
         [ $RETVAL = 0 ] && touch /var/lock/subsys/nginx
#终止函数,并返回$RETVAL的值(通常用于函数的结束, 本身这段代码也是个函数,所以我们也要返回,返回RETVAL的值)
         return $RETVAL
}
#Stop nginx daemons functions.
stop() {
         echo -n $"Stoping $prog:"
#killproc也在. /etc/rc.d/init.d/functions里面定义
         killproc $nginxd
         RETVAL=$?
         echo
         [ $RETVAL = 0 ] && rm -f /var/lock/subsys/nginx /usr/local/nginx/logs/nginx.pid
}
reload() {
         echo -n $"Reloading $prog:"
         #kill -HUP `cat ${nginx_pid}`
         killproc $nginxd -HUP
         RETVAL=$?
         echo
}
#See how we were called.
case "$1" in
start)
         start
         ;;
stop)
         stop
         ;;
reload)
         reload
         ;;
restart)
         stop
         start
         ;;
#status在. /etc/rc.d/init.d/functions里有定义
status)
         status $prog
         RETVAL=$?
         ;;
#输入其他内容提示以下内容
*)
         echo $"Usage:$prog{start|stop|restart|reload|status|help}"
         exit 1
esac
exit $RETVAL
#################################################################
[root@manor nginx-1.0.12]# chmod 775 /etc/rc.d/init.d/nginx
[root@manor nginx-1.0.12]# /etc/rc.d/init.d/nginx restart
Stoping nginx:                                             [确定]
正在启动 nginx:                                         [确定]
[root@manor nginx-1.0.12]# service nginx restart
Stoping nginx:                                             [确定]
正在启动 nginx:                                         [确定]
[root@manor nginx-1.0.12]# chkconfig nginx on
posted @ 2016-09-06 10:40  bdoooooog  阅读(5008)  评论(0编辑  收藏  举报