news 2026/4/16 14:30:58

再也不用手动跑脚本,这个设置太实用了

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
再也不用手动跑脚本,这个设置太实用了

再也不用手动跑脚本,这个设置太实用了

你是不是也经历过这样的场景:写好了一个数据采集脚本、一个日志清理工具,或者一个定时监控程序,每次重启服务器后都得手动登录、cd到目录、再敲一遍python monitor.py?重复操作不仅费时,还容易遗漏——尤其在多台设备上部署时,光是检查是否启动就让人头疼。

其实,Linux系统早就有成熟的机制来解决这个问题。只是很多人卡在“不知道从哪下手”或者“试了几次没成功就放弃了”。今天这篇内容,不讲抽象原理,不堆参数配置,就用最直白的方式,带你把“开机自动运行脚本”这件事真正落地。整个过程只需要6步,每一步都有明确指令、常见坑点提醒和验证方法,哪怕你刚接触Linux命令行,也能照着做完、立刻见效。

我们用的是Ubuntu 18.04及后续版本(如20.04、22.04)通用的systemd方案,它比老版本的rc.local更稳定、更可控,也更容易排查问题。重点来了:这不是教你怎么“凑合用”,而是帮你搭一条真正可靠、可维护、能长期运行的自动化通道。


1. 为什么老办法不管用了?

在Ubuntu 14.04时代,大家习惯直接编辑/etc/rc.local文件,在里面加一行python /path/to/script.py,保存后重启就能生效。但到了Ubuntu 18.04,这个文件默认不再被系统读取——不是删了,而是“被禁用了”。

原因很简单:Ubuntu切换到了systemd作为初始化系统,而rc.local只是一个兼容性遗留接口,需要显式启用才能工作。很多教程只说“改一下rc.local就行”,却没告诉你:光改文件内容没用,必须先让系统认识它、信任它、愿意执行它。

这就像给快递员留了一张纸条说“请把包裹放门口”,但如果没告诉他你是谁、门锁密码是多少、甚至没给他开门的权限,那张纸条就只是废纸。

所以,我们的第一步,不是写脚本,而是给系统发一张“通行证”


2. 创建systemd服务单元:让rc.local重新被识别

systemd通过“服务单元文件”来管理各类启动任务。我们要做的,就是为rc.local创建一个专属的服务定义,告诉systemd:“这个文件是可信的,允许它在多用户模式下运行。”

2.1 新建rc-local.service文件

打开终端,执行以下命令:

sudo vim /etc/systemd/system/rc-local.service

小提示:如果你不熟悉vim,可以用sudo nano /etc/systemd/system/rc-local.service替代,nano更直观,按Ctrl+O保存,Ctrl+X退出。

2.2 粘贴服务配置内容

把下面这段内容完整复制进去(注意:不要漏掉空行和缩进):

[Unit] Description=/etc/rc.local Compatibility ConditionPathExists=/etc/rc.local [Service] Type=forking ExecStart=/etc/rc.local start TimeoutSec=0 StandardOutput=tty RemainAfterExit=yes SysVStartPriority=99 [Install] WantedBy=multi-user.target

这段配置的意思是:

  • 这个服务叫rc-local,作用是兼容旧版rc.local;
  • 只有当/etc/rc.local这个文件真实存在时,才尝试启动;
  • 启动方式是“forking”(后台进程模式),适合shell脚本;
  • 不设超时限制(TimeoutSec=0),避免脚本稍慢就被系统杀掉;
  • RemainAfterExit=yes表示:即使脚本执行完了,也认为服务仍在运行——这对rc.local这种“一次性执行”的场景很关键;
  • 最后一句说明:它应该在系统进入标准多用户状态(即我们日常使用的图形或命令行环境)时被拉起。

2.3 验证文件是否创建成功

执行以下命令查看文件是否存在且内容正确:

ls -l /etc/systemd/system/rc-local.service

你应该看到类似输出:

-rw-r--r-- 1 root root 327 Jun 15 10:20 /etc/systemd/system/rc-local.service

如果文件大小接近320字节,说明内容基本完整。下一步,我们来准备那个核心载体——rc.local本身。


3. 编写并配置rc.local:你的启动总控台

rc.local在这里不直接写业务逻辑,而是作为一个“启动索引”——就像电脑桌面的快捷方式,它不干活,但它知道该让谁干活、怎么干。

3.1 创建rc.local文件

sudo vim /etc/rc.local

3.2 填入标准模板(含关键细节)

