石家庄市网站建设_网站建设公司_网站制作_seo优化
2026/1/22 4:09:44 网站建设 项目流程

再也不用手动执行命令了,开机启动脚本帮你搞定一切

你有没有遇到过这样的情况:每次重启设备后,都要手动运行一堆命令来初始化系统、启动服务或者点亮某个LED?不仅麻烦,还容易遗漏。其实,Linux系统早已提供了强大的开机自启机制,只要设置一次,后续就能全自动执行。

本文将带你彻底搞懂如何在现代Linux系统(如Armbian)中配置开机启动脚本,告别重复操作。我们会从基础概念讲起,手把手教你创建并管理自启动任务,确保你不仅能用起来,还能理解背后的原理。


1. 理解Linux的启动管理系统:systemd vs init.d

在动手之前,先搞清楚“谁在控制开机流程”。这关系到你应该用哪种方式写启动脚本。

1.1 init.d(SysV init)——传统的方式

init.d是早期Linux使用的启动管理方式,它的核心逻辑很简单:

  • 所有启动脚本放在/etc/init.d/目录下
  • 系统根据/etc/rc*.d/中的软链接顺序执行这些脚本(比如S01xxx,S02xxx
  • 脚本自己负责处理 start、stop、restart 等动作

优点是简单直观,但缺点也很明显:

  • 不支持并行启动,拖慢开机速度
  • 没有依赖管理,容易出错
  • 日志分散,排查问题困难

1.2 systemd —— 现代系统的标准

如今几乎所有主流Linux发行版(包括Debian、Ubuntu及其衍生系统如Armbian)都默认使用systemd作为初始化系统(PID 1 进程)。

它通过.service单元文件来定义服务,具备以下优势:

  • 支持服务之间的依赖关系(例如:网络就绪后再启动Web服务)
  • 可以并行加载多个服务,显著提升启动速度
  • 自带日志系统(journalctl),便于调试
  • 提供丰富的控制策略:失败自动重启、超时检测、资源限制等

关键点:即使你在/etc/init.d/下写了脚本,现代系统也是由 systemd 兼容层去调用它。真正的“主角”始终是 systemd。


2. 如何验证你的系统使用的是 systemd?

别猜,直接看事实。打开终端,输入:

ps -p 1 -o comm=

如果输出结果是:

systemd

那就说明你的系统确实是用 systemd 作为初始化进程。

再进一步验证某个旧式 init.d 脚本是否被 systemd 接管:

systemctl status gpio-init.sh

你会发现,即便这是一个 shell 脚本,systemd 也会为它生成一个临时的服务单元进行管理。


3. 推荐做法:使用 systemd service 文件

虽然兼容 init.d,但我们强烈建议新项目直接使用.service文件。这样更规范、可控性更强、也更容易维护。

下面是一个完整的实践示例:让设备开机时自动运行一个自定义脚本。

3.1 编写实际要执行的脚本

假设我们想在开机时初始化一些GPIO引脚,并点亮一个状态灯。

创建脚本文件:

sudo nano /usr/local/bin/boot-init.sh

写入内容:

#!/bin/bash # 导出 GPIO 引脚 echo "6" > /sys/class/gpio/export 2>/dev/null echo "7" > /sys/class/gpio/export 2>/dev/null echo "8" > /sys/class/gpio/gpio6/direction"out" echo "in" > /sys/class/gpio/gpio7/direction echo "out" > /sys/class/gpio/gpio8/direction # 设置初始电平(点亮LED) echo "1" > /sys/class/gpio/gpio6/value exit 0

保存后赋予可执行权限:

sudo chmod +x /usr/local/bin/boot-init.sh

3.2 创建 systemd service 文件

接下来告诉 systemd:“这个脚本需要在系统准备好后自动运行”。

创建服务单元文件:

sudo nano /etc/systemd/system/boot-init.service

填入以下内容:

[Unit] Description=Custom Boot Initialization Script After=multi-user.target [Service] Type=oneshot ExecStart=/usr/local/bin/boot-init.sh RemainAfterExit=yes [Install] WantedBy=multi-user.target

各字段解释如下:

  • Description: 服务描述,方便识别
  • After=multi-user.target: 表示等到多用户环境就绪后再运行(即网络、文件系统等基本准备完成)
  • Type=oneshot: 表示这是一个一次性执行的任务,不需要长期运行
  • RemainAfterExit=yes: 告诉 systemd,即使脚本执行完了,也认为服务处于“激活”状态
  • WantedBy=multi-user.target: 开机时自动启用该服务

3.3 启用并测试服务

刷新 systemd 配置,使其读取新服务:

sudo systemctl daemon-reexec

启用服务(开机自启):

sudo systemctl enable boot-init.service

立即手动运行一次看看效果:

sudo systemctl start boot-init.service

查看执行状态和日志:

sudo systemctl status boot-init.service

如果有错误,可以用 journalctl 查看详细输出:

journalctl -u boot-init.service --since "5 minutes ago"

一切正常的话,重启系统试试:

sudo reboot

重启后再次检查服务状态,确认它已成功运行。


4. 查看当前所有开机启动项

了解系统里有哪些程序会在开机时自动运行,有助于排查问题或优化性能。

4.1 查看所有启用的 systemd 服务

systemctl list-unit-files --type=service --state=enabled

这条命令会列出所有标记为“开机启动”的服务,例如:

ssh.service enabled cron.service enabled docker.service enabled boot-init.service enabled

4.2 查看 init.d 脚本注册情况(如有)

如果你曾经使用过update-rc.d添加脚本,可以通过以下命令查看:

ls /etc/rc*.d/

输出可能类似:

/etc/rc0.d/K01gpio-init.sh /etc/rc2.d/S01gpio-init.sh /etc/rc6.d/K01gpio-init.sh

其中Sxx表示启动(Start),Kxx表示关闭(Kill),数字代表顺序。

4.3 查看完整的启动依赖树

想知道系统启动时到底加载了哪些组件?可以查看 multi-user.target 的依赖链:

systemctl list-dependencies multi-user.target

这会展示出整个启动过程中涉及的所有服务和目标。


5. 实用技巧与常见问题解决

5.1 脚本执行失败怎么办?

最常见的原因是执行时机太早。比如你的脚本依赖网络,但 systemd 在网络还没准备好时就执行了。

解决方案:明确指定依赖。

修改[Unit]段落:

[Unit] Description=Boot Init Script After=network.target multi-user.target Requires=network.target

这样就能确保在网络可用之后再运行脚本。

5.2 如何让脚本后台持续运行?

如果你的脚本需要长期驻留(比如监听某个事件),不要用Type=oneshot,而是改为:

[Service] Type=simple ExecStart=/path/to/your/script.sh Restart=always RestartSec=5
  • Restart=always:崩溃后自动重启
  • RestartSec=5:等待5秒后再重启

5.3 删除不再需要的启动服务

当你想移除某个开机任务时,记得做三件事:

# 1. 停止正在运行的服务 sudo systemctl stop boot-init.service # 2. 禁用开机自启 sudo systemctl disable boot-init.service # 3. 删除 service 文件 sudo rm /etc/systemd/system/boot-init.service # 4. 重新加载配置 sudo systemctl daemon-reload

6. 总结

通过本文,你应该已经掌握了如何在现代Linux系统中高效地配置开机启动脚本。我们回顾一下核心要点:

  • systemd 是现代Linux的标准启动管理器,功能强大且稳定。
  • 尽量避免使用老旧的 init.d 脚本,优先采用.service单元文件方式。
  • 编写启动脚本时,注意执行路径、权限、依赖顺序等问题。
  • 利用systemctljournalctl工具可以轻松管理和调试服务。
  • 正确设置After=Requires=能有效避免因资源未就绪导致的失败。

现在你可以把那些反复敲的命令统统封装成一个启动服务,从此再也不用手动执行了。无论是初始化硬件、启动应用还是自动化运维,这套方法都能帮你省下大量时间和精力。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询