Linux 云服务器 SSH 无法访问时,通过救援机挂载系统盘修复 /run/sshd 教程

一、适用场景

本文适用于以下场景:

Linux 云服务器无法通过 SSH 登录
SSH 端口连接失败或 Connection refused
云控制台无法直接登录,或没有系统密码
系统盘可以从故障服务器卸载并挂载到救援机
系统为 Ubuntu / Debian 系列
SSH 服务为 ssh / sshd

常见故障表现:

nc -vz <目标服务器IP> <SSH端口>

返回:

Connection refused

说明网络能到达目标服务器,但目标端口没有服务监听。

如果检查 sshd 配置时报错:

sudo chroot /mnt/rescue sshd -t

返回:

Missing privilege separation directory: /run/sshd

说明 sshd 启动依赖的 /run/sshd 目录不存在,可能导致 SSH 服务无法正常启动。


二、处理思路

整体流程如下:

1. 给故障服务器创建快照或镜像备份
2. 停止故障服务器
3. 卸载故障服务器系统盘
4. 将系统盘挂载到一台正常救援机
5. 在救援机上挂载故障系统盘
6. 检查 SSH 配置
7. 修复 /run/sshd 缺失问题
8. 增加 systemd 和 tmpfiles 兜底配置
9. 启用 SSH 服务
10. 卸载系统盘
11. 挂回原服务器
12. 启动原服务器并验证 SSH

三、云平台控制台操作

不同云厂商界面名称略有差异,例如 AWS、腾讯云、阿里云、华为云,但思路一致。

1. 创建备份

操作系统盘前,建议先做快照或镜像。

通用操作路径:

云服务器控制台 → 选择故障实例 → 系统盘 / 云硬盘 → 创建快照

或者:

云服务器控制台 → 选择故障实例 → 创建镜像

建议命名格式:

<服务器名称>-before-ssh-fix-YYYYMMDD

例如:

app-prod-01-before-ssh-fix-20260508

2. 停止故障服务器

注意是 停止 / Stop,不是 销毁 / Terminate / Delete

云服务器控制台 → 选择故障实例 → 停止实例

等待实例状态变为:

Stopped / 已停止

3. 卸载系统盘

在故障实例详情中记录以下信息:

实例 ID
系统盘 ID
系统盘原挂载设备名
可用区 / Availability Zone

然后卸载系统盘:

云硬盘 / Volumes → 选择故障服务器系统盘 → 卸载

4. 挂载系统盘到救援机

救援机要求:

与故障服务器在同一个可用区
系统正常
可以 SSH 登录
建议使用同类 Linux 系统,例如 Ubuntu

将故障系统盘挂载到救援机。

设备名可以使用类似:

/dev/sdf
/dev/vdb

在部分云平台或 Nitro 架构实例中,进入系统后可能显示为:

/dev/nvme1n1

这是正常现象。


四、救援机上挂载故障系统盘

SSH 登录救援机后,查看磁盘:

lsblk

再查看文件系统:

lsblk -f

一般可以看到类似:

nvme0n1       救援机自己的系统盘
nvme1n1       挂载过来的故障系统盘
└─nvme1n1p1   故障系统盘分区

创建挂载目录:

sudo mkdir -p /mnt/rescue

挂载故障系统盘分区:

sudo mount <故障盘分区> /mnt/rescue

示例:

sudo mount /dev/nvme1n1p1 /mnt/rescue

如果不是 nvme1n1p1,需要根据 lsblk -f 的结果选择正确分区。

确认挂载成功:

ls /mnt/rescue

正常应该能看到类似目录:

bin  boot  dev  etc  home  lib  opt  proc  root  run  usr  var

五、检查 SSH 配置

1. 检查主配置文件

sudo grep -nE '^(Port|ListenAddress|PubkeyAuthentication|PasswordAuthentication|UsePAM)' /mnt/rescue/etc/ssh/sshd_config

重点关注:

Port <SSH端口>
PubkeyAuthentication
PasswordAuthentication
UsePAM

例如:

Port 22

或者:

Port 2222

如果服务器使用了非标准端口,要确认这里配置的是实际 SSH 登录端口。


2. 检查 sshd_config.d 覆盖配置

Ubuntu 云镜像经常会在下面目录放额外配置:

sudo ls -l /mnt/rescue/etc/ssh/sshd_config.d/

继续检查是否有覆盖配置:

sudo grep -RniE '^(Port|ListenAddress|PubkeyAuthentication|PasswordAuthentication|DenyUsers|AllowUsers|AllowGroups|MaxStartups)' /mnt/rescue/etc/ssh/sshd_config.d/ 2>/dev/null

如果看到:

PasswordAuthentication no

一般表示禁止 SSH 密码登录,只允许密钥登录。
这通常是云服务器默认安全配置,不一定是问题。


六、进入 chroot 检查 sshd

挂载 chroot 所需目录:

sudo mount --bind /dev /mnt/rescue/dev
sudo mount --bind /proc /mnt/rescue/proc
sudo mount --bind /sys /mnt/rescue/sys

检查 sshd 配置:

sudo chroot /mnt/rescue sshd -t
echo $?

如果正常,通常没有输出,并返回:

0

如果返回:

Missing privilege separation directory: /run/sshd

说明 /run/sshd 缺失,需要继续修复。


七、修复 /run/sshd 缺失问题

1. 临时创建 /run/sshd

sudo mkdir -p /mnt/rescue/run/sshd
sudo chmod 755 /mnt/rescue/run/sshd

再次检查:

sudo chroot /mnt/rescue sshd -t
echo $?

期望返回:

0

2. 增加 systemd 启动兜底配置

因为 /run 是临时目录,系统重启后 /run/sshd 不会永久保留,所以需要让 systemd 每次启动 SSH 服务前自动创建该目录。

创建 override 目录:

sudo mkdir -p /mnt/rescue/etc/systemd/system/ssh.service.d

写入配置:

sudo tee /mnt/rescue/etc/systemd/system/ssh.service.d/override.conf >/dev/null <<'EOF'
[Service]
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
EOF

作用:

启动 ssh 服务前自动创建 /run/sshd
目录权限为 0755

3. 增加 tmpfiles 兜底配置

创建 tmpfiles 配置目录:

sudo mkdir -p /mnt/rescue/etc/tmpfiles.d

写入配置:

echo 'd /run/sshd 0755 root root -' | sudo tee /mnt/rescue/etc/tmpfiles.d/sshd.conf

作用:

系统启动时通过 systemd-tmpfiles 自动创建 /run/sshd

八、启用 SSH 服务并最终检查

启用 SSH 服务开机自启:

sudo chroot /mnt/rescue systemctl enable ssh

再次检查 sshd 配置:

sudo chroot /mnt/rescue sshd -t
echo $?

期望返回:

0

如果返回 0,说明 SSH 配置正常。


九、卸载故障系统盘

先切换到根目录,避免挂载目录被占用:

cd /

卸载所有挂载:

sudo umount -R /mnt/rescue

确认没有挂载残留:

lsblk

如果提示 busy,可以检查是否还有进程占用:

sudo lsof +f -- /mnt/rescue

或重新执行:

cd /
sudo umount -R /mnt/rescue

十、挂回原服务器

在云平台控制台中操作:

云硬盘 / Volumes → 选择故障系统盘 → 从救援机卸载

等待磁盘状态变为空闲或可挂载。

然后挂回原服务器:

云硬盘 / Volumes → 选择故障系统盘 → 挂载到原服务器

注意:

设备名必须使用原来的系统盘设备名

常见设备名:

/dev/sda1
/dev/xvda
/dev/vda

具体以云平台原实例详情中记录的 Root device name 为准。


十一、启动原服务器并验证

启动原服务器:

云服务器控制台 → 选择原实例 → 启动实例

启动完成后,在跳板机或同网络服务器上测试 SSH 端口:

nc -vz <目标服务器IP> <SSH端口>

正常结果:

Connection to <目标服务器IP> <SSH端口> port [tcp/*] succeeded!

测试 SSH 登录:

chmod 400 <密钥文件>
ssh -i <密钥文件> -p <SSH端口> <用户名>@<目标服务器IP>

示例:

chmod 400 /tmp/server.pem
ssh -i /tmp/server.pem -p 22 ubuntu@<目标服务器IP>

如果使用非标准端口:

ssh -i /tmp/server.pem -p <SSH端口> ubuntu@<目标服务器IP>

登录成功后,检查 SSH 服务状态:

sudo systemctl status ssh

检查监听端口:

sudo ss -lntp | grep <SSH端口>

检查 sshd 配置:

sudo sshd -t
echo $?

期望返回:

0

十二、恢复后建议加固

1. 设置 VNC / 控制台备用登录密码

为了避免下次 SSH 异常时完全无法进入系统,建议给普通运维用户设置系统密码。

例如 Ubuntu 默认用户:

sudo passwd ubuntu

检查用户状态:

sudo passwd -S ubuntu

如果看到类似:

ubuntu P ...

说明密码可用。

以后通过云控制台 VNC 登录:

login: ubuntu
Password: 输入设置的系统密码

登录后提权:

sudo -i

注意:这不等于开启 SSH 密码登录。
SSH 仍然可以保持密钥登录。


2. 不建议长期开启 root SSH 密码登录

如果只是为了 VNC 兜底,建议设置普通用户密码,不建议开启 root SSH 密码登录。

SSH 推荐配置:

PasswordAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes

十三、故障原因说明

/run 是运行时临时目录,通常由 tmpfs 提供:

mount | grep ' /run '

正常情况下:

/run 目录会在系统启动后生成
/run/sshd 不会永久保存在磁盘上
SSH 服务启动时需要 /run/sshd
正常应由 systemd 或 systemd-tmpfiles 自动创建

如果系统启动时没有正确创建 /run/sshd,sshd 可能启动失败,最终导致 SSH 端口没有监听。

典型表现:

SSH 端口 Connection refused
sshd -t 报 Missing privilege separation directory: /run/sshd

最终修复方式:

临时创建 /run/sshd
增加 systemd RuntimeDirectory=sshd
增加 tmpfiles 兜底配置
启用 ssh 服务
重新挂回系统盘并启动服务器

十四、完整命令汇总

# 1. 查看磁盘
lsblk
lsblk -f

# 2. 创建挂载目录
sudo mkdir -p /mnt/rescue

# 3. 挂载故障系统盘
sudo mount <故障盘分区> /mnt/rescue
# 示例:
# sudo mount /dev/nvme1n1p1 /mnt/rescue

# 4. 检查 ssh 主配置
sudo grep -nE '^(Port|ListenAddress|PubkeyAuthentication|PasswordAuthentication|UsePAM)' /mnt/rescue/etc/ssh/sshd_config

# 5. 检查 sshd_config.d 覆盖配置
sudo ls -l /mnt/rescue/etc/ssh/sshd_config.d/
sudo grep -RniE '^(Port|ListenAddress|PubkeyAuthentication|PasswordAuthentication|DenyUsers|AllowUsers|AllowGroups|MaxStartups)' /mnt/rescue/etc/ssh/sshd_config.d/ 2>/dev/null

# 6. 准备 chroot 环境
sudo mount --bind /dev /mnt/rescue/dev
sudo mount --bind /proc /mnt/rescue/proc
sudo mount --bind /sys /mnt/rescue/sys

# 7. 检查 sshd 配置
sudo chroot /mnt/rescue sshd -t
echo $?

# 8. 如果报 Missing privilege separation directory: /run/sshd,则创建目录
sudo mkdir -p /mnt/rescue/run/sshd
sudo chmod 755 /mnt/rescue/run/sshd

# 9. 再次检查 sshd
sudo chroot /mnt/rescue sshd -t
echo $?

# 10. 增加 systemd override
sudo mkdir -p /mnt/rescue/etc/systemd/system/ssh.service.d

sudo tee /mnt/rescue/etc/systemd/system/ssh.service.d/override.conf >/dev/null <<'EOF'
[Service]
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
EOF

# 11. 增加 tmpfiles 兜底配置
sudo mkdir -p /mnt/rescue/etc/tmpfiles.d

echo 'd /run/sshd 0755 root root -' | sudo tee /mnt/rescue/etc/tmpfiles.d/sshd.conf

# 12. 启用 ssh 服务
sudo chroot /mnt/rescue systemctl enable ssh

# 13. 最终检查
sudo chroot /mnt/rescue sshd -t
echo $?

# 14. 卸载故障系统盘
cd /
sudo umount -R /mnt/rescue

# 15. 挂回原服务器后验证
nc -vz <目标服务器IP> <SSH端口>
ssh -i <密钥文件> -p <SSH端口> <用户名>@<目标服务器IP>

十五、注意事项

  1. 操作系统盘前必须先做快照或镜像备份。
  2. 停止实例时不要误点销毁、终止、删除。
  3. 救援机必须和故障盘在同一个可用区。
  4. 挂回原服务器时,系统盘设备名要使用原来的 Root device name。
  5. /run/sshd 是运行时目录,不能只依赖手工创建,必须增加 systemd 或 tmpfiles 兜底配置。
  6. 修复完成后建议测试云控制台 VNC 登录,设置普通用户密码作为保底。
  7. 不建议长期开放 SSH 密码登录和 root 密码登录。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