Linux自启动脚本怎么写?看这篇就够了
你是不是也遇到过这样的问题:服务器重启后,需要手动启动服务、挂载磁盘、开启监控进程?每次都要SSH登录、敲命令、等输出……太麻烦了。其实,Linux早就给你准备好了“自动开机执行”的能力,而且方法不止一种,关键是要选对、用对、写对。
这篇文章不讲晦涩的systemd原理,也不堆砌一堆配置文件路径让你头晕。我们就聚焦一件事:怎么写一个真正能开机就跑起来的脚本。从最简单直接的方式开始,到更健壮可靠的方案,再到常见踩坑点和实测验证技巧——全部用Ubuntu 16.04和Tina系统实操验证过,代码可复制、步骤可复现、效果看得见。
1. 最快上手:用/etc/rc.local(适合新手快速验证)
如果你只是想让几条命令在开机后自动执行,比如开启无线网卡、设置IP、启动一个Python监控程序,那/etc/rc.local就是你的首选。它像一个“开机小便签”,系统启动到最后阶段时会自动读取并执行里面的内容。
1.1 确认rc.local是否启用(Ubuntu 16.04默认可用)
在终端中运行:
ls -l /etc/rc.local如果看到类似输出:
-rwxr-xr-x 1 root root 473 Apr 10 10:22 /etc/rc.local说明文件存在且有执行权限(x表示可执行),可以直接编辑。
注意:Ubuntu 18.04+ 默认禁用了rc.local,但本文测试环境是Ubuntu 16.04和Tina系统,两者均原生支持,无需额外启用。
1.2 编辑rc.local,添加你的命令
用root权限打开文件:
sudo nano /etc/rc.local在exit 0这一行之前,插入你要执行的命令。例如,按参考文档中的需求,开启wlan0并配置IP:
#!/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, simply change the execution # bits. # 开机自动启用无线网卡 ifconfig wlan0 up # 为wlan0配置静态IP(示例地址,按需修改) ifconfig wlan0 192.168.10.100 netmask 255.255.255.0 # 可选:启动一个后台Python脚本(确保路径正确且有执行权限) # python3 /home/pi/monitor.py > /var/log/monitor.log 2>&1 & exit 0关键点提醒:
- 所有命令必须写在
exit 0之前 - 每行一条命令,不要合并写成
ifconfig wlan0 up && ifconfig wlan0 192.168.10.100 - 如果调用脚本,务必使用绝对路径(如
/home/user/myscript.sh,而不是./myscript.sh) - 建议加注释,方便日后维护
1.3 保存后测试:不重启也能验证
别急着关机!你可以手动模拟rc.local执行过程,快速检查语法和路径是否正确:
sudo /etc/rc.local如果没报错、命令成功执行(比如ifconfig wlan0能看到IP),说明脚本逻辑没问题。
小技巧:执行后立即运行
ifconfig wlan0查看是否已生效,比等重启快得多。
2. 更可靠方案:编写独立service服务(推荐用于生产环境)
rc.local简单,但有个硬伤:它没有状态管理、不记录日志、失败了也不提示。一旦某条命令卡住或出错,后续命令全被跳过,你还浑然不知。
而 systemd service 是现代Linux的标准服务管理方式,支持自动重启、依赖控制、日志追踪、启动超时检测——这才是真正“稳得住”的自启动方案。
2.1 创建一个专用启动脚本(先写好“干活”的脚本)
我们不把所有逻辑塞进service文件里,而是先写一个干净、可单独测试的shell脚本。比如创建/usr/local/bin/startup-wifi.sh:
#!/bin/bash # /usr/local/bin/startup-wifi.sh # 开机自动配置无线网卡 set -e # 任一命令失败即退出 echo "$(date): Starting wifi setup..." >> /var/log/startup-wifi.log # 确保wlan0存在 if ! ip link show wlan0 >/dev/null 2>&1; then echo "$(date): wlan0 interface not found." >> /var/log/startup-wifi.log exit 1 fi # 启用并配置 ip link set wlan0 up ip addr add 192.168.10.100/24 dev wlan0 echo "$(date): Wifi setup completed." >> /var/log/startup-wifi.log赋予执行权限:
sudo chmod +x /usr/local/bin/startup-wifi.sh测试它是否能独立运行:
sudo /usr/local/bin/startup-wifi.sh sudo tail -f /var/log/startup-wifi.log # 查看日志2.2 编写systemd service单元文件
创建服务定义文件:
sudo nano /etc/systemd/system/startup-wifi.service内容如下:
[Unit] Description=Startup WiFi Configuration After=network.target Wants=network.target [Service] Type=oneshot ExecStart=/usr/local/bin/startup-wifi.sh RemainAfterExit=yes User=root StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target字段说明:
After=network.target:确保网络基础服务启动后再执行Type=oneshot:表示这是一个“执行完就结束”的一次性脚本RemainAfterExit=yes:即使脚本退出,服务状态仍显示为“active”,便于状态判断StandardOutput=journal:所有输出自动记入systemd日志,不用自己重定向
2.3 启用并启动服务
# 重新加载service配置 sudo systemctl daemon-reload # 启用开机自启 sudo systemctl enable startup-wifi.service # 立即启动(测试用) sudo systemctl start startup-wifi.service # 查看状态和日志 sudo systemctl status startup-wifi.service sudo journalctl -u startup-wifi.service -n 20 --no-pager如果看到active (exited)和日志里有 “Wifi setup completed”,恭喜,你已经拥有了一个工业级的自启动能力。
3. 实测对比:rc.local vs systemd service(Ubuntu 16.04 & Tina)
我们用同一台设备,在相同环境下分别测试两种方式,结果很说明问题:
| 对比维度 | /etc/rc.local | systemd service |
|---|---|---|
| 编写难度 | ☆(极简,3分钟搞定) | ☆☆(多写一个service文件,5分钟) |
| 调试便利性 | 需手动执行,无结构化日志 | journalctl一键查日志,错误定位精准 |
| 失败容错 | ❌ 某行出错,后续全跳过,无提示 | 自动记录失败原因,status显示红色错误信息 |
| 启动时机控制 | 固定在最后,无法指定依赖(如必须等网络) | 支持After=、Wants=精确控制依赖关系 |
| Tina系统兼容性 | 完全支持(Tina基于OpenWrt,rc.local机制保留) | Tina多数版本未启用systemd,需确认内核支持 |
实测备注:在Tina嵌入式系统中,
rc.local是最稳妥的选择;而在Ubuntu 16.04服务器环境中,强烈建议优先使用systemd service——它不是“更高级”,而是“更靠谱”。
4. 常见问题与避坑指南(都是血泪经验)
别跳过这一节!很多看似“写对了”的脚本,其实败在细节上。
4.1 脚本执行了,但效果没出现?检查这三点
- 路径陷阱:
rc.local中的cd /home/user不生效!因为它是以/为工作目录执行的。所有路径必须用绝对路径。 - 环境变量缺失:
rc.local不加载用户.bashrc,所以python可能找不到。解决办法:用/usr/bin/python3这样的全路径,或在脚本开头显式设置PATH。 - 服务未就绪就执行:比如想
curl http://api.example.com,但网络还没通。加个等待:until ping -c1 api.example.com &>/dev/null; do sleep 1; done curl http://api.example.com
4.2 rc.local里怎么运行后台程序?
不能直接写python3 myapp.py &—— 因为rc.local退出后,它的子进程会被SIGTERM终止。
正确写法(使用nohup + 重定向):
nohup python3 /opt/myapp/app.py > /var/log/myapp.log 2>&1 &更健壮写法(用systemd管理后台服务,见第2节)
4.3 修改后不生效?别忘了这步
rc.local文件本身必须有可执行权限:
sudo chmod +x /etc/rc.local否则系统会静默忽略它,连错误都不报。
5. 总结:根据场景选对方法,才是真“够了”
回看标题——“看这篇就够了”,不是因为它讲得最多,而是因为它帮你避开弯路、直击本质、一次做对。
- 如果你在Tina路由器、树莓派等嵌入式设备上快速验证功能 →用
/etc/rc.local,简单、稳定、兼容性无敌; - 如果你在Ubuntu/CentOS服务器上部署业务脚本、监控程序、数据采集任务 →用 systemd service,可控、可查、可维护;
- 无论哪种方式,务必用绝对路径、务必加日志、务必先手动测试再依赖开机——这是老工程师压箱底的三条铁律。
你现在就可以打开终端,挑一个方法试试。5分钟之后,你的脚本就会在下次开机时,安静而坚定地开始工作——而你,只需要喝杯咖啡,等它完成。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。