Linux/Ubuntu服务自启动原理剖析及三种实现方式

news2024/9/29 5:34:42

面向Linux系统,并非只是Ubuntu;系统版本不同,配置上可能有所不同。

1、自启动的原理剖析

1.1、 运行等级

Linux分了7个运行等级,分别用数字0,1,2,3,4,5,6表示,每个运行等级支持的功能不一样

  • 0:关机 (init 0 关机)

  • 1:单用户模式 (应用场景:管理员在配置系统的时候,不希望有人登录)

  • 2:无网络连接的多用户命令行模式

  • 3:有网络连接的多用户命令行模式

  • 4:系统不可用

  • 5:带图形界面的多用户模式 (一般安装默认的运行级别, 可以编辑 /etc/inittab来修改默认运行级别)

  • 6:重新启动 (init 6==reboot)

1.2、 运行等级原理

  • /etc/rc.d/init.d 下有很多服务程序脚本(支持start/restart/stop操作的shell脚本)

  • /etc/rc.d有7个rcN.d目录,对应7个运行级别;N对应0~6,共7个数字

  • Ubuntu系统中没有rc.d目录,直接在etc目录下;(22新系统)

在这里插入图片描述

  • rcN.d目录下都是一些符号链接,都链接到init.d目录的服务脚本;命名规则:

    • K+两位数字+服务名:表示要关闭的服务;K:kill的意思,杀死,关闭

    • S+两位数字+服务名:表示要开启的服务;S:start的意思,开启,开始

    • 两位数字表示启动优先级

在这里插入图片描述

  • 查看系统的运行级别:runlevel

在这里插入图片描述

  • 系统启动后更新运行级别进入到对应的rcN.d目录,遍历对应的链接文件,并执行(开启或关闭)

  • init 0 关机,init 6 重启

1.3、自启动服务相关命令

1> chkconfig

RedHat系统下的命令

  • 显示开机可以自动启动的服务
chkconfig --list
  • 添加开机自动启动服务
chkconfig --add 服务名
  • 删除开机自动启动服务
chkconfig --del 服务名
  • 开机自启动/关闭开机自启动
# -level 35:运行在3和5模式
# on:开启
# off:关闭
chkconfig -level 35 服务名 on/off
  • 查看服务状态
chkconfig 服务名 status

2> sysv-rc-conf

Ubuntu下的命令sysv-rc-conf

在这里插入图片描述

  • 显示开机可以自动启动的服务
sysv-rc-conf --list

在这里插入图片描述

  • 开机自启动/关闭开机自启动
# -level 35:运行在3和5模式
# on:开启
# off:关闭
sysv-rc-conf -level 35 服务名 on/off

Ubuntu下 sysv-rc-conf命令的安装

# 基本安装步骤:
# apt 或 apt-get 都可以
apt-get update
apt-get install sysv-rc-conf

安装时可能遇到的问题

  • 没有公钥

在这里插入图片描述

# 下载公钥
# 最后的 C0B21F32 就是上面提示中缺少的公钥后8位数字
apt-key adv --recv-keys --keyserver keyserver.Ubuntu.com C0B21F32

在这里插入图片描述

  • 软件包安装时出错

在这里插入图片描述

原因分析:dpkg: 处理归档A时出错:
正试图覆盖 x.x,它同时被包含于软件包XX,在处理时有错误发生:B.deb

出现上述错误的原因是因为该文件因为之前的某个deb的安装已经有内容了,安装与他相关文件时,需要覆盖该文件,但是没有成功。参考自:正试图覆盖…它同时被包含于软件包…在处理时有错误发生…

解决办法:执行如下命令dpkg -i --force-overwrite /B.deb 强制覆盖安装错误的内容,B.deb是你需要安装的deb文件

在这里插入图片描述

2、自启动实现方式

2.1、方式一:rc.local

  • rc.local文件位置:/etc/rc.local,没有的话可以自行创建。系统在开机时会执行/etc/rc.local

  • Ubuntu中不能直接使用该方式;有解决方案;参考:ubuntu20.4 rc.local不运行解决办法

1> 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.

2> 添加执行命令

假如在/home/test下有一个测试的jar包 test.jar,需要开机自启动

# 打开编辑;如果rc.local不存在的话,会创建新的
vim /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.

# 后台运行jar
# 命令前面加:nohup;后面加:&
nohup java -jar /home/test/test.jar &

# 退出
exit 0

