一看就会的开机自启教程,测试脚本轻松落地
你是不是也遇到过这样的情况:写好了一个监控脚本、一个数据采集程序,或者一个简单的环境检测工具,每次重启系统后都要手动点开终端、cd到目录、再敲一遍bash test.sh?重复操作不仅费时,还容易遗漏——尤其在无人值守的边缘设备或远程服务器上,一次忘记启动,可能就错过一整天的关键数据。
别担心,这其实是个非常基础但又特别实用的 Linux 系统能力:让脚本随系统一起醒来。它不依赖桌面环境,不挑发行版,不用改 crontab,也不需要复杂的 Docker 容器编排。只要你会写几行 bash,就能搞定。
本文就是为你准备的“零门槛实操指南”。我们不讲 systemd 的源码原理,不堆参数说明,不列十种方法让你纠结选哪个。只聚焦一件事:用一个可复制、可验证、可立即生效的最小闭环,把你的 test.sh 变成开机自动运行的服务。全程在 Ubuntu 环境下演示(其他主流发行版如 Debian、CentOS Stream 8+ 同样适用),所有命令都经过实测,贴上去就能跑。
1. 为什么这个方法最稳?一句话说清底层逻辑
Linux 系统启动时,会按顺序加载一系列预定义的服务单元(unit)。我们不是去“黑”系统,而是照着它的规矩,提交一个标准格式的服务描述文件(.service),告诉它:“请在我需要的时候,自动执行我指定的脚本。”
这就像给快递公司填一张标准运单——地址、收件人、物品名称都写清楚,剩下的派送、签收、状态更新,全由系统自动完成。不需要你守在门口等。
所以,核心就三步:
- 写一个符合规范的
AutoRun.service文件(相当于运单) - 把它放进系统认得的地方(
/etc/systemd/system/,相当于快递分拣中心) - 告诉系统“这张单子要长期有效”(
systemctl enable)
没有魔法,只有约定。
2. 手把手:从零创建 AutoRun.service 服务文件
这个文件是整个流程的“心脏”,但它其实非常简单。我们逐段解释每一行的作用,并标出你必须修改的地方(也就是适配你自己的环境)。
2.1 文件内容详解(带注释版)
[Unit] Description=AutoRun-Service After=network.target [Service] Type=simple User=root WorkingDirectory=/home/Ubuntu/Desktop ExecStart=/home/Ubuntu/Desktop/test.sh start [Install] WantedBy=multi-user.target现在,我们一行一行拆开看:
Description=AutoRun-Service
这是服务的“名字标签”,纯属给人看的,方便你以后用systemctl status AutoRun.service查状态时一眼认出。你可以改成Description=我的数据采集服务,完全没问题。After=network.target
表示“等网络准备好之后再启动我”。如果你的脚本不依赖网络(比如只是读取本地传感器),这一行可以保留,也可以删掉;如果它必须联网才能工作(比如要 curl 一个 API),那就必须留着。Type=simple
最常用类型,表示服务启动后,主进程就一直运行着。适合大多数 shell 脚本场景。不用改。User=root
关键配置项!指定以哪个用户身份运行脚本。如果你的test.sh需要访问硬件设备(如串口/dev/ttyUSB0)、写入系统日志、或操作 root 权限目录,请务必设为root。如果你只是普通用户操作自己家目录下的文件,也可以改成User=your_username(把your_username换成你实际的用户名)。WorkingDirectory=/home/Ubuntu/Desktop
关键路径项!这是脚本运行时的“当前工作目录”。很多脚本里写的相对路径(比如./config.json或../logs/)都依赖这个目录。请务必将/home/Ubuntu/Desktop替换成你存放test.sh的绝对路径。例如,如果你把脚本放在/opt/myproject/下,这里就写/opt/myproject/。ExecStart=/home/Ubuntu/Desktop/test.sh start
最关键的一行!这是真正要执行的命令。注意两点:
① 路径必须是绝对路径(不能写./test.sh或~/test.sh);
② 后面的start是传给脚本的参数。我们的test.sh示例里会用$1接收它,你可以根据需要改成run、init或者直接去掉(如果脚本不需要参数)。WantedBy=multi-user.target
表示“当系统进入多用户模式(即正常命令行登录状态)时,就自动启用我”。这是绝大多数服务器和桌面系统的默认目标,无需修改。
2.2 创建文件的实操步骤
打开终端,执行以下命令(假设你已将test.sh放在桌面):
# 进入桌面目录(请替换成你的真实路径) cd /home/Ubuntu/Desktop # 使用 nano 编辑器创建服务文件(你也可以用 vim 或 gedit) sudo nano AutoRun.service把上面带注释的完整内容粘贴进去,重点检查并修改WorkingDirectory和ExecStart中的路径。保存退出(nano 中按Ctrl+O回车保存,Ctrl+X退出)。
3. 部署服务:四条命令,全部生效
文件写好了,接下来就是把它“注册”进系统。只需四条命令,每一条都有明确目的,不会出错:
# 1. 复制服务文件到系统服务目录(必须用 sudo) sudo cp AutoRun.service /etc/systemd/system/ # 2. 设置文件权限(确保系统能安全读取) sudo chmod 644 /etc/systemd/system/AutoRun.service # 3. 通知 systemd:有新服务来了,重新扫描一遍 sudo systemctl daemon-reload # 4. 设为开机自启(这才是最关键的一步) sudo systemctl enable AutoRun.service执行完第四条后,终端会输出类似这样的提示:
Created symlink /etc/systemd/system/multi-user.target.wants/AutoRun.service → /etc/systemd/system/AutoRun.service.这意味着:成功了。下次开机,系统就会自动加载并运行你的脚本。
小贴士:如果你只是想立刻测试一下服务是否能跑通(不用等重启),可以加一条命令:
sudo systemctl start AutoRun.service然后用
sudo systemctl status AutoRun.service查看运行状态和最近日志。如果看到active (running),并且没有红色报错,就说明一切正常。
4. 测试脚本 test.sh:一个真实可用的范例
光有服务没用,脚本本身得靠谱。下面是一个经过实测、功能清晰、结构干净的test.sh示例。它做了三件事:记录启动时间、写入日志、并提供简单的状态反馈。
4.1 脚本内容(请复制保存为 test.sh)
#!/bin/bash # 脚本名称:test.sh # 功能:开机自启测试脚本,记录启动时间并写入日志 # 用法:bash test.sh start (服务中调用的就是这一行) LOG_FILE="/home/Ubuntu/Desktop/test.log" TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') case "$1" in start) echo "[$TIMESTAMP] 服务已启动 —— 开机自启测试成功!" >> "$LOG_FILE" echo "[$TIMESTAMP] 当前用户:$(whoami)" >> "$LOG_FILE" echo "[$TIMESTAMP] 工作目录:$(pwd)" >> "$LOG_FILE" echo "----------------------------------------" >> "$LOG_FILE" ;; *) echo "用法: $0 {start}" exit 1 ;; esac4.2 关键细节说明
#!/bin/bash是必须的“魔数行”,告诉系统用 bash 解释器来运行它。LOG_FILE变量定义了日志路径,请务必把/home/Ubuntu/Desktop/test.log替换成你希望保存日志的绝对路径。case "$1" in ...是标准的 bash 参数判断结构。服务里ExecStart=... test.sh start传入的start,就由这里接收并执行对应分支。>> "$LOG_FILE"是追加写入,避免每次启动都覆盖旧日志。echo "----------------------------------------"是分隔线,让日志更易读。
4.3 赋予执行权限(重要!)
脚本创建好后,必须让它“可执行”,否则 systemd 会报错:
chmod +x /home/Ubuntu/Desktop/test.sh这条命令只需执行一次。之后无论重启多少次,权限都会保留。
5. 验证与排错:三步确认是否真的成功
部署完别急着关机,先做三件事,快速验证效果:
5.1 第一步:检查服务状态
sudo systemctl status AutoRun.service理想输出应包含:
Loaded: loaded (/etc/systemd/system/AutoRun.service; enabled; vendor preset: enabled)→ 表示已启用(enabled)Active: active (running)或Active: inactive (dead)(刚部署完可能是 dead,但enabled是关键)- 最后几行是最近的日志,能看到你脚本写入的内容。
5.2 第二步:查看日志文件
直接打开你设定的test.log:
cat /home/Ubuntu/Desktop/test.log如果看到类似这样的内容,说明脚本已被成功调用:
[2024-06-15 09:22:10] 服务已启动 —— 开机自启测试成功! [2024-06-15 09:22:10] 当前用户:root [2024-06-15 09:22:10] 工作目录:/home/Ubuntu/Desktop ----------------------------------------5.3 第三步:模拟重启(可选,但最可靠)
如果你不想真重启机器,可以用 systemd 的“软重启”方式触发服务重载:
# 先停止服务 sudo systemctl stop AutoRun.service # 再启动一次(模拟开机过程) sudo systemctl start AutoRun.service # 再次检查日志 tail -n 5 /home/Ubuntu/Desktop/test.log如果日志里新增了一条记录,恭喜你,整套流程已经 100% 跑通。
6. 常见问题与一句话解决方案
实际操作中,新手最容易卡在这几个地方。我们把它们列出来,并给出最直接的解决命令:
问题1:
Failed to enable unit: Unit file AutoRun.service does not exist.
→ 你漏掉了cp命令,或者路径写错了。重新执行:sudo cp /home/Ubuntu/Desktop/AutoRun.service /etc/systemd/system/问题2:
Job for AutoRun.service failed because the control process exited with error code.
→ 脚本路径错误,或test.sh没有执行权限。检查:ls -l /home/Ubuntu/Desktop/test.sh(看是否有x权限)sudo chmod +x /home/Ubuntu/Desktop/test.sh问题3:日志文件没生成,或内容为空。
→WorkingDirectory和ExecStart中的路径不一致,导致脚本在错误目录下运行。用sudo systemctl status AutoRun.service查看报错详情,重点找No such file or directory。问题4:想取消开机自启,怎么恢复?
→ 两条命令搞定:sudo systemctl disable AutoRun.servicesudo rm /etc/systemd/system/AutoRun.service
(再加一条sudo systemctl daemon-reload更稳妥)
7. 进阶小技巧:让脚本更健壮、更实用
当你熟悉了基础流程,可以轻松加入这些小改进,让自动化更省心:
添加失败重试:在
[Service]段落里加上:Restart=on-failure RestartSec=10表示脚本意外退出后,10 秒后自动重试。对网络不稳定或初始化较慢的程序很友好。
限制资源占用:防止脚本失控吃光内存:
MemoryLimit=100M CPUQuota=50%支持多种启动模式:修改
test.sh,让它能响应start、stop、status:case "$1" in start) ... ;; stop) echo "[$(date)] 服务已停止" >> "$LOG_FILE" ;; status) echo "Running OK";; esac这样你就可以用
sudo systemctl stop AutoRun.service手动控制了。日志自动轮转:避免
test.log越积越大,加一行定时任务:# 每月1号清空日志(加到 crontab) 0 0 1 * * /bin/truncate -s 0 /home/Ubuntu/Desktop/test.log
8. 总结:你已经掌握了一个可复用的工程化习惯
回看整个过程,你其实只做了四件事:
- 写了一个结构清晰的
.service描述文件; - 把它放到系统认可的位置;
- 用标准命令注册并启用;
- 配合一个带参数判断的 shell 脚本,完成具体任务。
这看似是“开机自启”,本质上是你第一次亲手把一个零散的脚本,封装成了一个受系统管理、可监控、可启停、可复用的标准服务单元。这种思维方式,正是运维自动化和嵌入式开发中最基础、也最值钱的能力。
下次当你拿到一个新的 Python 监控程序、一个 Node.js 数据接口、甚至一个编译好的 C++ 工具,你都可以用完全相同的套路,把它变成开机就位的“数字员工”。
现在,关掉这篇教程,打开你的终端,把test.sh和AutoRun.service创建起来。五分钟后,你就能看到第一行日志写入test.log——那不是代码在运行,而是你亲手点亮的、属于自己的自动化之光。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。