跳至主要內容

Linux自启动

soulballad环境配置LinuxLinux约 2913 字大约 10 分钟

Linux自启动

Linux 自启动 假死自启动

在linux的使用过程中,我们经常会碰到需要将某个自定义的应用程序设置为开机自启动以节省操作时间,这里提供两个设置开机自启动的方法。

方法一:在 /etc/rc.local 添加

ubuntu在开机过程之后,会执行 /etc/rc.local (注意 /etc/init.d 中也有个 rc.local,不要弄混了)文件中的脚本程序,初始情况下,这个文件内容是这样的:

downey@ubuntu:~$ cat /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.  

并不包含其它内容,用户可以在里面添加需要开机执行的脚本命令,这里以diodon粘贴板工具为例,如果我要开机运行diodon进程,在文本中添加:

downey@ubuntu:~$ cat /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
./usr/bin/diodon &
exit 0

方法二:在/etc/init.d/ 目录下添加

添加用户进程

该方式就是将自己的用户脚本添加到 /etc/init.d 并链接到自启动程序当中。

还是以diodon软件来举例,我编辑一个运行 diodon 的脚本:

#!/bin/bash
./usr/bin/diodon  

将其命名为diodon.sh,并用指令:

chmod +x diodon.sh
sudo cp diodon.sh /etc/init.d/  

将文件放到 /etc/init.d 目录中,然后将 diodon.sh 脚本链接到开机运行序列中:

cd /etc/init.d
sudo update-rc.d diodon.sh defaults 96
insserv: warning: script 'diodon' missing LSB tags and overrides  

这样重新启动时,就可以看到diodon.sh正在运行了。

sudo update-rc.d diodon.sh defaults 96

在这条指令中,update-rc.d是一个系统的链接工具。

而 defaults 96 则是指定了脚本的开机顺序,数字为 0-99,数字越大执行优先级越低,用户添加的程序最好选择低优先级的执行顺序,因为很可能我们的用户程序会依赖一些系统的应用进程,例如如果应用程序要使用到网络部分,就先得让网络后台程序先初始化完毕。

看到这里,细心的朋友已经发现了,在链接脚本时有一个警告:

insserv: warning: script 'diodon' missing LSB tags and overrides  

作为一个菜鸟而言,是不敢忽视任何警告的,所以只好求助google,解决办法是在自己的脚本中的 #!/bin/bash 下添加:

#### BEGIN INIT INFO
# Provides:          downey
# Required-Start:    $local_fs $network
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: tomcat service
# Description:       tomcat service daemon
#### END INIT INFO  

添加这些的目的是告诉系统一些关于这个启动脚本的具体信息,其中比较重要的有这几项:

# Required-Start:   运行这个脚本需要的环境
# Required-Start:   停止这个脚本需要的环境
# Default-Start:    提供运行的运行级别
# Default-Stop:     不运行的运行级别
# Description:      描述

关于linux下的运行级别参考: linux运行级别open in new window

删除用户进程

既然有添加就必然有删除,如果需要删除自定义开机运行脚本,输入:

sudo update-rc.d -f diodon remove

方法三:systemd开机自启动

上面提到的两种方式适用于经典的 system V 控制系统启动和关闭的情况,但是目前(2018年10月)在大多数发行版上都开始使用了systemd的系统软件控制方式,包括Ubuntu16,centos.systemd系统管理着linux下的进程运行,属于应用程序,不属于linux内核的范畴。

在systemd系统上设置开机自启动的方式也是非常简单的(尽管systemd这套软件管理工具并不简单)。

确定系统是否用了systemd

这里要注意的是,systemd是linux发行版上的预装工具,用来管理系统软件的启动运行和结束,所以通常来说,这套东西是依赖于发行版的,如果系统使用了这一套工具,那么就可以使用它来管理进程,如果不是,即使你安装了它,它也不会被默认配置为系统管理工具。

查看系统是否使用systemd工具我们可以使用如下的指令:

systemd --version

如果系统返回如下类似的信息,表明该系统是由systemd工具来管理软件:

systemd 232
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN

systemctl的使用

对软件的管理主要是同通过systemd工具中的systemctl命令,相比于之前的system V的控制方式,systemd显得更加简洁明了,对用户更加友好,拿httpd来举例:

#开启httpd服务:
sudo systemctl start httpd
#设置httpd服务自启动:
sudo systemctl enable httpd

至于关闭和取消自启动,大家心里应该有数了吧。

设置systemctl的服务文件

我们再回到重点,设置开机自启动。

我们要为目标设置一个配置文件,其实这是可以预想到的,linux作为一个复杂的系统,开机自启动涉及到的依赖、运行级别、运行环境等等问题肯定需要用户去指定,在启动的时候系统才知道怎么正确地去运行软件。这个配置文件固定以.service作为后缀,比如我们如果要运行/home/downey目录下的test.sh脚本,我们可以添加一个配置文件 test.service:

