news 2026/2/6 2:49:45

Armbian系统维护小技巧:检查和管理所有开机项

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Armbian系统维护小技巧:检查和管理所有开机项

Armbian系统维护小技巧:检查和管理所有开机项

1. 理解Armbian的启动机制

1.1 为什么不能只看rc.local?

很多用户习惯性地认为/etc/rc.local就是开机启动的“总开关”,但在Armbian中,这其实是个常见误区。Armbian基于Debian/Ubuntu,从2015年起就默认采用systemd作为初始化系统,而rc.local只是systemd为了兼容旧脚本提供的一个特殊服务单元。它本身并不具备优先级控制、依赖管理或失败重试能力——这些都由systemd统一调度。

这意味着:即使你把命令写进rc.local,实际执行时机、环境变量、权限上下文都可能和预期不同。更关键的是,rc.local在systemd中默认是异步执行的,它不会等待其他服务就绪,也不会影响系统启动流程。如果你的脚本依赖网络或USB设备,很可能在它们还没准备好时就运行失败。

1.2 systemd与init.d的真实关系

Armbian的PID 1进程永远是/bin/systemd,这是内核加载后第一个用户空间进程。所有传统init.d脚本(存放在/etc/init.d/目录下)都是通过systemd的兼容层来调用的。当你运行sudo update-rc.d gpio-init.sh defaults时,systemd会自动生成一个临时unit文件,将其映射为sysv-generator的一部分。

你可以用这个命令验证:

ps -p 1 -o comm=

输出一定是systemd。再试试:

systemctl list-unit-files | grep gpio

你会发现gpio-init.sh被列为enabled状态,但它的unit类型显示为generated——这就是systemd动态生成的兼容单元。

这种设计的好处是平滑过渡,坏处是容易让人误以为init.d仍是独立体系。实际上,所有启动行为最终都受systemd控制,包括日志记录、资源限制、重启策略等。

2. 全面检查开机启动项的实用方法

2.1 查看真正启用的systemd服务

最权威的方式是直接查询systemd的unit状态数据库。以下命令能精准列出所有开机自动启动的服务:

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

--no-pager参数避免分页器干扰,适合脚本化处理。输出示例:

avahi-daemon.service enabled bluetooth.service enabled cron.service enabled gpio-init.service enabled networking.service enabled ssh.service enabled

注意:enabled表示已启用,但不等于正在运行;static表示该服务被其他服务依赖而自动激活;disabled则完全不会启动。

如果你想进一步筛选出与硬件初始化相关的服务,可以加管道过滤:

systemctl list-unit-files --type=service --state=enabled | grep -E "(gpio|hardware|init|boot)"

2.2 挖掘init.d脚本的真实状态

虽然init.d脚本被systemd接管,但它们的启用状态仍由/etc/rc*.d/目录结构决定。查看所有注册的SysV脚本:

ls -l /etc/rc*.d/S* 2>/dev/null | awk '{print $9}' | sort

这个命令会列出所有以S开头的符号链接,例如:

/etc/rc2.d/S01gpio-init.sh /etc/rc2.d/S02networking /etc/rc2.d/S03cron

其中数字代表启动顺序(01到99),字母S表示start,K表示kill(关机时执行)。但要注意:这些链接指向的原始脚本必须存在于/etc/init.d/目录下才有效。如果某个链接指向不存在的文件,systemd会在启动时静默跳过。

更可靠的方法是检查systemd对这些脚本的实际处理:

systemctl list-unit-files | grep '\.sh$' | grep enabled

这能直接看到哪些init.d脚本已被systemd识别并启用。

2.3 追踪完整的启动依赖链

单看服务列表还不够,因为某些服务可能通过依赖关系间接启动。要查看multi-user.target(标准多用户模式)下的完整启动树:

systemctl list-dependencies --all --no-pager multi-user.target | head -n 50

