news 2026/2/11 22:28:21

效果惊艳!我的Python脚本终于能开机自启了

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
效果惊艳!我的Python脚本终于能开机自启了

效果惊艳!我的Python脚本终于能开机自启了

你有没有试过写好一个Python脚本,满怀期待地设置成开机自动运行,结果重启后发现——什么都没发生?日志里空空如也,进程列表里找不到它的影子,连个报错提示都不给?别急,这不是你的代码有问题,大概率是系统启动机制没对上。

Ubuntu 18.04及之后的版本(包括20.04、22.04、24.04)早已弃用传统rc.local的直接执行方式,转而全面拥抱systemd服务管理。很多教程还在教你怎么改/etc/rc.local,却没告诉你:光改文件不注册服务,它根本不会被加载。今天这篇,不讲虚的,就用最直白的方式,带你把一个真实的Python脚本——从写好、到部署、再到开机稳稳跑起来,全程实操,一步不跳。

我们不用复杂的服务单元模板,不碰高深的systemd依赖配置,就用最轻量、最可靠、最易排查的rc-local.service方案。它不是“兼容旧习惯”,而是官方认可的平滑过渡方式。更重要的是,它足够简单,出问题时你能一眼看懂哪一步卡住了。

下面所有操作,我都以一个真实场景为例:

  • Python脚本路径:/home/yourname/myscript.py
  • 功能:每次开机后自动创建一个带时间戳的记录文件
  • 目标:重启后,你打开终端输入ls /tmp/startup_*.log,就能看到刚生成的日志

现在,我们开始。

1. 理解核心逻辑:为什么不能直接改rc.local?

在老版本Ubuntu中,/etc/rc.local是一个被系统自动调用的shell脚本,只要加上可执行权限,里面写的命令就会在多用户模式启动末尾执行。但新版本里,这个文件默认不存在,即使你手动创建,systemd也不会主动去读它——它已经成了一个“被遗忘的角落”。

systemd要求:任何想在启动时运行的东西,都必须以“服务单元”(service unit)的形式声明,并明确告诉系统:“我该在什么时候启动、依赖什么、失败了怎么处理”。

所以,真正的关键不是“写脚本”,而是“注册服务”。rc-local.service的作用,就是为/etc/rc.local这个传统入口,重新申请一张systemd的“通行证”。

划重点rc-local.service不是替代方案,而是桥梁。它让systemd认识并信任rc.local,从而恢复你熟悉的工作流。

2. 创建rc-local.service服务单元

这一步,我们告诉systemd:“请把/etc/rc.local当作一个合法服务来管理”。

打开终端,执行:

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

小提示:这里推荐用nano而非vim,对新手更友好。如果坚持用vim,记得保存时按Esc→ 输入:wq→ 回车。

将以下内容完整复制粘贴进去:

[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

这段配置的含义,用大白话解释:

  • [Unit]部分:说明这是个兼容性服务,且只在/etc/rc.local文件真实存在时才启用;
  • [Service]部分:Type=forking表示它会派生子进程(符合传统rc.local行为);ExecStart指明启动时执行哪条命令;RemainAfterExit=yes最关键——它告诉systemd:“哪怕rc.local执行完了,你也得认为这个服务还‘活着’,别把它当一次性任务关掉”;
  • [Install]部分:WantedBy=multi-user.target意味着它属于“标准多用户启动环境”,也就是我们日常使用的图形或命令行界面启动阶段。

保存并退出(nano中按Ctrl+O回车保存,Ctrl+X退出)。

3. 编写并配置/etc/rc.local启动索引脚本

rc.local现在不再是“被系统默认执行的脚本”,而是我们自己定义的“启动总控台”。你可以把它理解成一个启动清单:所有你想开机运行的程序,都列在这里统一调度。

执行:

sudo nano /etc/rc.local

粘贴以下内容(注意:这是完整模板,包含必需的shebang和退出码):

#!/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 "System started at $(date)" >> /var/log/rc-local.log # 示例:运行你自己的Python脚本(重点!替换为你的真实路径) su -c "python3 /home/yourname/myscript.py" -s /bin/sh yourname # =============== 你的启动命令到这里结束 =============== exit 0

关键细节说明

  • #!/bin/sh -e:必须有,且必须是sh,不是bash-e参数表示遇到任何命令失败就立即退出,避免后续命令误执行;
  • su -c "..." -s /bin/sh yourname:这是最稳妥的用户切换方式。yourname要替换成你实际的用户名(比如john)。它确保脚本以你的用户身份运行,能访问你的家目录、Python环境、.bashrc里的PATH等。绝对不要用sudo python3 ...,那会以root身份运行,很可能找不到你的pip包或配置文件
  • >> /var/log/rc-local.log:把启动时间追加写入日志,方便后续验证;
  • exit 0:必须有,且必须是0(表示成功)。少了它,systemd会认为脚本执行失败,整个服务启动失败。

保存退出。

4. 赋予执行权限并启用服务

现在,rc.local是个普通文本文件,systemd不认识它。我们需要两步:

第一步:让它变成可执行的脚本

sudo chmod +x /etc/rc.local

第二步:告诉systemd:“这个服务我要用”

sudo systemctl enable rc-local.service

enable命令的作用,是创建一个软链接,把rc-local.service加入到multi-user.target.wants目录下,确保每次开机都自动加载它。

成功提示:你会看到类似Created symlink /etc/systemd/system/multi-user.target.wants/rc-local.service → /etc/systemd/system/rc-local.service.的输出。

5. 启动服务并实时验证

别急着重启!先手动启动一次,看看有没有报错:

sudo systemctl start rc-local.service

然后立刻检查状态:

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 Mon 2024-06-10 10:23:45 CST; 5s ago Docs: man:systemd-rc-local-generator(8) Process: 1234 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS) Tasks: 0 (limit: 4915) Memory: 0B CGroup: /system.slice/rc-local.service