关于台后运行:在shell执行命令后加 & 是为了让应用程序在后台运行,rc.local也是一个脚本,主进程在运行这个脚本时必须能够返回,如果在这个脚本里面执行了一些死循环或者其他无法返回的任务,整个系统就很可能卡死在这里,无法启动,所以在这里运行的用户程序必须是能够返回或者本身就使用一些后台运行的进程。

# 赋予可执行权限
chmod 755 /etc/rc.local

3> 添加执行脚本文件

rc.local 中不直接添加执行命令,而是添加 .sh脚本文件,把具体的执行命令放入.sh文件中,这种方式更加优雅!如果配置项比较多时优势更明显。但是必须要给.sh脚本文件赋于相应的执行权限。脚本文件.sh可以放置在其它地方。

脚本文件:test.sh

#!/bin/bash
java -jar /home/test/test.jar
# 给脚本文件赋予可读可执行权限
# 7: 表示可读可写可执行
# 5: 表示可读可执行
chmod 755 /home/test/test.sh

rc.local 中添加

# 添加脚本文件的全路径名
nohup ./home/test/test.sh &

4> 删除自启动

删除相关.sh脚本文件,并删除rc.local中添加的相关命令即可

2.2、方式二:/etc/init.d

  • 将自己的脚本文件复制添加到/etc/init.d

  • 链接到自启动程序列表当中,在下次系统启动时,将会自动执行用户脚本

1> 复制脚本

复制脚本到/etc/init.d中;必须要放在这个文件夹中

  • 脚本文件
#!/bin/bash
nohup java -jar /home/test/test.jar &
# 给脚本文件赋予可读可执行权限
chmod 755 /home/test/test.sh
# 复制
cp /home/test/test.sh /etc/init.d/

2> 链接自启动程序列表

update-rc.d 命令其实就是把init.d中的脚本文件,在rcN.d中创建一个软链接;

# 切换目录
cd /etc/init.d
# 链接到自启动程序列表中
# update-rc.d  链接命令
# defaults  自启动程序列表
# 99 优先级;0~99之间,越大时,启动越靠后
update-rc.d test.sh defaults 99
# 警告信息:原因是脚本文件不规范
insserv: warning: script 'diodon' missing LSB tags and overrides  
  • 规范的脚本文件
#!/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  

nohup java -jar /home/test/test.jar &
  • Required-Start:运行这个脚本需要的环境

  • Required-Stop:停止这个脚本需要的环境

  • Default-Start:提供运行的运行级别

  • Default-Stop:不运行的运行级别

  • Description:描述

3> 删除自启动

# 切换目录
cd /etc/init.d

# 删除软链接
update-rc.d -f test.sh remove

# 删除 init.d中的脚本文
rm -rf test.sh

2.3、方式三(推荐):systemd

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

1> 查看systemd版本

# 查看版本
systemd --version
# 输出如下类似信息时,表示系统支持systemd
systemd 249 (249.11-0ubuntu3.6)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY -P11KIT -QRENCODE +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified

2> 添加配置文件

  • 在系统执行目标文件之前,需要为目标文件设置一个配置文件,以便系统在开机自启动时,可以根据配置文件确认其依赖、运行级别、运行环境等,只有这样系统才知道怎么正确地去运行目标文件

  • 配置文件的后缀:.service,比如:要运行/home/test/目录下的test.sh脚本,就需要添加一个配置文件 test.service

  • 配置文件 test.service

# ------ 单元模块 ------
[Unit]
# 运行软件的描述信息
Description=  
# 软件的文档
Documentation= 

# 因为软件的启动通常依赖于其他软件,这里是指定在哪个服务被启动之后再启动,设置优先级
After=network.target,mnt-data.mount

# 弱依赖于某个服务,目标服务的运行状态可以影响到本软件但不会决定本软件运行状态
Wants=
# 强依赖于某个服务,目标服务的状态可以决定本软件运行。
Requires=

# ------ 服务模块 ------
[Service]
# 执行启动命令时使用的脚本文件或文件的启动程序
ExecStart=/home/test/test.sh
# 执行关闭命令时使用的脚本文件
ExecStop=
# 执行重启命令时使用的脚本文件
ExecReload=/home/test/test.sh
# 软件运行方式,默认为simple
Type=simple

# ------ 安装模块 ------
[Install]
# 相当于设置软件,选择运行在linux的哪个运行级别,只是在systemd中不再有运行级别概念
WantedBy=multi-user.target

