蓝易云 - 【Linux】如何在linux系统重启或启动时执行命令或脚本(也支持docker容器内部)
在 Linux 系统中,如果希望系统在启动或重启时自动执行指定命令或脚本,可以通过多种方式实现,包括系统级(systemd、rc.local)、用户级(crontab)、以及容器级(Docker ENTRYPOINT/CMD)。以下内容覆盖通用 Linux 与 Docker 内部的最佳实践方案。⚙️
🧭 一、总体思路与执行机制
系统启动过程本质上是一个由内核 → systemd → 服务启动 → 用户环境的分层启动链。
我们只要将脚本“挂”在其中任意阶段,就能实现在开机执行。
graph TD
A[开机启动] --> B[加载内核]
B --> C[启动systemd]
C --> D[执行系统服务]
D --> E[执行用户级启动任务]
E --> F[脚本或命令自动运行✅]
核心思路: 把脚本注册为“系统启动任务”或“容器启动入口点”。
🧩 二、方法一:使用 systemd 创建开机自启服务(推荐✅)
这是现代 Linux(Ubuntu、Debian、CentOS 7+)最稳健、可管理的方式。
1️⃣ 创建脚本
先编写你需要开机执行的脚本:
sudo vim /usr/local/bin/startup.sh
写入内容示例:
#!/bin/bash
echo "$(date) : System started successfully" >> /var/log/startup.log
/usr/bin/python3 /opt/app/start.py &
解释:
-
#!/bin/bash表示使用 Bash 解释器执行。 -
&表示后台执行,防止阻塞系统启动流程。 -
/var/log/startup.log用于记录执行时间和日志。
保存后赋权:
sudo chmod +x /usr/local/bin/startup.sh
2️⃣ 创建 systemd 服务文件
sudo vim /etc/systemd/system/startup.service
写入以下内容:
[Unit]
Description=Custom Startup Script
After=network.target
[Service]
ExecStart=/usr/local/bin/startup.sh
Type=simple
RemainAfterExit=true
[Install]
WantedBy=multi-user.target
解释:
-
After=network.target保证脚本在网络启动后执行。 -
RemainAfterExit=true表示即便脚本执行完也保持为“已启动”状态。 -
WantedBy=multi-user.target意味着系统进入正常运行级别时执行。
3️⃣ 启用与测试
sudo systemctl daemon-reload
sudo systemctl enable startup.service
sudo systemctl start startup.service
执行完后重启验证:
sudo reboot
优势: 可靠、可控、带日志管理;
劣势: 配置稍繁琐,但企业级推荐使用。
⚙️ 三、方法二:使用 rc.local(传统兼容方案)
适用于轻量或旧系统环境(如嵌入式、轻量容器)。
sudo vim /etc/rc.local
添加以下内容:
#!/bin/bash
/usr/local/bin/startup.sh &
exit 0
赋权:
sudo chmod +x /etc/rc.local
解释:
系统在进入多用户模式时自动执行 /etc/rc.local。
此文件兼容旧系统,执行时机较晚(网络、服务均已启动)。
注意: 某些新版本系统需手动启用 rc-local 服务:
sudo systemctl enable rc-local.service
🕒 四、方法三:使用 crontab @reboot 关键字(简洁方案)
用户级启动任务可用:
crontab -e
添加行:
@reboot /usr/local/bin/startup.sh
解释:@reboot 表示系统每次启动后执行。
适合个人脚本、小型项目,但无日志管理能力。
🐳 五、方法四:Docker 容器启动时执行脚本(容器内)
在 Docker 场景中,容器并不遵循完整的 Linux 启动流程,而是通过 ENTRYPOINT 或 CMD 执行。
方式一:在 Dockerfile 中定义启动脚本
FROM ubuntu:22.04
COPY startup.sh /usr/local/bin/startup.sh
RUN chmod +x /usr/local/bin/startup.sh
ENTRYPOINT ["/usr/local/bin/startup.sh"]
解释:
容器启动即执行 startup.sh,可在脚本末尾调用主进程,例如:
#!/bin/bash
echo "Container start at $(date)" >> /var/log/container.log
exec nginx -g "daemon off;"
exec 保证容器主进程为 nginx,不会被脚本替代。
方式二:docker-compose.yml 中挂载脚本
command: bash -c "/usr/local/bin/startup.sh && tail -f /dev/null"
🧠 六、各方式比较表
| 方式 | 场景 | 优点 | 缺点 |
|---|---|---|---|
| systemd 服务 | 企业/生产环境 | 稳定、日志可控、依赖清晰 | 配置稍复杂 |
| rc.local | 兼容性强 | 简单直接 | 可能默认禁用 |
| crontab @reboot | 用户任务 | 简洁方便 | 无日志、不可依赖网络状态 |
| Docker ENTRYPOINT | 容器场景 | 一次性执行、轻量 | 不支持 systemd 服务 |
🔧 七、执行顺序原理图
graph TD
A[系统启动] --> B[systemd初始化]
B --> C[加载网络服务]
C --> D[执行rc.local]
D --> E[执行用户crontab@reboot]
E --> F[执行Docker ENTRYPOINT]
F --> G[完成脚本任务✅]
✅ 八、总结
-
推荐标准化方式: systemd 服务。
-
轻量容器场景: 直接在 Dockerfile 中设置 ENTRYPOINT。
-
快速测试或个人任务: 使用 crontab 的
@reboot关键字。
🌟 一句话总结:
Linux 启动执行脚本的本质是“注册执行点”,选对触发层级,脚本即可稳定执行。
更多推荐



所有评论(0)