--all参数显示所有层级,包括隐式依赖。你会看到类似这样的结构:

● ├─basic.target ● │ ├─sockets.target ● │ │ ├─dbus.socket ● │ │ └─systemd-journald.socket ● │ └─timers.target ● └─networking.service ● └─network-pre.target ● └─gpio-init.service

这个输出清晰表明:gpio-init.servicenetwork-pre.target的依赖项,因此会在网络服务启动前执行。这种可视化依赖关系对调试启动顺序问题至关重要。

3. 管理开机项的工程化实践

3.1 禁用不需要的服务(安全第一)

Armbian默认启用一些非必要服务,如蓝牙、Avahi(零配置网络)、打印服务等。在嵌入式场景中,它们不仅浪费内存,还可能带来安全风险。禁用方法非常简单:

sudo systemctl disable bluetooth.service avahi-daemon.service cups-browsed.service

禁用后立即生效,无需重启。但要注意:禁用networking.service会导致网络不可用,禁用sshd.service会切断远程连接——这类核心服务需谨慎操作。

如果想批量禁用所有非必需服务,可以用这个安全脚本:

#!/bin/bash # 安全禁用列表(根据Armbian默认配置调整) SAFE_TO_DISABLE=( "bluetooth.service" "avahi-daemon.service" "cups-browsed.service" "cups.service" " ModemManager.service" "whoopsie.service" ) for service in "${SAFE_TO_DISABLE[@]}"; do if systemctl is-enabled "$service" >/dev/null 2>&1; then echo "Disabling $service..." sudo systemctl disable "$service" fi done

3.2 诊断启动延迟的根源

如果发现Armbian启动变慢,不要盲目优化脚本。先用systemd自带的分析工具定位瓶颈:

systemd-analyze blame --no-pager

输出按耗时从高到低排序,例如:

12.456s networking.service 8.231s gpio-init.service 3.102s ssh.service ...

这里gpio-init.service耗时8秒,明显异常。接着检查其详细日志:

systemd-analyze critical-chain gpio-init.service

输出会显示完整依赖路径及各环节耗时。如果发现某一步骤卡住,再用journalctl深入:

journalctl -u gpio-init.service -b --no-pager

-b参数只显示本次启动的日志,避免历史记录干扰。

3.3 rc.local的正确用法(当真需要时)

尽管推荐使用原生systemd服务,但某些简单场景下rc.local仍有价值。关键是让它真正可靠:

  1. 确保rc-local.service已启用:

    sudo systemctl enable rc-local.service
  2. 编辑/etc/rc.local,在exit 0前添加你的命令,并确保有明确的错误处理:

    #!/bin/sh -e # # rc.local # # 等待GPIO子系统就绪 until [ -d /sys/class/gpio ]; do sleep 0.1 done # 设置LED echo 6 > /sys/class/gpio/export 2>/dev/null || true echo out > /sys/class/gpio/gpio6/direction 2>/dev/null || true echo 1 > /sys/class/gpio/gpio6/value 2>/dev/null || true exit 0

-e参数让脚本在任何命令失败时立即退出,2>/dev/null || true忽略导出GPIO时的“已存在”错误,这是嵌入式环境常见情况。

4. 创建健壮的开机启动服务

4.1 为什么gpio-init.service比脚本更可靠?

对比两种实现方式:

  • init.d脚本:无超时控制,失败不告警,日志分散在/var/log/syslog
  • systemd服务:可设置TimeoutStartSec=30,失败自动重试,日志集中管理

创建/etc/systemd/system/gpio-init.service

[Unit] Description=GPIO Initialization Service Documentation=https://docs.armbian.com/ Wants=multi-user.target After=multi-user.target Conflicts=rc-local.service [Service] Type=oneshot ExecStart=/usr/local/bin/gpio-init.sh RemainAfterExit=yes Restart=on-failure RestartSec=10 TimeoutStartSec=30 StandardOutput=journal StandardError=journal User=root [Install] WantedBy=multi-user.target