在上面的配置文件中,为了演示起见,将一些本来测试脚本不需要,但是又比较重要的配置项也写了出来,其实如果不需要可以删除,但是[Unit][Service][Install]这三个标签需要保留,如果某一项的依赖有多个,用逗号,作为分隔

  • 将配置文件放在 系统路径:/usr/lib/systemd/system 或者 用户路径:/etc/systemd/system 目录下

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

service文件示例

# ------ 单元模块 ------
[Unit]
# 服务描述
Description=test-server
# 服务依赖(网络连接之后启用)
After=network-online.target
# 服务依赖(在nss启动前)
Before=nss-lookup.target
# 弱依赖
Wants=network-online.target nss-lookup.target
# 强依赖
#Requires=

# ------ 服务模块 ------
[Service]
# 运行方式,默认为simple;该服务将立即启动
Type=simple
# 启用执行命令
ExecStart=/home/tuwer/envs/test/test.sh
# 关闭执行命令
ExecStop=/home/tuwer/envs/test/test.sh
# 重启执行命令
ExecReload=/home/tuwer/envs/test/test.sh
# 何时重启:当服务进程异常退出时
Restart=on-failure
# 重启间隔秒数
RestartSec=3s
# 进程在执行时的用户
User=tuwer

# ------ 安装模块 ------
[Install]
# 该服务所在的服务组;类似于运行级别
WantedBy=multi-user.target

3> 启动服务

systemctl start test.service

4> 查看服务是否运行

ps -ef|grep test.sh

5> 设置开机自启动

systemctl enable test.service
# 自启动设置成功;创建一个软链接
Created symlink /etc/systemd/system/multi-user.target.wants/test.service → /usr/lib/systemd/system/test.service. 
  • test.service放在/usr/lib/systemd/system/中,如果启动成功,就可以看到在/etc/systemd/system/multi-user.target.wants/目录下创建了一个/usr/lib/systemd/system/test.service文件的软链接,到这里设置开机自启动就完成了。

  • 两个目录分别假设为:A和B,如果把service文件放在A中,启动成功后,会在B中生成一个指向A中文件的软链接;如果把service文件放在B中,启动成功后,会在A中生成一个指向B中文件的软链接;

  • 类似于第二种方式中的 update-rc.d 命令

6> 查看服务状态

如果在重启系统后,test服务没有自启动,可以通过以下命令进行排查

# 查看 systemd 的运行日志
systemctl status test.service

7> 删除自启动

# 停止服务
systemctl stop test.service  
# 使服务失效
systemctl disable test.service

# 先切换到配置时放置的目录
cd /usr/lib/systemd/system/
# cd /etc/systemd/system/
# 删除 test.service
rm -rf test.service

8> systemctl命令汇总

  • systemctl start 服务名 开启服务

  • systemctl stop 服务名 关闭服务

  • systemctl status 服务名 显示状态

  • systemctl restart 服务名 重启服务

  • systemctl enable 服务名 开机启动服务

  • systemctl disable 服务名 禁止开机启动

  • systemctl daemon-reload 修改服务配置文件后需要重新加载服务

  • systemctl is-enabled 服务名 查询是否是自启动服务

  • systemctl list-units 查看系统中所有正在运行的服务

  • systemctl list-unit-files 查看系统中所有服务的开机启动状态

  • systemctl list-dependencies 服务名 查看系统中服务的依赖关系

  • systemctl mask 服务名 冻结服务

  • systemctl unmask 服务名 解冻服务

  • systemctl set-default multi-user.target 开机时不启动图形界面

  • systemctl set-default graphical.target 开机时启动图形界面

  • systemctl is-active 服务名 显示某个 Unit 是否正在运行

  • systemctl is-failed 服务名 显示某个 Unit 是否处于启动失败状态

  • systemd-analyze blame 查看每个服务的启动耗时

service服务配置文件样例

[Unit]
Description=ToDesk Daemon Service (服务描述)
After=network-online.target (服务依赖,再这些服务后启动本服务)
Before=nss-lookup.target (服务依赖,再这些服务前启动本服务)
Wants=network-online.target nss-lookup.target (与当前服务配合的其他服务,如果它们没有运行,当前服务不会启动失败)

[Service]
Type=simple (默认值,systemd认为该服务将立即启动)
ExecStart=/opt/todesk/bin/ToDesk_Service (启动当前服务的命令)
ExecStop=/bin/kill -SIGINT $MAINPID (停止当前服务时执行的命令)
Restart=on-failure (定义何种情况 Systemd 会自动重启当前服务,当前是仅在服务进程异常退出时重启)
RestartSec=3s (自动重启当前服务间隔的秒数)
User=root (设置进程在执行时使用的用户,当前是root)