重点关注三处:

  • Loaded: ... enabled:服务已启用;
  • Active: active (exited):服务已成功运行完毕;
  • status=0/SUCCESSrc.local内部执行成功。

如果看到failedinactive,立刻用下面命令查错:

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

它会显示最近50行该服务的日志,绝大多数问题(比如路径写错、权限不足、Python找不到模块)都能在这里一眼定位。

6. 编写你的Python脚本:一个真实可用的例子

现在,轮到你的Python脚本登场了。我们写一个简单但实用的:开机后自动在/tmp下创建一个带时间戳的log文件,证明它真的跑了。

创建文件:

nano ~/myscript.py

写入以下内容:

#!/usr/bin/env python3 import datetime import os # 获取当前时间,格式化为字符串 now = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") # 定义日志文件路径 log_path = f"/tmp/startup_{now}.log" # 写入内容:包含用户名、主机名、启动时间 with open(log_path, "w") as f: f.write(f"Python script executed at {now}\n") f.write(f"User: {os.getenv('USER')}\n") f.write(f"Hostname: {os.uname().nodename}\n") print(f"Log created: {log_path}")

保存退出。

为什么这个脚本能成功?

  • 它用了#!/usr/bin/env python3,确保调用系统默认的Python3;
  • 没有依赖外部包(如requests、pandas),避免环境问题;
  • 所有路径都是绝对路径或基于/tmp这种系统级可写目录;
  • print()语句会在systemctl status里显示,方便调试。

7. 最终验证:重启测试与日常维护

做完以上所有步骤,就可以进行终极测试了:

sudo reboot

等待系统重启完成,登录后立即执行:

ls -lt /tmp/startup_*.log

你应该能看到一个刚刚生成的、名字里带着当前时间戳的log文件。再用cat打开它:

cat /tmp/startup_*.log

内容应该类似:

Python script executed at 20240610_103522 User: yourname Hostname: myubuntu-pc

恭喜!你的Python脚本已真正实现开机自启。

日常维护小贴士

  • 修改脚本后无需重装服务:只需改~/myscript.py,下次开机自动生效;
  • 临时禁用自启sudo systemctl disable rc-local.service
  • 彻底删除sudo systemctl disable rc-local.service && sudo rm /etc/systemd/system/rc-local.service /etc/rc.local
  • 日志集中查看sudo journalctl -u rc-local.service --since "1 hour ago"查看过去一小时日志。

8. 常见问题与避坑指南

实际操作中,90%的问题都集中在几个地方。我把它们列出来,帮你省下几小时排查时间:

8.1 “脚本没运行,但systemctl status显示active”

原因rc.local里执行的命令本身失败了,但因为-e参数缺失或exit 0写在错误位置,导致rc.local整体返回了0。