[Unit]
Description=
Documentation=
After=network.target
Wants=
Requires=

[Service]
ExecStart=/home/downey/test.sh
ExecStop=
ExecReload=/home/downey/test.sh
Type=simple

[Install]
WantedBy=multi-user.target

将文件放在 /usr/lib/systemd/system 或者 /etc/systemd/system 目录下,然后可以测试一下:

sudo systemctl start test.service  

然后你可以查看你的/home/downey/test.sh脚本是否已经运行,如果已经运行表示配置文件没有问题。然后可以键入:

sudo systemctl enable test.service  

设置test脚本开机启动。如果上一步没有出问题,这一步基本上也不会有什么问题,系统会打印出如下信息:

Created symlink /etc/systemd/system/multi-user.target.wants/test.service → /usr/lib/systemd/system/test.service.  

可以看到,这里在 /etc/systemd/system/multi-user.target.wants/ 目录下创建了一个 /usr/lib/systemd/system/test.service 文件的软链接,到这里设置开机自启动就完成了。

systemctl配置文件的简单解析

在上面的配置文件中,为了演示起见,我将一些本测试脚本不需要但是比较重要的配置项也写了出来,其实如果不需要可以删除,但是[Unit]/[Service]/[Install]这三个标签需要保留。
我们来一个个简单介绍一下配置项:

Description: 运行软件描述
Documentation: 软件的文档
After: 因为软件的启动通常依赖于其他软件,这里是指定在哪个服务被启动之后再启动,设置优先级
Wants: 弱依赖于某个服务,目标服务的运行状态可以影响到本软件但不会决定本软件运行状态
Requires: 强依赖某个服务,目标服务的状态可以决定本软件运行。
ExecStart: 执行命令
ExecStop: 停止执行命令
ExecReload: 重启时的命令
Type: 软件运行方式,默认为simple
WantedBy: 这里相当于设置软件,选择运行在linux的哪个运行级别,只是在systemd中不在有运行级别概念,但是这里权当这么理解。

如果有多项,用逗号作为分隔。

方法四:定时自重启

定时监测与假死重启的方式,使用crontab 定时任务监测进程,并且实时重启。

准备 自动启动脚本

举个例子,

vi /usr/local/presto_monitor.sh

#!/bin/sh

command="/usr/local/Presto/presto-server-0.100/bin/launcher run"
appname=presto-server
logfile=/usr/local/log/presto_monitor.log

#返回 ps -ef 出来的所有字符串中含有 $appname 的进程个数
checkrun=`ps -ef | grep $appname | grep -v "grep" | wc -l` 
echo "$appname 运行监测开始….."

#ps -ef | grep launcher | grep -v "grep" | wc -l
#while true
#do
#echo $checkrun

if [ 0 = $checkrun ]; then
  #进程不存在
  time2=$(date "+%Y-%m-%d %H:%M:%S")
  echo "$appname 服务宕机,正在重新启动"
  #echo "$appname 服务宕机,宕机时间为:"$time2>>$appname.log

  #./$appname $appname &logfile
  nohup $command >  $logfile  2>&1 &
  #nohup  /usr/local/Presto/presto-server-0.100/bin/launcher run  >  presto_run.log  2>&1 &

  sleep 1
  pid=$(ps -ef | grep -v 'grep' | egrep $appname| awk '{printf $2 " "}')   
  echo "$appname ($pid)重新启动成功!!!"
else
  #进程存在
  sleep 1

  pid=$(ps -ef | grep -v 'grep' | egrep $appname| awk '{printf $2 " "}')      
  echo "$appname ($pid) 服务运行正常...持续监控中"
fi

time=$(date "+%Y-%m-%d %H:%M:%S")
echo "本轮监测完毕,当前时间为:"$time
#done

#这里有一行

使用nohup命令后台运行命令之后,需要使用exit正常退出当前账户,这样才能保证命令一直在后台运行(es head插件有这个问题)。

command>out.file是将command的输出重定向到out.file文件,即输出内容不打印到屏幕上,而是输出到out.file文件中。如果不想要输出文件则修改 out.file 为 /dev/null。

2>&1 是将标准出错重定向到标准输出,这里的标准输出已经重定向到了out.file文件,即将标准出错也输出到out.file文件中。

最后一个&, 是让该命令在后台执行。

0-输入 1-输出 2-错误

crontab 定时任务

crontab:定时任务的守护进程,精确到分,设计秒的我们一般写脚本 -->相当于闹钟

​日志文件: ll /var/log/cron*

​编辑文件: vim /etc/crontab

​进程:ps -ef | grep crond ==> /etc/init.d/crond restart

