当前位置: 首页 > news >正文

告别每次手动执行!让脚本随系统自动启动

告别每次手动执行!让脚本随系统自动启动

你是否也经历过这样的场景:每天开机后第一件事就是打开终端,cd到项目目录,输入./start.sh,再等几秒看日志滚动?重复操作不仅耗时,还容易遗漏——尤其当你需要在无人值守的服务器、边缘设备或开发板上长期运行某个服务时,手动启动根本不可靠。

其实,Linux系统早已为我们准备好了成熟的自动化方案。本文不讲抽象概念,不堆砌术语,只聚焦一件事:如何让一个普通Shell脚本,在系统启动完成后自动、稳定、可靠地跑起来。我们用最常见、最稳妥的方式,带你从零完成配置,全程可复制、可验证、无坑可踩。

无论你是刚接触Linux的新手,还是需要快速部署测试环境的开发者,只要你会写基础Shell命令,就能跟着本文一步到位。不需要理解systemd的完整架构,也不用研究init进程的演进历史——我们要的,是今天下午就能用上的解决方案。


1. 先写一个真正能干活的脚本

很多教程一上来就教改配置文件,结果脚本本身就有问题:权限不对、路径错误、缺少退出码……最后排查半天才发现是脚本没跑通。所以第一步,我们先确保脚本本身是“健康”的。

1.1 创建脚本文件

推荐将脚本放在一个固定、易管理的位置,比如/opt/scripts/(系统级脚本常用路径)或~/bin/(用户级)。这里以/opt/scripts/为例:

sudo mkdir -p /opt/scripts sudo nano /opt/scripts/auto_run_test.sh

注意:不要用~或相对路径(如./script.sh)在系统级启动中,因为启动时当前工作目录不确定,~可能无法展开。

在编辑器中输入以下内容(请逐字复制,注意符号全为英文):

#!/bin/bash # 记录启动时间,用于验证是否真正在开机时执行 echo "[$(date '+%Y-%m-%d %H:%M:%S')] System startup triggered" > /tmp/startup_log.txt # 进入你的实际工作目录(示例路径,请按需修改) cd /home/user/mywbc_v5_usb/build || { echo "Failed to enter build directory" >> /tmp/startup_log.txt exit 1 } # 执行你的核心程序(此处为 ./sim/sim,保持原样) if ./sim/sim; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] Simulation completed successfully" >> /tmp/startup_log.txt else echo "[$(date '+%Y-%m-%d %H:%M:%S')] Simulation failed with exit code $?" >> /tmp/startup_log.txt fi

这段脚本做了三件关键事:

  • 用绝对路径记录日志到/tmp/startup_log.txt/tmp在所有Linux发行版中都存在且可写)
  • 使用cd ... || { ... }结构确保目录切换失败时有明确反馈并退出
  • 检查./sim/sim的执行结果,成功或失败都记入日志,便于后续排查

1.2 设置执行权限

脚本不是文本文件,它必须被系统识别为“可执行程序”。这一步不能跳过:

sudo chmod +x /opt/scripts/auto_run_test.sh

+x777更安全、更精准——它只赋予执行权限,不开放读写权限给所有人。777是典型的安全隐患,在生产环境中应严格避免。

验证是否生效:

/opt/scripts/auto_run_test.sh cat /tmp/startup_log.txt

如果看到带时间戳的日志输出,说明脚本本身完全正常。


2. 选择最适合的启动机制:rc.local 还是 systemd?

Ubuntu 16.04 及更早版本默认使用rc.local;而 Ubuntu 18.04 及以后版本(包括主流的 20.04、22.04、24.04)已全面转向systemd。盲目套用旧教程,很可能在新系统上“配置写了,但脚本根本不执行”。

我们不假设你的系统版本,而是提供双路径方案:先检测,再选择,一次搞定。

2.1 快速判断你的系统是否支持 rc.local

运行以下命令:

ls /etc/rc.local
  • 如果返回/etc/rc.local,说明系统保留了该机制(常见于 Ubuntu 16.04、18.04 初期);
  • 如果提示No such file or directory,说明系统已移除rc.local(Ubuntu 20.04+ 默认行为)。

注意:即使文件存在,也可能被 systemd 禁用。我们后面会统一验证。

2.2 方案一:启用并配置 rc.local(适用于保留该机制的系统)

如果上一步确认/etc/rc.local存在,继续执行:

# 确保文件可写 sudo chmod 644 /etc/rc.local # 编辑文件 sudo nano /etc/rc.local

