如何让脚本随Armbian开机运行?这篇教程太实用了
1. 为什么你的脚本没在开机时执行?
你写好了点灯脚本,测试时一切正常,但重启后LED却纹丝不动——这不是硬件问题,也不是脚本写错了,而是启动机制没配对。Armbian不是普通Linux发行版,它用的是现代systemd体系,但很多人还在用老方法(比如直接改rc.local)碰运气。结果就是:脚本被系统“看见”了,却没被“正确调度”。
更关键的是,Armbian的启动流程里藏着一个常见误区:很多人以为/etc/rc.local是万能入口,其实从Debian 10+和Ubuntu 20.04起,rc.local默认已被systemd禁用,即使文件存在,也不会自动执行。这不是bug,是设计使然。
所以,真正的问题从来不是“怎么写脚本”,而是“怎么让系统在正确的时间、以正确的权限、在正确的依赖条件下运行它”。
我们不讲抽象原理,直接上手——用两种经过实测的方法,让你的脚本稳稳跑在Armbian开机第一秒。
2. 推荐方案:用systemd service(更可靠、更可控)
这是Armbian官方推荐的方式,也是当前最主流、最健壮的方案。它不像init.d那样靠文件名排序猜顺序,而是用明确的依赖声明告诉系统:“这个脚本必须等网络就绪后再运行”或“必须在GPIO子系统加载完成后启动”。
2.1 创建服务定义文件
打开终端,新建一个service文件:
sudo nano /etc/systemd/system/test-startup.service粘贴以下内容(注意:已按Armbian实际环境优化):
[Unit] Description=Test startup script for Armbian After=multi-user.target Wants=multi-user.target [Service] Type=oneshot ExecStart=/usr/local/bin/test-startup.sh RemainAfterExit=yes User=root WorkingDirectory=/usr/local/bin StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target关键参数说明(用人话):
After=multi-user.target:确保系统基础服务(网络、文件系统、GPIO驱动)都准备好了再执行Type=oneshot:表示这是一个“执行一次就结束”的脚本,不是常驻进程RemainAfterExit=yes:脚本执行完后,systemd仍认为服务处于“激活”状态,方便后续状态查询User=root:强制以root权限运行(GPIO操作必须root)StandardOutput=journal:所有打印输出都会被journalctl捕获,方便排查问题
2.2 编写你的实际脚本
创建可执行脚本文件:
sudo nano /usr/local/bin/test-startup.sh写入你的业务逻辑(例如点亮LED):
#!/bin/bash # 等待GPIO子系统稳定(Armbian启动时可能有短暂延迟) sleep 2 # 导出并配置GPIO引脚(以Armbian常用引脚为例) if [ ! -d "/sys/class/gpio/gpio6" ]; then echo 6 > /sys/class/gpio/export sleep 0.1 fi echo "out" > /sys/class/gpio/gpio6/direction echo 1 > /sys/class/gpio/gpio6/value # 可选:记录日志到系统日志 logger "test-startup.sh executed: GPIO6 set to HIGH"重要操作:赋予执行权限
sudo chmod +x /usr/local/bin/test-startup.sh2.3 启用并验证服务
启用服务(让系统记住开机要运行它):
sudo systemctl daemon-reload sudo systemctl enable test-startup.service立即测试是否能正常运行(不重启):
sudo systemctl start test-startup.service检查执行结果和日志:
sudo systemctl status test-startup.service sudo journalctl -u test-startup.service -n 20 --no-pager如果看到active (exited)和你脚本里的logger日志,说明一切就绪。
3. 兼容方案:用init.d(适合快速验证或遗留脚本)
如果你已有现成的init.d脚本,或者只是想快速验证逻辑,Armbian依然支持它——但必须按规范注册,不能只放文件就完事。
3.1 编写标准init.d脚本
创建脚本文件:
sudo nano /etc/init.d/test-startup内容如下(注意文件名无.sh后缀,这是SysV规范):
#!/bin/bash ### BEGIN INIT INFO # Provides: test-startup # Required-Start: $local_fs $network $syslog # Required-Stop: $local_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Run test startup script # Description: Enable service provided by test-startup ### END INIT INFO case "$1" in start) echo "Starting test startup script..." /usr/local/bin/test-startup.sh ;; stop) echo "Stopping test startup script..." # 这里可添加清理逻辑,如关闭LED echo 0 > /sys/class/gpio/gpio6/value 2>/dev/null ;; restart|force-reload) $0 stop $0 start ;; *) echo "Usage: $0 {start|stop|restart|force-reload}" >&2 exit 3 ;; esac exit 0说明:
### BEGIN INIT INFO段是关键,它告诉update-rc.d该在哪个运行级别启动、依赖哪些基础服务Required-Start: $local_fs $network $syslog确保文件系统、网络、日志系统就绪后再运行Default-Start: 2 3 4 5对应多用户模式(Armbian默认运行级别)
3.2 注册并启用
赋予执行权限:
sudo chmod +x /etc/init.d/test-startup注册为开机启动项:
sudo update-rc.d test-startup defaults你会看到类似输出:
update-rc.d: using dependency based boot sequencing验证是否注册成功:
ls /etc/rc*.d/ | grep test-startup应看到类似S01test-startup的链接文件。
手动启动测试:
sudo /etc/init.d/test-startup start4. 常见失败原因与解决方案
别急着重装系统,90%的“开机不执行”问题都出在这几个地方:
4.1 脚本路径或权限错误
错误做法:脚本放在/home/pi/下,或没加+x权限
正确做法:脚本统一放/usr/local/bin/,且sudo chmod +x
为什么是
/usr/local/bin?因为它是系统级可执行目录,不受用户家目录权限限制,且在PATH中,systemd和init.d都能无歧义调用。
4.2 GPIO设备未就绪(最隐蔽的坑)
Armbian启动时,内核加载GPIO驱动有微小延迟。如果你的脚本一上来就写/sys/class/gpio/gpio6/value,很可能因设备节点还没生成而失败。
解决方案:在脚本开头加等待逻辑
# 等待GPIO节点出现,最多等5秒 for i in $(seq 1 5); do if [ -d "/sys/class/gpio/gpio6" ]; then break fi sleep 1 done或者更稳妥地用wait-for-sysfs(Armbian自带):
# 在service文件的[Service]段添加 ExecStartPre=/bin/sh -c 'until [ -d /sys/class/gpio/gpio6 ]; do sleep 0.5; done'4.3 rc.local被禁用(别再踩这个坑)
如果你习惯用/etc/rc.local,请先确认它是否生效:
sudo systemctl status rc-local如果显示inactive (dead),说明被禁用了。启用它需两步:
sudo systemctl unmask rc-local sudo systemctl enable rc-local但 强烈不建议依赖rc.local——它没有依赖管理,无法保证执行时机,且在Armbian新版本中可能被彻底移除。
5. 调试技巧:三步定位问题根源
当脚本没按预期运行时,别盲目重启。按顺序执行这三步:
5.1 查看服务是否启用
# 检查是否已启用(开机自启) systemctl is-enabled test-startup.service # 检查当前状态(是否运行过) systemctl is-active test-startup.service5.2 查看完整日志(最有效)
# 查看最近10条日志,带时间戳 sudo journalctl -u test-startup.service -n 10 -o short-precise # 实时跟踪日志(运行后立刻看输出) sudo journalctl -u test-startup.service -f日志里会清晰显示:
- 脚本是否被调用
- 执行到哪一行出错(如
Permission denied、No such file or directory) - 是否因超时被systemd终止
5.3 手动模拟启动环境
systemd运行脚本时,环境变量和工作目录与你登录终端不同。用以下命令模拟:
# 以systemd相同方式运行(root权限、无交互、标准输出到journal) sudo systemd-run --scope --unit=test-debug /usr/local/bin/test-startup.sh sudo journalctl -u test-debug -n 20这能帮你复现真实启动场景下的行为。
6. 总结:选对方法,一次搞定
| 方案 | 适用场景 | 启动可靠性 | 调试便利性 | 维护成本 |
|---|---|---|---|---|
| systemd service | 新项目、生产环境、需要精细控制 | (依赖明确、自动重试) | (journalctl一键查日志) | (配置清晰,易修改) |
| init.d | 快速验证、迁移旧脚本、临时调试 | (兼容层稳定,但无依赖保障) | (需/etc/init.d/xxx status) | (需维护INIT INFO头) |
| rc.local | 仅限极简单任务、临时测试 | (易被禁用、无保障) | (日志分散,难追踪) | (未来可能失效) |
最终建议:
- 新写脚本,一律用systemd service,按本文第2节操作;
- 已有init.d脚本,可先用第3节快速验证,再逐步迁移到systemd;
- 彻底放弃
rc.local作为主力方案,它已是技术债。
现在,重启你的Armbian设备,观察LED是否准时亮起——那束光,就是你亲手点亮的系统确定性。
--- > **获取更多AI镜像** > > 想探索更多AI镜像和应用场景?访问 [CSDN星图镜像广场](https://ai.csdn.net/?utm_source=mirror_blog_end),提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。