​作用:定时备份,实时备份

centos7中启用rc-local

rc-local简介

大多时候我们可以在 /etc/rc.local 中写一些命令来启动自己的程序或服务,但是配置后无法启动,查看了下是 rc-local.service 未启动

[root@master ~]# systemctl enable rc-local.service
[root@master ~]# systemctl start rc-local.service
[root@master ~]# systemctl status rc-local.service 
● rc-local.service - /etc/rc.d/rc.local Compatibility
   Loaded: loaded (/usr/lib/systemd/system/rc-local.service; static; vendor preset: disabled)
   Active: inactive (dead)
Condition: start condition failed at Tue 2019-05-21 20:22:46 CST; 1s ago
           ConditionFileIsExecutable=/etc/rc.d/rc.local was not met

默认情况下,使用上面的命令无法启动 rc-local.service 服务,原因是需要两处文件都设置可执行权限,但是 /etc/rc.d/rc.local 默认没有可执行权限

解决方法

设置可执行权限

## 设置可执行权限
[root@master ~]# chmod +x /etc/rc.d/rc.local
[root@master ~]# chmod +x /etc/rc.local

启动并查看状态

[root@master ~]# systemctl start rc-local.service 
[root@master ~]# systemctl status rc-local.service 
● rc-local.service - /etc/rc.d/rc.local Compatibility
   Loaded: loaded (/usr/lib/systemd/system/rc-local.service; static; vendor preset: disabled)
   Active: active (exited) since Tue 2019-05-21 20:23:54 CST; 1s ago
  Process: 5141 ExecStart=/etc/rc.d/rc.local start (code=exited, status=0/SUCCESS)

May 21 20:23:54 master systemd[1]: Starting /etc/rc.d/rc.local Compatibility...
May 21 20:23:54 master systemd[1]: Started /etc/rc.d/rc.local Compatibility.

附录

rc.local

#!/bin/bash
# THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES

touch /var/lock/subsys/local

#start redis
#/usr/local/redis/bin/redis-server  /usr/local/redis/redis.conf
/usr/bin/su  - root  -c   "/usr/local/redis/bin/redis-server  /usr/local/redis/redis.conf"


#start nginx
#/usr/bin/su  - root  -c   "/usr/local/openresty/nginx/sbin/nginx  -c /usr/local/openresty/nginx/conf/nginx.conf"


# 启动zookeeper
/usr/bin/su  - root  -c   "/work/zookeeper/zookeeper-3.4.13/bin/zkServer.sh start"

# 启动 zookeeper集群
#/usr/bin/su  - root  -c   "/work/zookeeper/zookeeper_01/bin/zkServer.sh start"
#sleep 5s
#/usr/bin/su  - root  -c   "/work/zookeeper/zookeeper_02/bin/zkServer.sh start"
#sleep 5s
#/usr/bin/su  - root  -c   "/work/zookeeper/zookeeper_03/bin/zkServer.sh start"

# 启动 Nacos
/usr/bin/su  - root  -c   "/work/nacos/bin/startup.sh -m standalone"


#start springcloud

sleep 5s

/usr/bin/su  - root  -c   "/work/cloud-eureka-1.0-SNAPSHOT/bin/deploy.sh start"

sleep 10s

/usr/bin/su  - root  -c   "/work/cloud-config-1.0-SNAPSHOT/bin/deploy.sh start"


# 启动 kafka
/usr/bin/su  - root  -c   "nohup /work/kafka_2.12-2.2.0/bin/kafka-server-start.sh /work/kafka_2.12-2.2.0/config/server.properties  2>&1 &"


#启动 sentinel

# /usr/bin/su  - root  -c   "nohup java  -server -Xms64m -Xmx256m  -Dserver.port=8849   -Dcsp.sentinel.dashboard.server=localhost:8849 -Dproject.name=sentinel-dashboard -jar /work/sentinel-dashboard-1.7.1.jar  2>&1 &"


#sleep 2s
# 启动 rocketmq namenode
#/usr/bin/su  - root  -c   "nohup mqnamesrv -n 192.168.56.121:9876 &"


#sleep 30s
# 启动 rocketmq broker
#/usr/bin/su  - root  -c   "nohup sh mqbroker -n 192.168.56.121:9876 autoCreateTopicEnable=true -c /usr/local/rocketmq/rocketmq-all-4.5.2/conf/broker.conf &"

#sleep 5s
# 启动rocketmq-console
#/usr/bin/su  - root  -c   "nohup java  -server -Xms64m -Xmx256m  -jar /usr/local/rocketmq/rocketmq-console-1.0.1.jar --rocketmq.config.namesrvAddr='172.18.11.111:9876'  2>&1 &"

参考:

上次编辑于:
贡献者: soulballad