关键配置说明:

  • Conflicts=rc-local.service防止与rc.local冲突
  • Restart=on-failure确保脚本失败时重试
  • StandardOutput=journal强制日志进入journalctl
  • User=root明确指定执行用户,避免权限问题

4.2 脚本本身的健壮性增强

/usr/local/bin/gpio-init.sh不应假设环境已就绪。改进版如下:

#!/bin/bash # GPIO初始化脚本 - 增强健壮性版本 set -e # 任何命令失败立即退出 LOGFILE="/var/log/gpio-init.log" exec >> "$LOGFILE" 2>&1 echo "[$(date)] Starting GPIO init..." # 等待sysfs就绪(最多30秒) for i in $(seq 1 30); do if [ -d "/sys/class/gpio" ]; then break fi sleep 0.5 if [ $i -eq 30 ]; then echo "ERROR: /sys/class/gpio not available after 30 seconds" exit 1 fi done # 导出并配置GPIO引脚 GPIO_PINS=(6 7 8 9 10) for pin in "${GPIO_PINS[@]}"; do # 忽略已存在的错误 echo "$pin" > /sys/class/gpio/export 2>/dev/null || true # 等待方向文件出现 for j in $(seq 1 10); do if [ -f "/sys/class/gpio/gpio${pin}/direction" ]; then break fi sleep 0.1 done echo "out" > "/sys/class/gpio/gpio${pin}/direction" 2>/dev/null || true echo "1" > "/sys/class/gpio/gpio${pin}/value" 2>/dev/null || true done echo "[$(date)] GPIO init completed successfully"

这个脚本增加了超时等待、错误重试、日志记录,完全符合生产环境要求。

5. 日常维护与故障排查

5.1 快速验证启动项状态

建立一个日常检查清单,每次系统更新后运行:

# 1. 检查是否有新服务被意外启用 systemctl list-unit-files --type=service --state=enabled | grep -v "armbian\|systemd\|dbus" # 2. 检查所有GPIO相关服务是否正常 systemctl list-units --type=service --state=failed | grep gpio # 3. 检查启动耗时是否异常 systemd-analyze time # 4. 检查最近一次启动的GPIO日志 journalctl -u gpio-init.service -n 20 --no-pager

5.2 恢复出厂启动配置

如果误操作导致系统无法启动,Armbian提供安全恢复机制。在U-Boot启动时按空格键进入菜单,选择“Recovery mode”。进入后执行:

# 重置所有systemd服务到默认状态 sudo systemctl preset-all # 禁用所有用户自定义服务 sudo systemctl list-unit-files --type=service --state=enabled | \ grep -v "systemd\|dbus\|basic\|multi-user" | \ awk '{print $1}' | xargs -r sudo systemctl disable # 重启 sudo reboot

systemctl preset-all会根据/lib/systemd/system-preset/中的规则重置服务状态,这是Armbian官方推荐的恢复方式。

5.3 监控启动项变更

长期运维中,需要知道谁修改了启动项。利用systemd的审计功能:

# 启用systemd审计(需root) sudo mkdir -p /etc/systemd/system.control echo 'ControlGroup=cpu,io,memory,pids' | sudo tee /etc/systemd/system.control/audit.conf # 创建监控脚本 /usr/local/bin/check-startup-changes.sh #!/bin/bash CURRENT_HASH=$(systemctl list-unit-files --type=service --state=enabled | md5sum | cut -d' ' -f1) PREV_HASH=$(cat /var/lib/armbian/startup-hash 2>/dev/null || echo "") if [ "$CURRENT_HASH" != "$PREV_HASH" ]; then echo "Startup services changed at $(date)" | mail -s "Armbian Startup Alert" admin@example.com systemctl list-unit-files --type=service --state=enabled > /var/lib/armbian/startup-changes-$(date +%s).log echo "$CURRENT_HASH" > /var/lib/armbian/startup-hash fi

