### [VPS首次开机 cloud-init 卡住怎么办?从状态、日志到网络与重试安全恢复](https://www.jiyueip.com/article/13355) **Published:** 2026-07-30T04:35:21 **Author:** 斑斓助理 **Excerpt:** VPS首次开机时cloud-init长时间运行或初始化失败,应先区分阶段、保存日志,再检查网络、DNS、用户数据、软件包和systemd依赖。本文给出安全重跑与验收顺序。 VPS首次开机后,cloud-init长时间停在running、软件包安装失败或SSH密钥没有写入,先不要连续执行`cloud-init clean`或重跑整套初始化。正确做法是先确定卡在哪个阶段,保留日志和当前配置,再按网络、元数据、用户数据和systemd依赖逐层修复。cloud-init的状态恢复,不等于把所有初始化动作再执行一遍。 ## 先判断是等待、失败还是已经完成 不同发行版和镜像的单元名称可能略有差异,先读取本机实际状态: ``` cloud-init status --long cloud-init query --all 2>/dev/null | head -c 4000 systemctl status cloud-init-local cloud-init cloud-config cloud-final --no-pager systemctl list-jobs ``` `status --long`显示的是总体状态;`cloud-init-local`、`cloud-config`和`cloud-final`分别对应不同阶段。若某个阶段仍在等待,不要只看控制台“初始化中”的字样。`list-jobs`可以提示systemd是否在等挂载、网络或其他单元。 先把现场保存下来: ``` sudo journalctl -b -u cloud-init-local -u cloud-init -u cloud-config -u cloud-final --no-pager > /root/cloud-init-journal.txt sudo cp -a /var/log/cloud-init.log /root/cloud-init.log.$(date +%s) sudo cp -a /var/log/cloud-init-output.log /root/cloud-init-output.log.$(date +%s) sudo cloud-init query userdata 2>/dev/null > /root/cloud-init-userdata.txt ``` 日志中可能包含用户名、令牌或密码片段,提交给服务商前应先脱敏。不要把完整日志直接贴到公开论坛。 ## 按四个阶段定位停点 | 阶段 | 主要任务 | 常见停点 | | --- | --- | --- | | local | 读取本地数据源、网络前的早期准备 | 磁盘、挂载或数据源探测异常 | | config | 用户、SSH、写文件和基础配置 | YAML格式、权限或模块参数错误 | | final | 安装软件包、执行脚本和启动服务 | DNS、软件源、外部下载或脚本阻塞 | | cleanup | 记录完成标记并收尾 | 前置任务未退出,服务重复触发 | `/var/log/cloud-init.log`适合看模块级调用,`cloud-init-output.log`更接近用户脚本的标准输出。找到第一条有因果意义的错误比追最后一行“failed”更重要:后者经常只是前面超时或退出码的结果。 ## 网络和DNS:能连IP不代表初始化能下载 cloud-init的final阶段经常要访问软件源、镜像仓库或元数据服务。先在不改配置的情况下验证: ``` ip addr ip route getent hosts archive.ubuntu.com 2>/dev/null resolvectl status 2>/dev/null || cat /etc/resolv.conf curl -I --connect-timeout 5 https://archive.ubuntu.com/ ``` 如果IP可达而域名解析失败,应沿解析器、`resolv.conf`、DNS服务和出站53端口排查,可参考[VPS能访问IP却解析不了域名的分层排查](https://www.jiyueip.com/article/13258)。不要为了让初始化“先跑完”而永久写死一个未经验证的DNS地址;云厂商的内网软件源和元数据地址也可能依赖特定路由。 ## 用户数据和YAML:先验证格式,再谈模块 用户数据常见问题包括缩进错误、Tab字符、未加引号的特殊值、脚本没有shebang,以及脚本返回非零退出码。可以先检查文件中是否存在明显的Tab或不可见字符,再把复杂脚本拆到独立文件测试。不要在生产实例上直接重复执行包含分区、删除或迁移动作的脚本。 ``` sudo sed -n '1,240p' /var/lib/cloud/instance/user-data.txt sudo sed -n 'l' /var/lib/cloud/instance/user-data.txt sudo cloud-init devel schema --config-file /var/lib/cloud/instance/user-data.txt ``` 部分旧版本不提供`cloud-init devel schema`,命令失败不等于配置错误,此时应以日志和发行版文档为准。脚本最好具备幂等性:重复运行不会重复创建用户、覆盖证书或追加相同的配置行。 ## 软件包安装卡住时,先查锁、代理和交互提示 如果日志停在apt、dnf或脚本下载,先确认是否有另一个包管理进程、仓库证书错误、代理环境变量或等待交互输入: ``` ps -ef | grep -E '[a]pt|[d]pkg|[d]nf|[y]um' sudo journalctl -b -u apt-daily.service -u apt-daily-upgrade.service --no-pager env | grep -iE '^(http|https|all|no)_proxy=' sudo grep -RIn 'DPkg::|Acquire::.*Proxy' /etc/apt 2>/dev/null ``` 不要直接删除包管理器锁文件,也不要用`-y`掩盖需要人工确认的变更。若初始化依赖代理,明确区分cloud-init服务环境和交互终端环境;两者不会自动共享所有变量。 ## systemd依赖未就绪:检查顺序而不是盲目重启 用户数据常会在数据库、数据盘或网络服务未就绪时启动应用。此时先检查实际单元、依赖和本次启动日志,再调整排序、拉起关系或应用重试,可结合[systemd服务依赖启动失败的三层排查](https://www.jiyueip.com/article/13352)。cloud-init负责初始化,systemd负责服务编排,不能用一个层面的重试替代另一个层面的健康检查。 ## 什么时候可以重跑,怎样避免重复破坏 1. 先做快照或至少保存配置、日志和数据目录清单。 2. 确认用户脚本中没有不可逆操作,必要时先注释外部副作用。 3. 只针对失败模块做受控验证,不要直接清空整个`/var/lib/cloud`。 4. 需要重新模拟首次启动时,再评估`cloud-init clean`的影响,并准备控制台或带外登录。 5. 重跑后记录新的实例状态和日志,确认完成标记、SSH、网络、软件包与服务都通过。 `cloud-init clean --logs --seed`会影响实例下次启动时的识别和日志,不能当作普通“刷新按钮”。不同镜像对数据源、实例ID和清理行为的支持也不同,执行前要查对应版本文档。 ## 恢复后验收清单 - `cloud-init status --long`为完成状态,且没有新的失败单元; - SSH密钥、主机名、时区、网络路由和DNS符合预期; - 软件包版本、配置文件权限和服务启停状态已记录; - 应用能完成一次无破坏性的健康检查; - 初始化日志已归档并去除敏感字段; - 将修复后的用户数据和镜像版本纳入下一次恢复演练,可参考[VPS备份恢复后的完整性验收](https://www.jiyueip.com/article/13351)。 ## 结论 VPS的cloud-init故障排查顺序应是“确认阶段—保存证据—验证网络和数据源—检查用户数据—核对systemd依赖—受控重跑—完整验收”。先定位实际阻塞点,再决定是否重跑,才能避免重复创建、重复安装或覆盖已有数据。初始化完成的标志不是页面显示成功,而是配置、服务和日志都能被复核。 **Tags:** Linux服务器, Ubuntu服务器, VPS, VPS监控, 云服务器 **Categories:** 行业洞察 ---