Linux – rc.local/init.d/chkconfig/service/systemctl/rcN.d的区别与联系
SysV
SysV是最早的启动方式(在Upstart与systemd之前存在了几十年,并且现在也很多人在用),拿CentOS系统来说,在CentOS7之前,还一直用着SysV启动方式,chkconfig
/rc0.d-rc6.d
/init.d
/rc.local
/service
这些都是SysV启动方式里的东西。
init.d
目录在/etc/init.d/
,它是SysV启动方式里放置启动脚本的地方;rc0.d-rc6.d
目录在/etc/rc.d/rc0.d
–/etc/rc.d/rc6.d
,这7个目录分别代表SysV启动方式中的7个系统运行级别;chkconfig
用于操作/etc/init.d/
中的脚本,把它们创建符号链接到/etc/rc.d/rc0.d
–/etc/rc.d/rc6.d
,主要用于开机自启动;service
也是操作/etc/init.d/
中的脚本,主要用于手动启动、关闭、重启等;rc.local
是一个文件,我们一般把需要开机自启动的命令放到该文件中,用于实现开机自启动,是开启自启动的另一种方式,它实际路径在/etc/rc.d/rc.local
,但会有一个符号链接在/etc/rc.local
;- 这里很多目录以
.d
结尾,这个d
是directory
,即目录的意思,而rc.d/rc.local中的rc
是run command
的意思。
SysV系统运行级别
SysV启动方式有运行级别的概念,一般有0-6共7个运行级别(runlevel):
0:表示关机状态
1:表示单用户模式状态(又称s级别,s就single的首字母,single就是单个的意思,一般系统出现问题的时候会进入该状态,如root密码丢失等)
2:表示多用户模式,但是没有NFS功能
3:表示多用户模式(生产环境中的服务器默认运行状态)
4:系统保留
5:表示图形化界面状态
6:表示重启状态
关于SysV启动方式,请看:浅析Linux初始化init系统第一部分 – Sysvinit
设置系统级别为3:
init 3
查看当前系统级别(一般情况下服务器的运行级别都是3,即多用户模式):
runlevel
chkconfig的使用
列出所有的系统服务
chkconfig --list
列出某一个服务(httpd是服务名称,是apache http服务器)
chkconfig --list httpd
添加一个服务
chkconfig --add httpd
删除一个服务
chkconfig --del httpd
设置httpd在2,3,4,5运行级别开机自启动:
chkconfig --level httpd 2345 on
自己写一个服务
在/etc/init.d/
目录下创建一个文件test
(注意不要用”.sh”结尾),并把以下代码放进去,然后保存:
#!/bin/bash
#chkconfig:2345 66 22 #2345表示运行级别;开机顺序为66;关机顺序为22;把2345换成"-"则表示所有运行级别
#description:this is ckconfig test script
echo "hello,my name is $HOSTNAME"
给它添加可执行权限
chmod u+x ./test
随便进入“rc0-rc6”中的其中一个目录,比如我进入/etc/rc.d/rc3.d
,看一下这里面的文件,还没有test
。
使用chkconfig把test
添加到开机自启动:
chkconfig --add test
现在再看,已经有一个K22test
符号链接了,它指向的就是test
:
K22test -> ../init.d/test
用chkconfig查看:
chkconfig --list test
确实有了,不过全部都是off的:
test 0:off 1:off 2:off 3:off 4:off 5:off 6:off
使用chkconfig设置test
在级别3时开机自启动:
chkconfig test --level 3 on
使用chkconfig检查一下test
的当前状态:
chkconfig --list test
可以看到,当前状态是在级别3是on(正是前面我们设置的):
test 0:off 1:off 2:off 3:on 4:off 5:off 6:off
然后再去/etc/rc.d/rc3.d
查看test
的符号链接,你会发现符号链接已经由之前的K22test
变成现在的S66test
:
lrwxrwxrwx. 1 root root 14 Mar 23 02:00 S66test -> ../init.d/test
删除test在所有rcN.d中的符号链接:
chkconfig --del test
然后我们用service的方式来启动:
service test start
/etc/init.d/
目录就是service的工作目录,运行以上命令时,它会去/etc/init.d/
目录中找到文件名为test
的脚本,因为我们执行的是start
,所以它会去检测test
里面是否有start()
函数,如果有,它就会执行start()
函数里的命令,如果没有,那就是单纯把脚本运行一遍,就相当于我们手动运行./test
。
分析实验得出结果
由前面的test
实验我们得出,chkconfig --add test
命令会从/etc/init.d/
目录下查找名为test
的脚本,并把它创建一个符号链接(即软链接)到“rc0.d-rc6.d”共7个目录中,并且符号链接的名字为K+NN+test
,“NN”是两位数字。
“NN”中的N分别是多少,是由test文件里的一句注释来指定的:
#chkconfig: 2345 66 22
2345: 表示该脚本运行在2、3、4、5这四个运行级别,理论上chkconfig应该是往rc2.d、rc3.d、rc4.d、rc5.d这四个目录中创建符号链接的,但实际上我测试它是往七个rcN.d里都创建了符号链接(系统版本:CentOS release 6.10 (Final))。
66: 表示开机启动顺序,设置为on时,符号链接名字为“S开头+开机启动顺序+脚本名称”,所以最终名称为“S66test”,S
表示Start(开启)。
22: 表示关机关闭顺序,设置为off时,符号链接名字为“K开头+关机关闭顺序+脚本名称”,所以最终名称为“K22test”,K
表示Kill(关闭)。
另外,放到init.d
的启动脚本,未必要添加到chkconfig,经常有人直接用这样的方式直接使用:
sudo /etc/init.d/httpd start
或者结合service来使用:
service httpd start
只要放在/etc/init.d/
目录中的脚本,service都可以通过service 脚本名 start
来启动,如果脚本中没有start()
函数,那就相当于手动执行./脚本名
,如果脚本文件里有start()/stop()/restart()
之类的函数,那么service就做这些操作其实就是执行脚本里的函数,比如你可以看看/etc/init.d/sshd
,这个是用于开机启动sshd服务的,它里面就有start()/stop()/restart()
这些函数。
rc.local
相信很多人做开启自启动都是以下方式添加的(其中“commmd”是启动某个服务的命令):
echo 'commmd' >> /etc/rc.local
其实/etc/rc.local
是一个符号链接(软链接),真正的文件是在/etc/rc.d/rc.local
:
lrwxrwxrwx. 1 root root 13 Mar 22 22:01 /etc/rc.local -> rc.d/rc.local
rc.local
文件的开头有这句注释:
# This script will be executed after all the other init scripts.
# You can put your own initialization stuff in here if you don’t
# want to do the full Sys V style init stuff.
它的意思就是,你可以把你自己的初始化的东西放到这里(如果你不想做完整的SysV风格启动的话),“完整的SysV风格启动”就是前面我们说的,要写个脚本放到/etc/init.d/
目录中,并用chkconfig来做管理。
所以其实rc.local
文件一般是让你添加一些简单的开机自启动命令的,你不需要往“init.d”里添加后,再用chkconfig来管理,这样会简单很多。
而往“init.d”目录添加的,往往是内容比较多的脚本,比如某些软件官方发行的那些自启动都会往那里放,这些脚本里面往往会用shell写一些start/stop/restart方法,并做一些复杂一点的判断,一般都是为了保证程序能更好的运行。
systemd与systemctl
systemd是一种最新的Linux启动方式,以前是用SysV启动方式,后来Ubuntu开发了Upstart, systemd是在Upstart后出来的,据说比upstart更先进,而systemctl就是systemd的管理工具。
CentOS系统从CentOS7开启默认使用systemd来管理开机启动,并且它的功能远远不止设置程序开机自启动,它还管理了系统的方方面面,为些很多人觉得它太复杂,所以反对使用systemd。
以下只列出常用的几个命令:
# 启动nginx
systemctl start nginx
# 查看nginx启动状态
systemctl status nginx
# 关闭nginx
systemctl stop nginx
# 重启nginx
systemctl restart nginx
# 设置nginx开机启动
systemctl enable nginx
详细了解systemd请看以下两篇文章:
Systemd入门教程:命令篇
Systemd入门教程:实战篇
service
service最初是用于SysV
启动方式中,用于启动、停止、重启服务,具体功能与被启动的服务有关,被启动的服务存放在/etc/init.d/
下(实际上是/etc/rc.d/init.d
,因为/etc/init.d/
是软链到/etc/rc.d/init.d/
),所以其实被启动的服务是一个“启动脚本”,在里面有shell自己写了start函数,stop函数,然后service start/stop就是调用脚本里的start和stop函数(你可以自己找个shell看看,比如vim /etc/init.d/network
)。
但是,假如/etc/init.d/
下的启动脚本没有写start函数,service一样可以启动它,理由很简单,start就是把那个启动脚本里的shell都运行一遍嘛,你自己用./
的方式也能运行(而且service也是用这个原理)。
由于CentOS系统从CentOS7开始,用systemd代替了SysV启动方式,这时service为了兼容CentOS7,做了一层判断,如果是CentOS7,那么会自动调用systemctl来操作,否则还是去/etc/init.d/
找到对应的脚本来执行。
比如我在CentOS7上用service重启网卡,它实际上是使用systemctl(via systemctl):
使用which service
命令可以找到service命令在哪里,然后你可以直接用vim打开它,你会发现,service
命令只不过是个shell脚本罢了。
参考:
Difference between systemctl and service commands
linux学习笔记-chkconfig原理及应用
[…] 这里要特别注意,稍微了解Linux的童鞋都知道,service命令是用于启动Linux的进程的(参见这里),但在这里是例外,service iptables start并没有启动一个进程,你无法用ps aux | grep iptables的方式看到一个叫iptables的进程,你只能用service iptables status去查看它的状态。 […]
[…] 这里要特别注意,稍微了解Linux的童鞋都知道,service命令是用于启动Linux的进程的(参见这里),但在这里是例外,service iptables start并没有启动一个进程,你无法用ps aux | grep iptables的方式看到一个叫iptables的进程,你只能用service iptables status去查看它的状态。 […]