配合cron每小时执行一次,就能及时发现非授权变更。

6. 总结:构建可维护的启动管理体系

6.1 核心原则回顾

Armbian的启动管理不是简单的“脚本堆砌”,而是一个分层可控的系统。记住三个关键点:

  • 唯一真相源systemctl list-unit-files是唯一权威的启动项清单,ls /etc/rc*.d/只是兼容层视图
  • 日志即证据:所有启动问题的第一手信息都在journalctl -b中,不要猜测,要查证
  • 渐进式增强:从rc.local起步没问题,但当需求复杂化时,必须迁移到原生systemd服务

6.2 推荐工作流

  1. 开发阶段:用rc.local快速验证逻辑
  2. 测试阶段:编写systemd service文件,用systemctl start手动测试
  3. 部署阶段systemctl enable启用,并用systemd-analyze确认性能
  4. 运维阶段:定期运行检查脚本,监控变更,保留日志快照

这套流程让启动管理从“能用”走向“可靠”,从“个人经验”升级为“团队规范”。

--- > **获取更多AI镜像** > > 想探索更多AI镜像和应用场景?访问 [CSDN星图镜像广场](https://ai.csdn.net/?utm_source=mirror_blog_end),提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/4 18:56:36

B站视频下载工具使用指南:从入门到精通

B站视频下载工具使用指南:从入门到精通 【免费下载链接】BiliDownloader BiliDownloader是一款界面精简,操作简单且高速下载的b站下载器 项目地址: https://gitcode.com/gh_mirrors/bi/BiliDownloader 你是否曾经遇到过想看的B站视频却因网络问题…

作者头像 李华
网站建设 2026/2/3 19:12:55

3步搞定!m4s-converter让B站缓存播放难题成为历史

3步搞定!m4s-converter让B站缓存播放难题成为历史 【免费下载链接】m4s-converter 将bilibili缓存的m4s转成mp4(读PC端缓存目录) 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否遇到过这样的情况:在B站缓存了系列教学视频&am…

作者头像 李华
网站建设 2026/1/30 14:20:16

智能家居设计工具完全指南:从新手到专家的三阶进化之路

智能家居设计工具完全指南:从新手到专家的三阶进化之路 【免费下载链接】HappyIslandDesigner "Happy Island Designer (Alpha)",是一个在线工具,它允许用户设计和定制自己的岛屿。这个工具是受游戏《动物森友会》(Animal Crossing…

作者头像 李华
网站建设 2026/2/5 15:52:31

B站缓存视频格式转换实用指南:从m4s到MP4的完整解决方案

B站缓存视频格式转换实用指南:从m4s到MP4的完整解决方案 【免费下载链接】m4s-converter 将bilibili缓存的m4s转成mp4(读PC端缓存目录) 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 当你在B站客户端缓存了喜爱的视频,却发现无法在…

作者头像 李华
网站建设 2026/2/5 14:27:21

CosyVoice-300M Lite为何适合云原生?弹性部署实战指南

CosyVoice-300M Lite为何适合云原生?弹性部署实战指南 1. 为什么轻量级TTS在云原生场景中不可替代? 你有没有遇到过这样的情况:想快速验证一个语音播报功能,却卡在了模型部署环节——动辄几个GB的依赖、必须配GPU的环境要求、漫…

作者头像 李华
网站建设 2026/1/29 11:36:14

3个高效步骤解决音乐歌词下载难题:音乐工具使用指南

3个高效步骤解决音乐歌词下载难题:音乐工具使用指南 【免费下载链接】163MusicLyrics Windows 云音乐歌词获取【网易云、QQ音乐】 项目地址: https://gitcode.com/GitHub_Trending/16/163MusicLyrics 音乐歌词下载是音乐爱好者管理音乐库的基础需求&#xff…

作者头像 李华