systemd 是唯一稳定可控的日志和依赖管理方案,/etc/rc.local 默认不执行是设计使然;应使用最小化 .service 文件配置,确保 PATH、网络就绪及绝对路径调用。

systemd 是当前唯一能稳定、可控、可查的日志和依赖管理方案,其他方法要么默认禁用(如 rc.local),要么根本不是开机机制(如 /etc/profile.d/)。
为什么直接往 /etc/rc.local 里写命令经常失败
不是你脚本写错了,是 systemd 默认根本不执行它。即使文件存在、有 #!/bin/bash、也加了 chmod +x,rc-local.service 仍处于 inactive (dead) 状态——这是设计使然,不是 bug。
-
/etc/rc.local在 systemd 系统中只是一个“兼容层”,必须显式启用对应 service 才会触发 - 它的执行环境极简:
PATH只含/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin,没加载用户 profile,也没 network-online 保证 - 脚本里用了
sudo、systemctl、su - user -c这类交互命令,会卡住或静默失败 - 如果脚本依赖 DNS 或远程服务,
After=network.target不够,得上network-online.target
用 systemd 创建 .service 文件的最小可行配置
不要照抄模板,只保留真正需要的字段。一个能立刻生效的最简版如下:
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
[Unit] Description=My Startup Script After=network.target <p>[Service] Type=oneshot ExecStart=/opt/myscript.sh RemainAfterExit=yes</p><p>[Install] WantedBy=multi-user.target
-
Type=oneshot适合一次性脚本;若要长期运行进程(如 Python Web 服务),改用Type=simple,并确保进程不 daemonize -
ExecStart=必须写绝对路径,不能用~或$HOME -
RemainAfterExit=yes让 service 状态保持 active,方便后续用systemctl is-active判断是否已执行 - 想以非 root 用户运行?加一行
User=deploy,别在脚本里用su
启用后怎么确认真的跑起来了
别等重启,立刻验证:
- 重载配置:
systemctl daemon-reload - 启用开机自启:
systemctl enable myscript.service - 立即启动并观察输出:
systemctl start myscript.service && journalctl -u myscript.service -n 20 -f - 检查是否注册成功:
systemctl is-enabled myscript.service应返回enabled - 查看实际启动时机:
systemctl list-dependencies --after myscript.service,确认它确实在 network 后执行
@reboot crontab 和 ln -s /etc/init.d 的适用边界
它们不是“替代方案”,而是有明确限制的备选:
-
@reboot由 cron 触发,只对指定用户生效(sudo crontab -e是 root,crontab -e是当前用户),且不保证网络就绪——适合纯本地、无依赖的轻量任务 -
ln -s /etc/init.d/myscript /etc/rc.d/rc3.d/S99myscript仅在 SysVinit 系统(CentOS 6、Ubuntu 14.04)有效;在 systemd 下,这个链接会被忽略,除非你额外启用systemd-sysv-generator兼容层 -
/etc/profile.d/下的脚本只在用户登录 shell 时 source,系统启动时完全不执行——这是常见误解源头
真正容易被忽略的是:所有方式都要求脚本本身可执行(chmod +x),且内部调用的命令必须用绝对路径。哪怕 date 在 shell 里能直接敲,在开机环境中也可能因 PATH 缺失而报 command not found。

