将你的脚本调用行添加到exit 0之前(注意:必须在exit 0之前,否则不会执行):

#!/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 just change the execution # bits. # # By default this script does nothing. # >>> 添加以下两行 <<< cd /opt/scripts ./auto_run_test.sh exit 0

保存退出后,必须启用 rc-local 服务(Ubuntu 18.04+ 即使有文件也默认禁用):

sudo systemctl enable rc-local sudo systemctl start rc-local

检查状态:

sudo systemctl status rc-local

若显示active (exited),说明已成功启用。

2.3 方案二:使用 systemd 服务(推荐,适用于所有现代 Ubuntu)

这是目前最标准、最可靠、最易维护的方式。我们创建一个专属的服务单元文件:

sudo nano /etc/systemd/system/auto-run-test.service

填入以下内容(请逐字复制,注意缩进和空格):

[Unit] Description=Auto-run test script at boot After=multi-user.target Wants=multi-user.target [Service] Type=oneshot ExecStart=/opt/scripts/auto_run_test.sh RemainAfterExit=yes User=user WorkingDirectory=/opt/scripts [Install] WantedBy=multi-user.target

参数说明:

  • Type=oneshot:表示脚本执行完即退出,适合一次性任务;
  • RemainAfterExit=yes:让服务状态保持“active”,便于用systemctl status查看结果;
  • User=user务必替换成你实际的用户名(如ubuntudev),不能写root(除非脚本必须 root 权限);
  • WorkingDirectory:显式指定工作目录,避免因路径问题导致脚本失败。

保存后,启用并启动服务:

sudo systemctl daemon-reload sudo systemctl enable auto-run-test.service sudo systemctl start auto-run-test.service

验证是否生效:

sudo systemctl status auto-run-test.service

正常应显示active (exited),且日志中能看到你脚本的输出。


3. 验证与排错:别让“以为成功”耽误你时间

配置完成不等于万事大吉。真正的验证,必须在重启后进行。但在此之前,我们可以做几项快速检查,大幅降低失败概率。

3.1 三步自查清单(重启前必做)

检查项命令预期结果不通过怎么办
脚本是否可执行ls -l /opt/scripts/auto_run_test.sh显示-rwxr-xr-x或类似含x的权限sudo chmod +x /opt/scripts/auto_run_test.sh
脚本能否手动运行/opt/scripts/auto_run_test.sh && cat /tmp/startup_log.txt日志中有时间戳和成功信息检查脚本内路径、权限、依赖是否缺失
服务/脚本是否启用sudo systemctl is-enabled auto-run-test.service(systemd)
sudo systemctl is-enabled rc-local(rc.local)
返回enabledsudo systemctl enable xxx

3.2 重启后如何确认真的成功?

重启后,第一时间执行:

# 查看日志(最直接证据) cat /tmp/startup_log.txt # 查看服务状态(systemd 方案) sudo systemctl status auto-run-test.service # 查看 rc.local 执行痕迹(rc.local 方案) sudo journalctl -u rc-local --no-pager -n 20

如果日志里有你脚本输出的时间戳,且服务状态为active,恭喜,你已经成功了。

3.3 常见失败原因与修复建议

  • 问题:日志为空,服务显示failed
    → 检查/opt/scripts/auto_run_test.sh中的cd目录是否存在?./sim/sim文件是否有执行权限?用ls -l /home/user/mywbc_v5_usb/build/确认。

  • 问题:服务状态为inactive,但手动start可以
    → 很可能是User=设置错误。systemd服务默认以 root 运行,但你的程序可能依赖用户环境变量(如$HOME$DISPLAY)。此时应改为User=user并确保该用户已登录过图形界面,或改用Type=simple+LoginSession=true(进阶需求,本文不展开)。

  • 问题:rc.local 配置后无反应
    → Ubuntu 20.04+ 默认禁用。务必执行sudo systemctl enable rc-local,并确认/etc/rc.local文件开头有#!/bin/sh -e,结尾有exit 0


4. 进阶建议:让自动启动更健壮、更可控

生产环境或长期运行场景下,仅“能启动”还不够。以下是几个提升稳定性的实用技巧,无需复杂配置,一行命令即可生效。

4.1 加入延迟启动,避开资源竞争

某些脚本依赖网络、USB设备或GPU驱动,而这些组件在系统启动早期可能尚未就绪。简单加个等待即可:

# 在 auto_run_test.sh 开头加入(等待10秒) sleep 10

