06 开机自启动
Linux初始化系统
想要设置开发板的某程序开机时自启动,有多种方式,本质上是使用了Linux的初始化系统(在linux内核启动后期会尝试加载用户空间的
init程序,init程序是由内核启动的第一个用户空间程序(PID为1),该程序负责启动用户空间的服务和程序),init程序由初始化系统提供:
可以通过以下方法查看系统的init进程到底是谁:
法1:


法2:pstree -p
Busybox
BusyBox 是一个高度集成的嵌入式Linux工具集,它既是一个轻量级初始化系统,也是一个精简版的Unix命令集合。它的核心设计目标是用最小的空间提供完整的Linux系统功能
BusyBox 提供了一个简化的init程序,用于替代传统的 SysVinit或 systemd,它的init程序有2种实现形式:
(1) 传统 SysVinit 风格
配置文件:
/etc/inittab启动流程:
- 内核启动后执行
/sbin/init(通常是 BusyBox 的符号链接) - BusyBox 读取
/etc/inittab,定义运行级别和启动脚本 - 执行
/etc/init.d/中的脚本(如rcS、rc.local)
示例
/etc/inittab:1
2
3
4::sysinit:/etc/init.d/rcS
::askfirst:/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a- 内核启动后执行
(2) 简化的 BusyBox init
- 如果没有
/etc/inittab,BusyBox 会执行默认行为: - 挂载
/proc和/sys - 运行
/etc/init.d/rcS(如果存在) - 启动一个登录 shell(如
/bin/sh)
System V Init
利用Linux的System V Init机制,它主要依靠内核启动的第一个用户进程initd来运行一些脚本来实现
内核启动后运行
/sbin/initinit 读取
/etc/inittab确定默认运行级别- SystemV给出7个运行级别,分别对应rc0.d~rc6.d目录

- 并且还有个
rcS.d目录,它在所有运行级别之前运行
- SystemV给出7个运行级别,分别对应rc0.d~rc6.d目录
执行相应运行级别的rc脚本(如
/etc/rc.d/rcX.d)rcX.d脚本按顺序执行该目录下的服务脚本链接
用该方法的好处主要是可以控制各个脚本的启动顺序
具体操作:
- 在
/etc/init.d/目录下添加自启动脚本
Linux 开机的时候,会加载运行 /etc/init.d 目录下的程序,因此我们可以把想要自动运行的脚本放到这个目录下即可。系统服务的启动就是通过这种方式实现的
- 添加完后务必设置文件的可执行权限
- 脚本必须以S或者K开头,比如:S01syslogd 、S02klogd 、S02sysctl 、S40network,S代表启动、K代表关机,这些脚本按数字升序依次执行
缺点
- 启动时间长。
init进程是串行启动,只有前一个进程启动完,才会启动下一个进程 - 启动脚本复杂。
init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长
参考链接
systemd
定义
- systemd 是现代Linux系统的初始化系统与系统管理守护进程
- 它在 Linux 内核启动完成之后,作为第一个用户态进程(PID 1)运行,负责启动和管理系统中的所有其他进程。
- 它不仅仅是一个 init 程序,还包括一系列工具和守护进程,用于:
- 启动服务(Service Management)
- 依赖管理和并行化启动
- 日志管理(journalctl)
- 设备管理(udev 集成)
- 挂载点和自动挂载管理
- 定时任务(timer)替代 cron
几乎所有主流 Linux 发行版(Fedora、Red Hat、Debian、Ubuntu、Arch Linux 等)都已经采用 systemd 作为默认 init 系统
切换到systemd后,可能会保留SystemV初始化系统的一些文件,比如
/etc/init.d之类的,里面的文件不会直接起作用,而会被systemd转成适用于它的单元文件,再起作用。之所以这样做是为了兼容一些软件(它们在安装时使用了SystemV来进行自启动)
设计目标
- 更快的启动速度
- 使用依赖关系树和并行化启动(不像 SysVinit 顺序执行脚本)
- 利用 socket 激活(服务按需启动)
- 统一管理接口
- 所有服务、挂载点、套接字、设备等都被抽象为 unit,统一管理
- 增强可靠性
- 服务崩溃时自动重启
- 使用 cgroup 控制服务进程,防止“孤儿进程”
- 模块化和扩展性
- 提供
systemctl、journalctl等工具 - 替代部分传统组件(cron、inetd、syslog)
- 提供
核心概念
Unit(单元)
- systemd 中所有受管对象都叫 unit,以配置文件描述,文件放在:
/etc/systemd/system//run/systemd/system//lib/systemd/system/
- unit文件的类型包括:
- service:守护进程或一次性任务(如
nginx.service) - socket:套接字(systemd 可通过 socket 激活启动服务)
- device:内核设备(udev 管理)
- mount/automount:挂载点与自动挂载
- target:服务组(类似于 SysV 的运行级别 runlevel),可以看成同步点
- timer:定时器(替代 cron)
- slice:资源控制分组(基于 cgroup)
- scope:非 systemd 启动的外部进程组
- service:守护进程或一次性任务(如
配置文件(Unit 文件)
以 .service 为例:
1 | [Unit] |
[Unit]:描述、依赖关系[Service]:如何启动、停止、重启[Install]:该服务被挂到哪些 target 下启用(即开机自启设置)
Target(服务组)
- 类似 SysV 的运行级别 (runlevel)
- 它本身不执行命令,而是作为一个「分组」和「同步点」:
- 分组作用:把一堆服务组织在一起,统一管理(像运行级别 runlevel)
- 同步作用:让 systemd 知道某个阶段达成了,可以继续下一个阶段(类似「里程碑」)
- 常见 target:
graphical.target→ 图形界面模式multi-user.target→ 多用户命令行模式rescue.target→ 单用户维护模式default.target→ 系统默认启动级别(一般指向上面某个 target)
当 systemd 启动时,它会:
- 看到默认目标假如是
multi-user.target - 查找
multi-user.target依赖的所有target和service - 并行启动它依赖的target,然后再启动它自己的service
Journal(日志系统)
systemd-journald负责日志收集。统一收集:
- 内核日志
- init 输出
- 服务标准输出/错误输出
- syslog
使用
journalctl查看:1
2
3journalctl -u ssh.service # 查看 ssh 服务日志
journalctl -b # 查看本次启动日志
journalctl -f # 实时日志(类似 tail -f)
systemd 的运行流程
- Linux 内核启动完成后,执行
systemd作为 PID 1 - 读取默认目标(
default.target),加载对应的 unit - 解析 unit 之间的依赖关系,尽可能并行地启动服务
- 启动过程中会进行 socket/device/mount 等激活
- 最终进入目标运行级别(如
multi-user.target或graphical.target)
systemd 常用命令
服务管理
1 | systemctl start nginx.service # 启动服务 |
开机自启
1 | systemctl enable nginx.service # 设置开机自启 |
Target 管理
1 | systemctl isolate multi-user.target # 切换到多用户模式 |
查看信息
1 | systemctl list-units --type=service # 查看所有已加载的服务 |
使用systemd创建一个开机自启动的服务的流程是什么?
1.准备好要启动的进程
2.创建一个unit文件,比如xxx.service,并写好内容
3.通过sudo systemctl daemon-reload刷新一下unit文件
4.systemctl start xxx.service,systemctl status xxx.service启动服务并查看其状态是否正常
5.systemctl enable xxx.service设置开机自启动
