通过 sshfs 把远程集群目录挂载到本地(wsl)

适用场景:本地 WSL 编辑代码,远程 HPC/集群运行计算,通过 sshfs 把集群上的源码目录和数据目录像本地磁盘一样使用。 本教程只讲目录挂载这件事是怎么做到的。


一句话概括

sshfs(SSH Filesystem)通过 SSH 协议把远程服务器上的一个目录映射成本地文件系统里的普通目录。挂载后,lscdvimcode . 等操作与本地无异,改动实时同步到远程。


前置条件

1 本地环境

  • WSL2 / Linux / macOS 终端
  • 已安装 sshsshfstmuxfusermount

检查命令:

ssh -V
sshfs -V
tmux -V
which fusermount

安装:

sudo apt update
sudo apt install -y ssh sshfs tmux

2 远程集群侧

  • 已开通账号,已知用户名和登录节点地址
  • 已上传 SSH 公钥到集群
  • 集群开启动态二次验证(如 Google Authenticator)

3 目录信息

远程目录 本地挂载点 用途
/public/home/your_username ~/shenma/cluster_home 源码、个人配置
/data/share/your_username ~/shenma/cluster_data 计算结果、大文件

核心原理

本地程序
   │
   ▼
~/shenma/cluster_home
   │   FUSE / sshfs
   ▼
SSH 隧道
   │
   ▼
cluster:/public/home/your_username
  • sshfs:把本地挂载点的读写请求翻译成 SFTP 命令,通过 SSH 发到远程。
  • ControlMaster:第一条 SSH 完成认证后创建控制套接字,后续连接复用,免再次认证。
  • tmux:在后台保持交互式终端会话,让动态验证码登录长期有效。

配置 SSH

编辑 ~/.ssh/config

Host cluster
    HostName cluster.example.com
    User your_username
    Port 22

    IdentityFile ~/.ssh/id_ed25519_cluster

    ControlMaster auto
    ControlPath ~/.ssh/controlmasters/
    ControlPersist 8h

    ForwardX11 yes
    ForwardX11Trusted yes

    ServerAliveInterval 30
    ServerAliveCountMax 3

创建控制套接字目录:

mkdir -p ~/.ssh/controlmasters
chmod 700 ~/.ssh/controlmasters

测试:

ssh cluster

建立 SSH 主连接

创建挂载点:

mkdir -p ~/shenma/cluster_home
mkdir -p ~/shenma/cluster_data

在 tmux 中启动 SSH:

tmux new-session -d -s cluster-master "ssh -Y cluster"

进入 tmux 输入验证码:

tmux attach -t cluster-master

输入 Google Authenticator 验证码后,按 Ctrl+B 再按 D 分离会话。

验证主连接:

ssh -O check cluster

应看到 Master running (pid=...)


挂载远程目录

sshfs cluster:/public/home/your_username ~/shenma/cluster_home
sshfs cluster:/data/share/your_username ~/shenma/cluster_data

查看挂载:

df -h | grep sshfs

验证挂载

mountpoint -q ~/shenma/cluster_home && echo "cluster_home 已挂载"
ls -la ~/shenma/cluster_home

测试写入:

echo "hello" > ~/shenma/cluster_home/sshfs_test.txt
cat ~/shenma/cluster_home/sshfs_test.txt
rm ~/shenma/cluster_home/sshfs_test.txt

使用与卸载

使用挂载目录:

cd ~/shenma/cluster_home/your_project
vim some_file.cpp
ls ~/shenma/cluster_data/your_case

卸载:

fusermount -u ~/shenma/cluster_home
fusermount -u ~/shenma/cluster_data
ssh -O exit cluster
tmux kill-session -t cluster-master

一键管理脚本

下面脚本把上面的所有操作封装成菜单,保存为 ~/shenma/scripts/cluster-mount.sh

#!/usr/bin/env bash
# cluster-mount.sh — 检查/建立/关闭 sshfs 挂载与 SSH ControlMaster
#
# 使用前修改:SSH_HOST、SSHFS_HOME_REMOTE、SSHFS_DATA_REMOTE