解决

  • 确保/etc/rc.local第一行是#!/bin/sh -e
  • 确保exit 0是文件最后一行,且前面没有其他命令;
  • rc.local里加一句set -x(放在#!/bin/sh -e下面),它会让每条命令执行时都打印出来,便于追踪。

8.2 “报错:python3: command not found”

原因su -c切换用户后,PATH环境变量被重置,找不到python3命令。

解决

  • 不要用python3,改用绝对路径:/usr/bin/python3(先用which python3确认);
  • 或者,在su -c命令里显式指定PATH:
    su -c "PATH=/usr/local/bin:/usr/bin:/bin python3 /home/yourname/myscript.py" -s /bin/sh yourname

8.3 “Python脚本报错:No module named 'xxx'”

原因:你的脚本依赖了pip安装的包(如requests),但systemd环境下找不到这些包。

解决

  • 推荐:用虚拟环境。创建环境 → 激活 → pip install → 在rc.local里用虚拟环境的python路径执行;
  • 快速方案:用sudo pip3 install xxx全局安装(仅限简单工具包);
  • 绝对避免:在脚本里用os.system("pip install xxx"),这会导致启动变慢且不可靠。

8.4 “中文路径或文件名导致脚本崩溃”

原因rc.local默认使用POSIX locale(C locale),不支持UTF-8中文。

解决

  • 最佳实践:所有路径、文件名、字符串,一律用英文;
  • 若必须用中文:在rc.localsu -c命令前,加上LANG=en_US.UTF-8
    su -c "LANG=en_US.UTF-8 python3 /home/yourname/中文脚本.py" -s /bin/sh yourname

总结

这篇文章没有堆砌术语,没有绕弯子,就做了一件事:把一个看似玄乎的“开机自启”,拆解成你能在5分钟内跟着敲完、10分钟内看到效果的清晰步骤

我们从理解systemd的底层逻辑出发,亲手创建服务单元、编写启动索引、调试Python脚本、验证最终效果,每一步都对应一个可观察、可验证的结果。你学到的不是一个孤立的技巧,而是一套可复用的方法论:当面对任何Linux服务配置问题时,先问“它是不是一个systemd服务?”,再查“它的状态和日志是什么?”——这两步,能解决80%的疑难杂症

现在,你的Python脚本已经稳稳地站在了系统启动队列的最前端。它不再需要你手动唤醒,而是在你还没打开电脑前,就已经默默开始了工作。这种掌控感,正是自动化真正的魅力所在。


获取更多AI镜像

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

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

工业温度控制器开发中的芯片包获取指南

以下是对您提供的博文内容进行 深度润色与专业重构后的版本 。本次优化严格遵循您的全部要求: ✅ 彻底去除AI痕迹,语言自然、老练、有工程师温度; ✅ 摒弃模板化结构(如“引言/概述/总结”),以真实工程…

作者头像 李华
网站建设 2026/2/8 19:16:55

Speech Seaco Paraformer性能优化指南,提速3倍

Speech Seaco Paraformer性能优化指南,提速3倍 在实际部署Speech Seaco Paraformer ASR模型过程中,很多用户反馈:识别速度虽已达到5–6倍实时,但面对批量会议录音、长时访谈或高并发语音处理场景时,仍存在显存占用高、…

作者头像 李华
网站建设 2026/2/9 1:49:43

Qwen2.5-VL-AWQ:AI视觉全能王,长视频解析新体验

Qwen2.5-VL-AWQ:AI视觉全能王,长视频解析新体验 【免费下载链接】Qwen2.5-VL-7B-Instruct-AWQ 项目地址: https://ai.gitcode.com/hf_mirrors/Qwen/Qwen2.5-VL-7B-Instruct-AWQ 导语:阿里达摩院最新推出的Qwen2.5-VL-7B-Instruct-AWQ…

作者头像 李华
网站建设 2026/2/10 3:34:07

YOLOv9官方镜像助力中小企业快速落地AI

YOLOv9官方镜像助力中小企业快速落地AI 在食品加工厂的流水线上,摄像头每秒扫描数十个包装盒,系统需在200毫秒内识别出标签错贴、封口不严或异物混入;在电力巡检场景中,无人机拍摄的数千张杆塔照片,要求模型准确区分绝…

作者头像 李华
网站建设 2026/2/8 12:35:10

Wan2.1-FLF2V:14B模型打造720P超高清视频

Wan2.1-FLF2V:14B模型打造720P超高清视频 【免费下载链接】Wan2.1-FLF2V-14B-720P 项目地址: https://ai.gitcode.com/hf_mirrors/Wan-AI/Wan2.1-FLF2V-14B-720P 导语:Wan2.1-FLF2V-14B-720P模型正式发布,通过"首帧-末帧到视频&…

作者头像 李华
网站建设 2026/2/4 16:09:37

通义千问3-14B与Mixtral对比:Dense vs MoE架构性能评测

通义千问3-14B与Mixtral对比:Dense vs MoE架构性能评测 1. 架构分水岭:为什么Dense和MoE根本不是同一类选手? 很多人一看到“14B vs 8x7B”,下意识就比参数总量、比显存占用、比跑分高低——这就像拿一辆油电混动轿车和一台工业…

作者头像 李华