粘贴以下内容(特别注意第一行#!/bin/sh -e和最后一行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. echo "看到这行字,说明rc.local已成功加载。" > /usr/local/test.log exit 0

关键细节说明:

  • #!/bin/sh -e:指定解释器为sh,并开启“出错即停”模式(-e)。这意味着只要某一行命令失败(返回非0值),整个脚本就会立即终止,避免错误被掩盖;
  • exit 0:必须有!这是告诉systemd“我执行成功了”。没有它,systemd会认为脚本异常退出,后续步骤可能不触发;
  • echo ... > /usr/local/test.log:这是我们的“心跳检测”。只要这个文件被成功写入,就证明整个链路通了。

3.3 赋予执行权限

sudo chmod +x /etc/rc.local

这一步极其重要。Linux不会执行一个没有“可执行位”的文件,哪怕它语法完全正确。你可以用ls -l /etc/rc.local确认输出中包含x(如-rwxr-xr-x)。


4. 启用并启动服务:让设置真正生效

现在,systemd已经知道rc-local.service的存在,也知道/etc/rc.local是它的执行入口。接下来,我们要正式“激活”它。

4.1 启用服务(开机自启)

sudo systemctl enable rc-local

这条命令的作用是:在系统启动流程中,为rc-local.service创建一个软链接,确保它被纳入启动序列。执行后你会看到类似提示:

Created symlink /etc/systemd/system/multi-user.target.wants/rc-local.service → /etc/systemd/system/rc-local.service.

4.2 立即启动服务(无需重启)

sudo systemctl start rc-local.service

4.3 检查服务状态(必做!)

sudo systemctl status rc-local.service

正常情况下,你应该看到:

● rc-local.service - /etc/rc.local Compatibility Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; vendor preset: enabled) Active: active (exited) since Sat 2024-06-15 10:25:33 CST; 1min 2s ago Docs: man:systemd.special(7) Process: 1234 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)

重点关注三处:

  • enabled:说明已设为开机启动;
  • active (exited):说明服务已成功运行完毕;
  • status=0/SUCCESS:说明脚本执行无报错。

如果看到failedinactive,别急着重来,先看下一条。

4.4 查看日志定位问题(排错利器)

如果状态异常,用这条命令看详细报错:

sudo journalctl -u rc-local.service -n 20 --no-pager

它会显示最近20行该服务的日志。常见错误包括:

  • /etc/rc.local没有执行权限(Permission denied);
  • 脚本里调用了不存在的命令(比如写了python3但系统只有python);
  • 路径写错(比如/home/user/script.py实际是/home/ubuntu/script.py);
  • Python脚本里有中文字符但没声明编码(Python 2尤其敏感)。

5. 把你的脚本真正挂上去:从测试到生产

现在,rc.local已经能稳定运行了。下一步,就是让它去调用你自己的业务脚本。

5.1 创建你的业务脚本(以Python为例)

假设你想开机自动运行一个叫data_collector.py的程序,放在/opt/myapp/目录下。

先创建脚本文件:

sudo mkdir -p /opt/myapp sudo vim /opt/myapp/data_collector.py

写一个极简测试版:

# /opt/myapp/data_collector.py with open("/tmp/collector_ran.txt", "w") as f: f.write("采集器已在开机时自动运行!")

5.2 创建一个包装shell脚本(推荐做法)

不建议直接在rc.local里写python /opt/myapp/data_collector.py,因为环境变量、工作目录、Python路径都可能和你手动执行时不一致。更稳妥的方式是写一个中间shell脚本:

sudo vim /opt/myapp/start_collector.sh

内容如下:

#!/bin/bash # 切换到脚本所在目录,避免相对路径出错 cd /opt/myapp # 显式指定python解释器(避免系统默认python版本不符) /usr/bin/python3 /opt/myapp/data_collector.py # 记录执行时间,便于后续排查 echo "$(date): collector started" >> /var/log/collector.log

赋予执行权限:

sudo chmod +x /opt/myapp/start_collector.sh

5.3 修改rc.local,调用你的启动脚本

再次编辑/etc/rc.local

sudo vim /etc/rc.local

exit 0之前,添加这一行:

/opt/myapp/start_collector.sh

完整片段应类似:

#!/bin/sh -e ... echo "看到这行字,说明rc.local已成功加载。" > /usr/local/test.log /opt/myapp/start_collector.sh exit 0

保存退出。现在,每次开机,系统都会自动执行start_collector.sh,进而运行你的Python程序。

5.4 验证效果

重启系统:

sudo reboot

等机器起来后,检查两个关键文件:

# 看rc.local是否执行成功 cat /usr/local/test.log # 看你的业务脚本是否真的运行了 cat /tmp/collector_ran.txt # 看日志是否记录 tail -n 5 /var/log/collector.log

如果三个文件都存在且内容符合预期,恭喜你,自动化通道已经打通。


6. 实用技巧与避坑指南

这套方案看似简单,但在真实环境中,有几个高频问题值得提前了解,帮你省下几小时调试时间。

6.1 环境变量问题:为什么脚本里找不到命令?

你在终端能运行pip list,但rc.local里执行就报command not found?这是因为systemd服务默认不加载用户的shell配置(如.bashrc),PATH路径非常精简。

解决方案:在shell脚本开头显式设置PATH,例如:

#!/bin/bash export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin" cd /opt/myapp python3 data_collector.py

6.2 权限问题:为什么写不了文件?

rc.local是以root身份运行的,但你的脚本可能想往普通用户目录(如/home/ubuntu/logs/)写日志,而root默认没有该用户的写权限。

解决方案:用sudo -u username切换用户执行,例如:

sudo -u ubuntu /opt/myapp/start_collector.sh

6.3 启动时机问题:我的服务依赖网络,但脚本运行时网络还没就绪

rc.local默认在multi-user.target阶段运行,此时网络可能尚未完全配置好(尤其是DHCP获取IP需要时间)。

解决方案:在rc-local.service[Unit]部分增加依赖声明:

[Unit] Description=/etc/rc.local Compatibility ConditionPathExists=/etc/rc.local After=network-online.target Wants=network-online.target

然后重新加载配置:

sudo systemctl daemon-reload sudo systemctl restart rc-local.service

6.4 调试技巧:如何快速验证修改是否生效?

不用每次重启。你可以这样模拟一次完整启动流程:

# 重新加载所有unit文件 sudo systemctl daemon-reload # 重启rc-local服务(相当于重走一遍开机流程) sudo systemctl restart rc-local.service # 立即查看结果 sudo systemctl status rc-local.service

7. 总结:你真正掌握的不只是一个技巧

到这里,你已经完成了一次完整的Linux开机自启实践。回顾一下,你实际构建的是一个可扩展、可维护、可诊断的自动化基础框架

  • 你学会了systemd服务单元的基本写法,以后可以为任何程序(Node.js、Java、Go)创建专属启动服务;
  • 你理解了rc.local的现代定位——它不是过时的古董,而是灵活的启动调度中心;
  • 你掌握了环境隔离、权限控制、依赖管理这些工程化必备意识;
  • 你拥有了快速验证和精准排错的能力,而不是靠“重启试试看”。

更重要的是,这件事的复利价值极高:一旦配置好,它就默默为你工作数月甚至数年,每天节省的几分钟,累积起来就是几天的开发时间。

下次当你又写好一个新脚本,只需三步:放进固定目录、写个启动包装、加一行调用——再也不用手动跑了。


获取更多AI镜像

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 10:58:18

51单片机流水灯代码Keil烧录前的准备事项说明

以下是对您提供的博文内容进行 深度润色与工程化重构后的技术文章 。全文已彻底去除AI生成痕迹,采用资深嵌入式工程师第一人称视角写作,语言自然、逻辑严密、节奏紧凑,兼具教学性与实战指导价值。结构上打破传统“引言-正文-总结”模板&…

作者头像 李华
网站建设 2026/4/15 21:42:36

Live Avatar部署提速:降低sample_steps效果实测

Live Avatar部署提速:降低sample_steps效果实测 1. Live Avatar模型简介 Live Avatar是由阿里联合高校开源的数字人生成模型,专注于高质量、低延迟的实时数字人视频生成。它基于Wan2.2-S2V-14B大模型架构,融合了DiT(Diffusion T…

作者头像 李华
网站建设 2026/4/16 12:23:53

Qwen-Image-Edit-2511效果展示:六组高质量海报案例分享

Qwen-Image-Edit-2511效果展示:六组高质量海报案例分享 Qwen-Image-Edit-2511不是一款“能修图”的模型,而是一款真正懂设计意图、守得住角色特征、画得出工业精度的AI图像编辑引擎。作为Qwen-Image-Edit-2509的增强版本,它在六个关键维度上…

作者头像 李华
网站建设 2026/4/15 16:32:35

语音识别前必做步骤:FSMN-VAD精准切分实战指南

语音识别前必做步骤:FSMN-VAD精准切分实战指南 1. 为什么语音识别前必须做端点检测? 你有没有遇到过这样的情况:把一段30分钟的会议录音直接喂给语音识别模型,结果识别结果里塞满了“呃”、“啊”、“这个那个”、长时间停顿&am…

作者头像 李华
网站建设 2026/4/16 12:41:27

YOLOv9训练总失败?低成本GPU优化部署案例完美解决

YOLOv9训练总失败?低成本GPU优化部署案例完美解决 你是不是也遇到过这样的情况:刚下载YOLOv9代码,满怀期待地准备训练自己的数据集,结果还没跑完第一个epoch就报错——CUDA out of memory、NaN loss、梯度爆炸、dataloader卡死……

作者头像 李华
网站建设 2026/4/16 12:42:32

Qwen3-Embedding-0.6B部署步骤详解:SGlang服务配置全流程

Qwen3-Embedding-0.6B部署步骤详解:SGlang服务配置全流程 你是否正在为本地快速搭建一个轻量、高效又开箱即用的文本嵌入服务而发愁?Qwen3-Embedding-0.6B 就是那个“小而强”的答案——它不占显存、启动快、支持多语言,还能直接对接 OpenAI…

作者头像 李华