set -euo pipefail

SSH_HOST="${SSH_HOST:-cluster}"
TMUX_SESSION="${TMUX_SESSION:-cluster-master}"

SSHFS_HOME_LOCAL="${SSHFS_HOME_LOCAL:-$HOME/shenma/cluster_home}"
SSHFS_HOME_REMOTE="${SSHFS_HOME_REMOTE:-/public/home/your_username}"

SSHFS_DATA_LOCAL="${SSHFS_DATA_LOCAL:-$HOME/shenma/cluster_data}"
SSHFS_DATA_REMOTE="${SSHFS_DATA_REMOTE:-/data/share/your_username}"

R='\033[0;31m'
G='\033[0;32m'
Y='\033[1;33m'
B='\033[0;34m'
N='\033[0m'

function menu() {
    echo -e "\n${B}sshfs 集群目录挂载管理${N}"
    echo -e "  1) 检查状态并修复"
    echo -e "  2) 断开连接"
    echo -e "  3) 退出"
    read -rp "请选择 [1-3]: " choice
}

function check_ssh_master() {
    if ssh -O check "$SSH_HOST" 2>/dev/null; then
        echo -e "${G}✓ SSH master 已连接${N}"
        return 0
    else
        echo -e "${Y}✗ SSH master 未连接${N}"
        return 1
    fi
}

function check_mount() {
    local local_path="$1" name="$2"
    if mountpoint -q "$local_path" 2>/dev/null; then
        echo -e "${G}✓ $name 已挂载 ($local_path)${N}"
        return 0
    else
        echo -e "${Y}✗ $name 未挂载 ($local_path)${N}"
        return 1
    fi
}

function repair_mount() {
    local local_path="$1" remote_path="$2" name="$3"
    if mountpoint -q "$local_path" 2>/dev/null; then return 0; fi

    echo -e "${Y}→ 重新挂载 $name${N}"
    mkdir -p "$local_path"
    if sshfs "$SSH_HOST:$remote_path" "$local_path"; then
        echo -e "${G}✓ $name 挂载成功${N}"
    else
        echo -e "${R}✗ $name 挂载失败${N}"
        return 1
    fi
}

function rebuild_ssh_master() {
    echo -e "\n${Y}SSH master 断开,需要重建。${N}"
    echo -e "${Y}请在 tmux 窗口中输入 Google Authenticator 验证码,然后按 Ctrl+B 再按 D 离开。${N}"
    read -n1 -rsp "按任意键继续 ..." tmp
    echo

    ssh -O exit "$SSH_HOST" 2>/dev/null || true
    tmux kill-session -t "$TMUX_SESSION" 2>/dev/null || true

    tmux new-session -d -s "$TMUX_SESSION" "ssh -Y $SSH_HOST"
    tmux attach -t "$TMUX_SESSION"
}

function do_check() {
    echo -e "\n${B}==> 当前状态${N}"
    local ssh_ok=true mount1_ok=true mount2_ok=true

    check_ssh_master || ssh_ok=false
    check_mount "$SSHFS_HOME_LOCAL" "home 目录" || mount1_ok=false
    check_mount "$SSHFS_DATA_LOCAL" "数据目录" || mount2_ok=false

    if [[ "$ssh_ok" == true && "$mount1_ok" == true && "$mount2_ok" == true ]]; then
        echo -e "\n${G}所有状态正常。${N}"
        return 0
    fi

    read -rp "状态异常,是否修复? [Y/n]: " confirm
    if [[ "$confirm" == [nN]* ]]; then
        echo -e "${Y}已取消修复。${N}"
        return 0
    fi

    do_repair
}

function do_repair() {
    echo -e "\n${B}==> 开始修复${N}"

    if ! check_ssh_master; then
        rebuild_ssh_master
        if ! check_ssh_master; then
            echo -e "${R}✗ SSH master 重建失败。${N}"
            return 1
        fi
    fi

    repair_mount "$SSHFS_HOME_LOCAL" "$SSHFS_HOME_REMOTE" "home 目录"
    repair_mount "$SSHFS_DATA_LOCAL" "$SSHFS_DATA_REMOTE" "数据目录"

    echo -e "\n${G}修复完成。${N}"
}