[Install]
WantedBy=multi-user.target (表示该服务所在的服务组,当前是服务所在的服务组是multi-user.target)

service配置文件字段详解

[Unit]区块通常是配置文件的第一个区块,用来定义 Unit 的元数据,以及配置与其他 Unit 的关系。它的主要字段如下。

Description:简短描述

Documentation:文档地址

Requires:当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败

Wants:与当前 Unit 配合的其他 Unit,如果它们没有运行,当前 Unit 不会启动失败

BindsTo:与Requires类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行

Before:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动

After:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动

Conflicts:这里指定的 Unit 不能与当前 Unit 同时运行

Condition...:当前 Unit 运行必须满足的条件,否则不会运行

Assert...:当前 Unit 运行必须满足的条件,否则会报启动失败

[Service]区块用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段如下。

Type:定义启动时的进程行为。它有以下几种值。

Type=simple:默认值,执行ExecStart指定的命令,启动主进程

Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出

Type=oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行

Type=dbus:当前服务通过D-Bus启动

Type=notify:当前服务启动完毕,会通知Systemd,再继续往下执行

Type=idle:若有其他任务执行完毕,当前服务才会运行

ExecStart:启动当前服务的命令

ExecStartPre:启动当前服务之前执行的命令

ExecStartPost:启动当前服务之后执行的命令

ExecReload:重启当前服务时执行的命令

ExecStop:停止当前服务时执行的命令

ExecStopPost:停止当其服务之后执行的命令

RestartSec:自动重启当前服务间隔的秒数

Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog

TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数

Environment:指定环境变量

[Install]通常是配置文件的最后一个区块,用来定义如何启动,以及是否开机启动。它的主要字段如下。

WantedBy:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system目录下面以 Target 名 + .wants后缀构成的子目录中

RequiredBy:它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入/etc/systemd/system目录下面以 Target 名 + .required后缀构成的子目录中

Alias:当前 Unit 可用于启动的别名

Also:当前 Unit 激活(enable)时,会被同时激活的其他 Unit

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/429643.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python】【进阶篇】十八、Python爬虫获取动态加载数据

目录十八、Python爬虫获取动态加载数据18.1 确定网站类型18.2 影片详情信息18.3 影片总数量18.4 影片类型与类型码18.5 编写完整程序十八、Python爬虫获取动态加载数据 如何获取电影“分类排行榜”中的电影数据(电影),比如输入“剧情”则会输…

用EasyX图形库画一个哆啦A梦

继续说图形库,加一点实战用图形画图(用来巩固代码): rectangle这个函数 四个参数,左上角坐标的x,y值,右下角坐标的x,y值;因为只要有两个点,就可以以它们的横坐标之差为长&#xff…

三范式建模和维度建模,到底该选哪一个?

编辑导语:当你需要从头开始设计数据仓库时,你会选择哪种建模方式?也许,你会从三范式建模和维度建模二者中选择。但是这二者有其各自的适用范围,具体选择哪种方法,还需要回归至业务层。本篇文章里&#xff0…

day-004-链表-两两交换链表中的节点、删除链表的倒数第N个节点、链表相交、环形链表II

两两交换链表中的节点 题目建议:用虚拟头结点,这样会方便很多。 题目链接/文章讲解/视频讲解 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* Li…

手麻系统源码,手术麻醉管理系统源码,二次开发方便快捷

手术麻醉管理系统源码,手麻系统源码,C# .net 桌面软件 C/S版 手术麻醉管理系统采用下拉式汉化菜单,界面友好,实用性强,设有与住院、病区、药房等系统的软件接口。 文末获取联系! 开发语言:C# …

4.1 随机变量的数学期望

学习目标: 如果我想学习随机变量的数学期望,我可能会采取以下步骤: 掌握概率论基础知识:在学习随机变量的期望之前,我需要了解概率论的基本概念,例如概率、随机变量、概率密度函数等。 学习数学期望的定义…

算法总结---最常用的五大算法(算法题思路)

一、总结 一句话总结: 【明确所求:dijkstra是求点到点的距离,辅助数组就是源点到目标点的数组】 【最简实例分析:比如思考dijkstra:假设先只有三个点】 1、贪心算法是什么? 当前看来最好的选择 局部最…