或者更智能地等待特定条件(例如等待 USB 设备出现):

# 等待 /dev/ttyUSB0 出现,最多等 60 秒 for i in $(seq 1 60); do if [ -c "/dev/ttyUSB0" ]; then break fi sleep 1 done

4.2 重定向所有输出到独立日志,避免干扰

echo和程序输出统一归档,方便追踪:

# 替换脚本中的 echo 行为,全部导向一个日志 exec >> /var/log/auto-run-test.log 2>&1 echo "[$(date)] Script started"

记得提前创建日志目录并赋权:

sudo mkdir -p /var/log/auto-run-test sudo chown user:user /var/log/auto-run-test.log

4.3 设置失败自动重试(仅 systemd)

auto-run-test.service[Service]段落中添加:

Restart=on-failure RestartSec=10 StartLimitIntervalSec=600 StartLimitBurst=3

含义:当脚本退出码非0时,等待10秒后重试;10分钟内最多重试3次。这对网络依赖型脚本非常有用。


5. 总结:你已经掌握了一项关键运维能力

回顾一下,我们完成了什么:

  • 写出一个结构清晰、自带日志、可独立验证的启动脚本;
  • 根据系统版本,选择了rc.localsystemd两种主流方案,并完成配置;
  • 掌握了重启前的三步自查法,大幅降低配置失败率;
  • 学会了查看日志、分析状态、定位常见问题的实操方法;
  • 获取了延迟启动、日志分离、失败重试等进阶技巧,让自动化真正可靠。

这不是一个“照着做就能用”的模板,而是一套可迁移的方法论。下次你需要让 Python 服务、Node.js 应用、或者 Docker 容器开机自启,思路完全一致:写好执行单元 → 选对启动机制 → 验证日志输出 → 持续优化健壮性

自动化真正的价值,不在于省下那几十秒点击,而在于把确定性交给机器,把创造力留给自己。


获取更多AI镜像

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

http://www.jsqmd.com/news/315714/

相关文章:

  • GLM-4-9B-Chat-1M GPU算力优化:vLLM中--gpu-memory-utilization调参指南
  • SGLang三级缓存架构解析:L1/L2/L3协同工作机制
  • Local AI MusicGen实战落地:数字艺术策展中AI生成沉浸式声景方案
  • SiameseUIE部署教程:解决‘目录不存在’问题的标准路径切换流程
  • 亲测Qwen2.5-7B LoRA微调,十分钟快速出效果真实体验
  • 如何构建轻量级UDS诊断协议驱动模块:新手教程
  • 基于UDS 28服务的CAN通信管理操作指南
  • 无需配置!一键启动Qwen2.5-7B LoRA微调环境(附实操)
  • 2026年评价高的精脱硫催化剂好评厂家曝光
  • WeKnora效果实测:在低至6GB显存GPU(RTX 3080)稳定运行Ollama-Qwen2.5
  • Allegro导出Gerber文件命名规范最佳实践
  • 让Python脚本随系统启动,测试镜像轻松实现
  • 为什么推荐用英文问?VibeThinker-1.5B-WEBUI语言差异实测
  • Local AI MusicGenGPU利用率:资源受限设备的部署策略
  • ms-swift强化学习初体验:GRPO算法快速上手
  • 使用QListView实现可编辑列表的手把手教程
  • 用GLM-4.6V-Flash-WEB实现电商图自动合规检测
  • Qwen-Image-2512-ComfyUI操作详解:内置工作流怎么用
  • Qwen-Image-2512-ComfyUI实测总结:最小改动原则很靠谱
  • 2026双金属耐磨弯头厂家合集:耐磨陶瓷弯头厂家+碳化硅耐磨弯头厂家一站式盘点
  • 2026双金属耐磨管道厂家指南:稀土合金耐磨管厂家收录
  • 2026年新疆成人学历咨询服务机构综合评估与精选推荐
  • 从部署到应用:Qwen3Guard-Gen-WEB完整实践路径
  • mPLUG-VQA部署排错手册:从CUDA版本冲突到PIL格式转换全解析
  • 为什么推荐用HeyGem?这3个优势太打动我
  • 一文搞懂ms-swift:大模型训练全流程可视化操作
  • AI净界使用指南:RMBG-1.4图像分割模型一文详解
  • 通义千问2.5-7B企业知识库搭建:RAG集成详细步骤
  • Z-Image-Turbo能力测评:提示词控制与风格还原度测试
  • CogVideoX-2b生成效果实测:中英文提示词对比与优化建议