艾格吃饱了 2025-12-03 10:25 采纳率: 99%
浏览 3
已采纳

Ubuntu 20.04 开机自启动脚本不执行?

在Ubuntu 20.04中,用户常遇到自定义脚本无法开机自动执行的问题。尽管已将脚本添加至`/etc/rc.local`或通过systemd创建了服务单元,但脚本仍可能未运行。常见原因包括:`rc-local.service`未启用、脚本权限不足(缺少可执行权限)、脚本路径错误、未以root权限运行,或systemd服务文件中未正确设置`Type=forking`或缺失`RemainAfterExit=yes`。此外,Ubuntu 20.04默认未安装`rc-local.service`,需手动启用。排查时应检查`journalctl -u rc-local`或对应service日志,确认执行失败的具体原因。
  • 写回答

1条回答 默认 最新

  • 璐寶 2025-12-03 10:38
    关注

    1. 问题背景与常见现象

    在 Ubuntu 20.04 系统中,许多系统管理员和运维工程师希望在系统启动时自动执行自定义脚本,例如初始化网络配置、挂载特定文件系统或启动私有服务。常见的实现方式包括使用传统的 /etc/rc.local 脚本机制,或通过 systemd 创建服务单元(service unit)。然而,即便按照传统方法配置,仍常出现脚本未被执行的情况。

    典型表现包括:

    • 系统重启后,预期的脚本行为未发生(如日志未生成、服务未启动)
    • rc-local.service 显示为 inactive (dead)
    • 手动执行脚本正常,但开机无法触发
    • systemd 服务状态显示 failedexited

    2. 根本原因分析

    Ubuntu 20.04 基于 systemd 架构,已逐步弃用 SysVinit 风格的启动流程。因此,/etc/rc.local 并非默认启用。以下是导致自定义脚本无法执行的主要原因:

    原因类别具体说明
    rc-local.service 未启用Ubuntu 20.04 默认不安装或启用该服务,需手动创建并启用
    脚本权限不足/etc/rc.local 或自定义脚本缺少可执行权限(chmod +x)
    路径错误或解释器缺失脚本首行未指定正确的解释器(如 #!/bin/bash),或命令路径未全路径化
    未以 root 权限运行某些操作(如绑定端口、挂载设备)需要 root 权限,而服务未正确配置用户
    systemd Type 配置错误对于后台运行脚本,未设置 Type=forking 导致 systemd 误判进程结束
    缺少 RemainAfterExit=yes对于一次性执行脚本,未设置此参数会导致 systemd 认为服务未运行
    依赖项未满足脚本依赖网络、文件系统等资源,但服务启动过早
    日志未检查未通过 journalctl 查看服务日志,难以定位失败原因

    3. 解决方案:启用 rc.local 支持

    由于 Ubuntu 20.04 默认未启用 rc-local.service,需手动配置:

    1. 创建 /etc/rc.local 文件:
    #!/bin/bash
    echo "[INFO] Running rc.local at $(date)" >> /var/log/rc-local.log
    # 自定义命令放在此处
    exit 0
    
    1. 添加可执行权限:
    sudo chmod +x /etc/rc.local
    
    1. 创建 systemd 服务单元:
    sudo tee /etc/systemd/system/rc-local.service <<EOF
    [Unit]
    Description=/etc/rc.local Compatibility
    ConditionPathExists=/etc/rc.local
    
    [Service]
    Type=forking
    ExecStart=/etc/rc.local start
    TimeoutSec=0
    StandardOutput=tty
    RemainAfterExit=yes
    SysRq=immediate
    Capabilities=CAP_ALL
    CapabilityBoundingSet=CAP_ALL
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    1. 启用并启动服务:
    sudo systemctl enable rc-local
    sudo systemctl start rc-local
    

    4. 使用 systemd 自定义服务的最佳实践

    推荐优先使用 systemd 服务而非 rc.local,因其更灵活且符合现代 Linux 启动标准。以下是一个通用模板:

    [Unit]
    Description=Custom Startup Script
    After=network.target syslog.target
    
    [Service]
    Type=oneshot
    ExecStart=/opt/scripts/mystartup.sh
    RemainAfterExit=yes
    User=root
    StandardOutput=journal
    StandardError=journal
    
    [Install]
    WantedBy=multi-user.target
    

    关键配置说明:

    • Type=oneshot:适用于执行后退出的脚本
    • RemainAfterExit=yes:确保服务状态保持 active
    • After=network.target:确保网络就绪后再执行
    • User=root:明确指定运行用户

    5. 排查流程图(Mermaid)

    
    graph TD
        A[系统启动后脚本未执行] --> B{是否使用 rc.local?}
        B -- 是 --> C[检查 rc-local.service 是否启用]
        C --> D[systemctl is-active rc-local]
        D -- inactive --> E[启用服务并检查日志]
        D -- active --> F[查看 journalctl -u rc-local]
        B -- 否 --> G[检查自定义 service 文件]
        G --> H[验证 Type 和 RemainAfterExit]
        H --> I[检查 ExecStart 路径是否正确]
        I --> J[运行 systemctl status myscript]
        J --> K[查看 journalctl -u myscript]
        K --> L[修复权限、路径或依赖问题]
    

    6. 日志排查与调试技巧

    当脚本未执行时,必须依赖日志进行诊断。常用命令如下:

    # 查看 rc-local 服务状态与日志
    systemctl status rc-local
    journalctl -u rc-local --since today
    
    # 查看自定义服务日志
    journalctl -u mystartup.service -f
    
    # 检查 systemd 总体启动流程
    systemd-analyze critical-chain
    

    建议在脚本中主动写入日志,便于追踪执行流程:

    #!/bin/bash
    exec > >(tee /var/log/mystartup.log)
    echo "[START] Custom script running at $(date)"
    # your commands here
    echo "[END] Script finished"
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 12月4日
  • 创建了问题 12月3日