第二章(2):从零开始掌握PyTorch基础知识,打造NLP学习利器

第二章(2):从零开始掌握PyTorch基础知识,打造NLP学习利器! 目录第二章(2):从零开始掌握PyTorch基础知识,打造NLP学习利器!1. Pytorch基础1.1 Pytorch安装1.1.…

计算机网络考试复习——第四章 4.1 4.2.1 4.2.2

网络层传输的单位是IP数据报 4.1 网络层的几个重要概念 网络层提供的两种服务:网络层应该向运输层提供怎样的服务?面向连接还是无连接? 在计算机通信中,可靠交付应当由谁来负责?是网络还是端系统? 面向连…

X79G Xeon 2630v2 电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网,转载需注明出处。(下载请直接百度黑果魏叔) 硬件型号驱动情况 主板X79G 处理器Intel Xeon 2630v2已驱动 内存32g (16*2 2666MHZ)已驱动 硬盘Intel 760p 512GB已驱动 显卡RX 470已驱动 声卡瑞昱 英特尔 High De…

硬件外设使用方法——GPIO

【硬件外设使用】——GPIO用法GPIO基本概念GPIO应用pyb与micropython什么是pyb什么是micropythonpyb与micropython关系GPIO在micropython中的用法什么是pyb库pyb库中的GPIO用法micropython下的GPIO用法经过与硬件群的小伙伴商量,决定直接找个板子讲实战了- -。 本部…

qt动态加载qss 更好的推荐方式

1、编写QRC资源文件[window和linux通用] 2、过rcc程序生成rcc资源文件 生成2进制数据: 通过控制台窗口执行以下命令,会把qrc中的资源文件写成二进制数据保存 rcc.exe -binary .\resuorce.qrc -o .\resuorce.rcc 生成16进制数据: 通过控制台窗…

JavaSE学习进阶day03_02 内部类

第二章 内部类(最难的) 2.1 概述 2.1.1 什么是内部类 将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。可以把内部类理解成寄生,外部类理解成宿主。 2.1.2 什么时候使用内部类 一个事物内…

STM32驱动SIM900A短信模块

简介:STM32F103C8T6驱动SIM900A短信模块源码介绍。 开发平台:KEIL ARM MCU型号:STM32F103C8T6 传感器型号:SIM900A 特别提示:驱动内可能使用了某些其他组件,比如delay等,在文末外设模板下载…

协议篇之以太网协议基础概念

协议篇之以太网协议基础概念一、写在前面二、什么是以太网三、以太网TCP/IP协议分层四、MAC地址与IP地址五、写在后面一、写在前面 在学习了串口协议后,发现通过串口传输数据,数据传输的速率较慢,无法符合高速率传输场景下的要求,…

PXE+Kickstart自动化安装操作系统

文章目录PXEKickstart 完美自动化部署系统理论知识:1、PXE2、DHCP实践实验:1、DHCP服务器配置2、TFTP服务器配置3、HTTP服务器安装4、PXE配置5、Kickstart实践配置PXEKickstart 完美自动化部署系统 理论知识: 无人值守原理:Kick…

飞行机器人专栏(十一)-- 空中机器人综合健康管理系统

目录 一. 综合健康管理系统架构 1. 系统架构: 2. 故障诊断算法: 3. 预测维护策略: 4. 安全与隐私: 5. 用户友好性: 6. 模块化与可扩展性: 7. 与其他系统集成: 8. 考虑环境因素&#xf…

获取文件内容方法使用说明

一、是什么? sikuli设备新增了一个获取文件内容的方法,该方法可以传入指定路径读取文件内容,方便后续做打印,对比等工作 二、怎么用? 1.文件绝对路径,例如 windows:F:\cn_sonic\sonic-agent…

abbyy finereader15下载安装使用及功能介绍

今天给大家分享一款一款真正的专业OCR,它不仅支持多国文字,还支持彩色文件识别、自动保留原稿插图和排版格式以及后台批处理识别功能,使用者再也不用在扫描软件、OCR、WORD、EXCEL之间换来换去了,处理文件会变的就像打开已经存档的…

RabbitMQ安装教程(Mac)

1、RabbitMQ是采用Erlang语言开发的,所以系统环境必须提供Erlang环境。 brew install rabbitmq前提必须是mac安装了HomeBrew(软件包管理系统),以下都是基于mac版本的。 等大概十几分钟 brew services start rabbitmq;RabbitMQWeb…