news 2026/6/26 13:17:27

绝对路径很重要!测试脚本自启必须注意这点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
绝对路径很重要!测试脚本自启必须注意这点

绝对路径很重要!测试脚本自启必须注意这点

你有没有遇到过这样的情况:写好了开机自启动服务,配置也全对,systemctl enable也执行了,可系统一重启,脚本就是不运行?日志里查不到错误,服务状态显示 active,但目标文件没生成、程序没启动、甚至echo都没写进日志——最后折腾半天,发现只是因为一行路径写成了./test.sh~/Desktop/test.sh

这不是玄学,是 Linux 系统服务机制里一个被很多人忽略却极其关键的细节:所有路径必须用绝对路径。本文不讲抽象原理,只聚焦一个真实可复现的问题场景——用systemd实现测试脚本开机自启,并手把手带你避开“相对路径陷阱”,确保每次重启都稳稳执行。


1. 为什么绝对路径不是建议,而是硬性要求?

1.1 systemd 启动时根本没有“当前目录”概念

当你在终端里敲./test.sh,Shell 会自动把当前工作目录(比如/home/Ubuntu/Desktop)拼到前面,变成/home/Ubuntu/Desktop/test.sh。但systemd不是 Shell,它启动服务时不会继承你的用户会话环境,也不会默认进入你期望的目录

它启动服务的默认工作目录是/(根目录)。这意味着:

  • 如果你在ExecStart里写./test.shsystemd会在/下找这个文件 → 找不到,报错No such file or directory
  • 如果你写~/Desktop/test.sh~systemd环境中根本不会展开 → 当作字面字符串处理 → 路径无效
  • 即使WorkingDirectory设对了,ExecStart里的路径仍需绝对路径——因为WorkingDirectory只影响进程的工作目录,不影响可执行文件本身的查找路径

核心结论ExecStartExecStopExecReload中指定的可执行文件路径,以及脚本内部调用的任何外部命令(如python3 ./main.py),只要涉及文件定位,就必须是绝对路径。这不是最佳实践,是systemd的强制规则。

1.2 一个真实失败案例还原

假设你写了这样的AutoRun.service

[Unit] Description=Test AutoRun After=network.target [Service] Type=simple User=ubuntu WorkingDirectory=/home/ubuntu/Desktop ExecStart=./test.sh start # 错误:相对路径

然后执行:

sudo cp AutoRun.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable AutoRun.service sudo reboot

重启后检查:

sudo systemctl status AutoRun.service

你会看到类似输出:

Active: failed (Result: exit-code) since ... Main PID: 1234 (code=exited, status=203/EXEC) ... Failed at step EXEC spawning ./test.sh: No such file or directory

status=203/EXEC就是systemd明确告诉你:它连可执行文件本体都找不到。


2. 正确配置:四步走,零容错

我们以一个最简但完整的测试场景为例:在桌面创建test.sh,开机后向同目录下的test.log写入一行时间戳。整个过程严格使用绝对路径,每一步都可验证。

2.1 第一步:准备测试脚本(绝对路径写死)

在你的桌面新建test.sh,内容如下(注意所有路径均为绝对路径):

#!/bin/bash # 文件保存路径:/home/your-username/Desktop/test.sh # 请将 your-username 替换为你真实的用户名,例如 ubuntu 或 ajlove # 记录日志的绝对路径 LOG_FILE="/home/your-username/Desktop/test.log" # 确保日志目录存在(虽然桌面通常存在,但严谨起见) mkdir -p "/home/your-username/Desktop" # 写入带时间戳的日志 echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开机自启动测试成功执行" >> "$LOG_FILE"

关键动作

  • nanovim编辑时,务必把your-username换成你自己的用户名(可通过whoami命令确认)
  • 保存后赋予执行权限:
    chmod +x /home/your-username/Desktop/test.sh

2.2 第二步:编写 service 文件(路径全部绝对化)

创建AutoRun.service文件(任意位置,如~/Downloads),内容如下:

[Unit] Description=AutoRun Test Service After=network.target # 可选:如果脚本依赖图形界面,加 After=graphical-session.target [Service] Type=simple User=your-username # 必须与脚本所有者一致 # WorkingDirectory 是进程的工作目录,用于脚本内相对路径操作(如 >> test.log) WorkingDirectory=/home/your-username/Desktop # ExecStart 必须是绝对路径!指向脚本本身 ExecStart=/home/your-username/Desktop/test.sh # 可选:添加 Restart 策略,让服务更健壮 Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target

关键动作

  • User=必须填写真实用户名,不能写root(除非脚本确实需要 root 权限且放在 root 目录下)
  • ExecStart=后面是脚本的完整绝对路径,不是./test.sh,也不是test.sh
  • WorkingDirectory=也必须是绝对路径,它决定了脚本里>> test.log这类相对路径写入的位置

2.3 第三步:部署 service 文件(权限与重载)

执行以下命令(注意路径和权限):

# 复制到 systemd 系统目录(需要 sudo) sudo cp ~/Downloads/AutoRun.service /etc/systemd/system/ # 设置正确权限(644 是标准 service 文件权限) sudo chmod 644 /etc/systemd/system/AutoRun.service # 重新加载 systemd 配置,让新 service 生效 sudo systemctl daemon-reload # 启用开机自启 sudo systemctl enable AutoRun.service # (可选)立即启动一次,测试是否能正常运行 sudo systemctl start AutoRun.service

2.4 第四步:验证与排错(三招定乾坤)

验证 1:检查服务状态
sudo systemctl status AutoRun.service
  • 正常应显示active (running)active (exited)
  • 如果是failed,看Main PID行和Failed at step提示,90% 是路径问题
验证 2:检查日志输出
cat /home/your-username/Desktop/test.log
  • 应能看到类似[$(date)] 开机自启动测试成功执行的记录
  • 如果没有,说明脚本根本没执行,回到status查原因
验证 3:手动模拟 systemd 环境(终极排错法)
# 切换到 systemd 默认工作目录 cd / # 以服务用户身份,用绝对路径执行脚本 sudo -u your-username /home/your-username/Desktop/test.sh # 检查日志是否生成 cat /home/your-username/Desktop/test.log
  • 如果这一步失败,说明脚本本身或路径有硬伤;如果成功,说明 service 配置没问题,问题可能出在UserWorkingDirectory设置上

3. 常见陷阱与避坑指南

3.1 “我用了 cd,为什么还是不行?”

很多新手会在脚本开头加cd /home/user/Desktop,以为这样就能解决路径问题。但这是徒劳的——systemd启动时找不到脚本本体,根本不会执行到cd这一行。路径错误发生在进程创建阶段,不是脚本运行阶段

3.2 “我的脚本里调用了 python,怎么写路径?”

如果你的test.sh里有python3 main.py,那么main.py的路径也必须是绝对路径:

# 错误 python3 main.py # 正确 python3 /home/your-username/Desktop/main.py

或者,更稳妥的方式是先cd到工作目录再执行:

cd /home/your-username/Desktop && python3 main.py

但前提是ExecStart=已经指向了正确的 shell 脚本绝对路径。

3.3 “能不能用环境变量?比如 $HOME?”

systemd默认不加载用户 shell 的环境变量(如$HOME$PATH)。你可以显式声明:

[Service] Environment="HOME=/home/your-username" Environment="PATH=/usr/local/bin:/usr/bin:/bin" ExecStart=/home/your-username/Desktop/test.sh

强烈不推荐——环境变量增加了不确定性,不如直接写死绝对路径来得清晰可靠。

3.4 “图形界面下桌面路径为什么有时不生效?”

Ubuntu 桌面版默认使用gnome-session,其桌面路径可能是/home/user/Desktop,但也可能是/home/user/桌面(中文系统)。务必用ls ~/确认真实路径名,或统一用英文路径(如改名为Desktop)避免编码问题。


4. 进阶技巧:让自启更健壮

4.1 添加启动延迟(防依赖未就绪)

如果脚本依赖网络或某个服务(如数据库),可在[Unit]中加:

After=network-online.target Wants=network-online.target

并在[Service]中加:

ExecStartPre=/bin/sleep 5 # 启动前等待5秒

