在系统或应用运维过程中,经常会自定义一些脚本来管理服务或应用,为了方便我们会把脚本放到 /etc/init.d/
目录下做成服务并使用 service 命令(centos 7 以前的发行版本)来管理。而要将服务添加到开机启动,我们就要使用 chkconfig 命令,所以在编写这类脚本时,必须符合 chkconfig 要求。
chkconfig 原理
使用 man 来看一下:
chkconfig - updates and queries runlevel information for system service
chkconfig
命令主要用来更新(启动或停止)和查询系统服务的运行级信息。
谨记: chkconfig
不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接。
使用语法
chkconfig [--add][--del][--list][系统服务]
或
chkconfig [--level <等级代号>][系统服务][on/off/reset]
使用例子
# 列出所有的系统服务
chkconfig --list
# 增加 named 服务
chkconfig --add named
# 删除 named 服务
chkconfig --del named
# 设置 named 在运行级别为2、3、4、5的情况下都是on(开启)的状态
chkconfig --level named 2345 on
添加服务
- 服务脚本必须存放在
/etc/ini.d/
目录下,并有执行权限; -
chkconfig --add <servicename>
在chkconfig工具服务列表中增加此服务,此时服务会被在/etc/rc.d/rcN.d
中赋予K(关机时执行)/S(开机时执行) 入口了; -
chkconfig --level 35 <servicename> on
,修改服务的默认启动等级。
/etc 目录下有一组 rc 开头目录,它们用来存放在各个运行级别下 linux 自动启动的服务:
/etc/rc0.d/ #运行模式 0 下需要启动的服务
/etc/rc1.d/ #运行模式 1 下需要启动的服务
/etc/rc2.d/ #运行模式 2 下需要启动的服务
/etc/rc3.d/ #运行模式 3 下需要启动的服务
/etc/rc4.d/ #运行模式 4 下需要启动的服务
/etc/rc5.d/ #运行模式 5 下需要启动的服务
/etc/rc6.d/ #运行模式 6 下需要启动的服务
编写 chkconfig 脚本说明
#!/bin/bash
# chkconfig: 35 99 05
# description: Test chkconfig
# file: /etc/init.d/foo
env > /tmp/ENVLOG
第二行中
35
:就是哪种 runlevel 下启动,如果是 -
代表默认的级别(2345)
99
:在开机启动脚本中的启动顺序(第99个启动),S99foo (越小优先权越高),格式:S+数字+服务名
05
:在关机时第 5 个停止, K05foo (越小优先权越高),格式:K+数字+服务名
其中的 S:代表开机 Start,K:代表关机 Kill
99
和 05
都是代表的顺序,所以在编写服务启动脚本时这行是必不可少的。 chkconfig
和 description
两行也是必不可少的,否则 chkconfig --add xxxx
服务时会报 "xxxx 服务不支持 chkconfig"。
chkconfig 脚本实例
写一个 lvs-dr 模式的 realserver 脚本,代码如下:
#!/bin/bash
# chkconfig: 35 12 90
# description: LVS DR mode, realserver config script
# file: /etc/init.d/realserver
VIPS=(172.16.14.252 172.16.14.253)
. /etc/rc.d/init.d/functions
case "$1" in
start)
# Start LVS-DR real server on this machine
/sbin/ifconfig lo down
/sbin/ifconfig lo up
echo "1" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" >/proc/sys/net/ipv4/conf/all/arp_announce
/sbin/sysctl -p >/dev/null 2>&1
for VI in ${!VIPS[@]}; do
/sbin/ifconfig lo:$VI ${VIPS[$VI]} netmask 255.255.255.255 broadcast ${VIPS[$VI]}
/sbin/route add -host ${VIPS[$VI]} dev lo:$VI
done
echo "RealServer Start OK"
;;
stop)
# Stop LVS-DR real server loopback device(s)
for VI in ${!VIPS[@]}; do
/sbin/ifconfig lo:$VI down
/sbin/route del ${VIPS[$VI]} >/dev/null 2>&1
done
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce
echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore
echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce
echo "RealServer Stoped"
;;
status)
# Status of LVS-DR real server
vips=$(echo "${VIPS[@]}" | tr ' ', '|')
haslo=`ifconfig -a | grep -Ec "$vips"`
hasroute=`netstat -rn | grep -Ec "$vips"`
if [ "$haslo" -lt 1 -o "$hasroute" -lt 1 ];then
echo "LVS-DR real server Stopped!"
else
echo "LVS-DR real server Running..."
fi
;;
*)
# Invalid entry
echo "$0: Usage: $0 {start|status|stop}"
exit 1
;;
esac
复习数组的语法
数组的操作语法,如下列出常见的操作:
语法 | 描述 |
---|---|
${!array[*]} | 获取数组所有键 |
${!array[@]} | 获取数组所有键 |
${array[*]} | 获取数组所有值 |
${array[@]} | 获取数组所有值 |
${#array[*]} | 获取数组的长度 |
${#array[@]} | 获取数组的长度 |
A[*]
与 A[@]
的区别: 当两者都没有用""
(引号)括起来的时候两者是一样的,但是有了 ""
:
-
@
:最大限度的保持原意,比如A[1]='a b' 那么这样输出的也是 a b 这是一个整体,而如果没有""
,这输出的是 a b 这是两个元素! -
*
:所有的元素都变成一个字符串了,也就是一个整体。
示例:
$ for i in "${a[@]}";do echo $i+'aa';done
1 2 3+aa
4 5 6+aa
7 8 9+aa
$ for i in "${a[*]}";do echo $i+'aa';done
1 2 3 4 5 6 7 8 9+aaa