function do_shutdown() {
    echo -e "\n${B}==> 关闭连接${N}"

    for mp in "$SSHFS_HOME_LOCAL" "$SSHFS_DATA_LOCAL"; do
        if mountpoint -q "$mp" 2>/dev/null; then
            fusermount -u "$mp" && echo -e "${G}✓ 已卸载 $mp${N}" || echo -e "${R}✗ 卸载失败 $mp${N}"
        else
            echo -e "${Y}  未挂载 $mp${N}"
        fi
    done

    if ssh -O check "$SSH_HOST" 2>/dev/null; then
        ssh -O exit "$SSH_HOST" && echo -e "${G}✓ SSH master 已关闭${N}" || echo -e "${R}✗ 关闭失败${N}"
    else
        echo -e "${Y}  SSH master 未运行${N}"
    fi

    if tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then
        tmux kill-session -t "$TMUX_SESSION" && echo -e "${G}✓ tmux 会话已关闭${N}" || echo -e "${R}✗ 关闭失败${N}"
    else
        echo -e "${Y}  tmux 会话不存在${N}"
    fi

    echo -e "\n${G}连接已清理。${N}"
}

function main() {
    while true; do
        menu
        case "$choice" in
            1) do_check ;;
            2)
                read -rp "确定断开连接? [y/N]: " confirm
                if [[ "$confirm" == [yY]* ]]; then
                    do_shutdown
                else
                    echo -e "${Y}已取消。${N}"
                fi
                ;;
            3)
                echo -e "${B}再见。${N}"
                exit 0
                ;;
            *) echo -e "${R}无效选择,请输入 1-3。${N}" ;;
        esac
    done
}

main "$@"

用法:

chmod +x ~/shenma/scripts/cluster-mount.sh
bash ~/shenma/scripts/cluster-mount.sh

菜单选项:

  1. 检查状态并修复:自动检查 SSH master 和挂载,缺失时提示输入验证码并修复。
  2. 断开连接:卸载、关闭 SSH master、关闭 tmux 会话。
  3. 退出:退出脚本。

故障排查

1 命令找不到

sudo apt update
sudo apt install -y sshfs

2 `read: Connection reset by peer`

SSH master 断开,重新执行:

tmux new-session -d -s cluster-master "ssh -Y cluster"

3 挂载点显示为空

检查主连接是否仍在:

ssh -O check cluster

4 卸载时提示 busy

先关闭占用挂载点的进程:

lsof ~/shenma/cluster_home
fusermount -uz ~/shenma/cluster_home

5 验证码反复失败

确认手机时间与服务器时间同步。动态验证码窗口通常只有 30 秒。

6 ControlMaster 自动断开

调小 ServerAliveInterval 或增大 ControlPersist


FAQ

1 sshfs 和 NFS 有什么区别?

sshfs 走 SSH 协议,不需要 NFS 服务或管理员权限,适合个人工作站临时挂载。NFS 性能更高,但需要服务端配置。

2 为什么不用密码登录?

集群安全策略通常禁用密码静态登录,必须密钥 + 二次验证。

3 可以不挂 tmux 吗?

如果你不需要二次验证,或集群支持免交互认证,可以直接 sshfs 挂载。需要动态验证码时,tmux 是最稳定的方案。

4 挂载后编辑大文件慢怎么办?

sshfs 适合源码、小文件和查看结果。频繁读写大文件建议用 rsync 同步或直接在集群上操作。

5 如何在 macOS 上使用?

安装 macFUSE 和 sshfs:

brew install macfuse sshfs tmux

然后按本教程相同步骤配置即可。

文章链接:https://sunwaybits.tech/mount-a-remote-cluster-directory-to-your-local-machine-wsl-using-sshfs/
文章标题:通过 sshfs 把远程集群目录挂载到本地(wsl)
文章作者:zs
暂无评论

发送评论 编辑评论


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