4.2 日志集中管理(不用自己写 log)

systemd自带日志系统,去掉脚本里的>> test.log,直接用journalctl查看:

# 查看该服务所有日志 sudo journalctl -u AutoRun.service -n 50 --no-pager # 实时跟踪 sudo journalctl -u AutoRun.service -f

这样更规范,也避免权限问题。

4.3 测试休眠唤醒自启(延伸场景)

如参考博文提到,休眠唤醒后也可触发。只需在[Service]中加:

ExecStartPost=/bin/sh -c 'echo "[$(date)] 唤醒后执行" >> /home/your-username/Desktop/wake.log'

并确保systemd的 suspend target 已启用(通常默认开启)。


5. 总结:绝对路径是自启稳定的基石

回看整个流程,你会发现:从脚本第一行#!/bin/bash,到ExecStart的路径,再到脚本内部所有文件操作,每一个涉及“位置”的地方,都必须是明确、完整、无歧义的绝对路径。这不是繁琐,而是 Linux 服务化设计的必然要求。

记住这三条铁律:

  • ExecStart 必须绝对路径:这是systemd查找可执行文件的唯一依据;
  • WorkingDirectory 必须绝对路径:它定义了脚本内相对路径的基准点;
  • 脚本内部所有文件操作,优先用绝对路径:避免因工作目录意外变化导致失败。

当你下次再配置开机自启时,别再问“为什么不行”,先问:“我写的每一条路径,是不是都从/开始的?”


获取更多AI镜像

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

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

如何用verl提升训练速度?3个加速技巧

如何用verl提升训练速度?3个加速技巧 [【免费下载链接】verl verl: Volcano Engine Reinforcement Learning for LLMs 项目地址: https://gitcode.com/GitHub_Trending/ve/verl/?utm_sourcegitcode_aigc_v1_t0&indextop&typecard& "【免费下载链…

作者头像 李华
网站建设 2026/6/19 21:32:27

开源力量:如何用RTKLIB构建自定义GNSS数据处理流水线

开源GNSS数据处理实战:基于RTKLIB构建工业级定位流水线 在精准定位技术领域,RTKLIB作为开源工具链的标杆,正在重新定义GNSS数据处理的可能性。不同于商业黑箱软件,这套由东京海洋大学开发的工具包为开发者提供了从厘米级定位到大…

作者头像 李华
网站建设 2026/6/19 21:30:32

亲测有效!Unsloth让T4显卡也能跑大模型微调

亲测有效!Unsloth让T4显卡也能跑大模型微调 你是不是也经历过这样的困扰:想微调一个14B级别的大模型,但手头只有一张T4显卡(16GB显存),刚跑两步就报“CUDA out of memory”?下载的开源教程动辄…

作者头像 李华
网站建设 2026/6/22 11:11:58

PotPlayer AI字幕翻译插件技术解析与实战指南

PotPlayer AI字幕翻译插件技术解析与实战指南 【免费下载链接】PotPlayer_Subtitle_Translate_Baidu PotPlayer 字幕在线翻译插件 - 百度平台 项目地址: https://gitcode.com/gh_mirrors/po/PotPlayer_Subtitle_Translate_Baidu 一、技术原理与环境认知 1.1 插件工作机…

作者头像 李华
网站建设 2026/6/19 22:37:13

HY-MT1.5-1.8B API封装:构建私有翻译服务完整流程

HY-MT1.5-1.8B API封装:构建私有翻译服务完整流程 1. 为什么你需要一个自己的翻译API? 你有没有遇到过这些情况? 翻译大量内部技术文档,但商用API按字符计费,一个月账单吓一跳;处理藏语、维吾尔语等民族…

作者头像 李华
网站建设 2026/6/19 22:37:05

bge-large-zh-v1.5镜像免配置优势:内置health check + auto-restart机制

bge-large-zh-v1.5镜像免配置优势:内置health check auto-restart机制 你有没有遇到过这样的情况:部署一个embedding模型,刚跑起来没多久就挂了,日志里找不到明显错误,重启几次后又莫名崩溃?或者每次服务…

作者头像 李华