SSHFS
SSHFS 是一个基于 FUSE 的文件系统客户端,用于通过 Secure Shell (SSH) 连接挂载远程目录。
安装
- 如果您经常需要挂载 sshfs 文件系统,可以尝试使用 sshfs 辅助工具,例如 sftpman、sshmntAUR、sshfs-mountctlAUR 或 fmount.py。
- 您可以使用 Google Authenticator 或 Fido 令牌 来提供类似于两步验证的额外安全性。
- SSH 密钥 可以代替传统的密码验证使用。
用法
挂载
为了能够挂载目录,SSH 用户需要拥有该目录的访问权限。运行 sshfs 来挂载远程目录:
$ sshfs [user@]host:[dir] mountpoint [options]
例如:
$ sshfs myuser@mycomputer:/remote/path /local/path -C -p 9876
此处 -p 9876 指定端口号,-C 启用压缩。更多选项请参阅 #选项 章节。
若未指定,远程路径默认为远程用户的主目录。默认用户名和选项可以在 ~/.ssh/config 中针对每个主机预先定义,以简化 sshfs 的使用。更多信息请参阅 OpenSSH#Client usage。
如果需要,SSH 会提示输入密码。如果您不想每天多次输入密码,请参阅 SSH 密钥。
卸载
要卸载远程系统:
$ fusermount3 -u mountpoint
示例
$ fusermount3 -u /local/path
选项
完整的选项列表可以在 sshfs(1) 和 mount.fuse(8) 中找到。
用户 ID 映射
sshfs 可以自动在本地和远程用户 ID 之间进行转换。使用 idmap=user 选项将连接用户的 UID 转换为远程用户 myuser 的 UID(GID 保持不变):
$ sshfs myuser@mycomputer:/remote/path /local/path -o idmap=user
如果您需要更精细地控制 UID 和 GID 转换,请查看 idmap=file、uidfile 和 gidfile 选项。
allow_root 或 allow_other
$ sshfs myuser@mycomputer:/remote/path /local/path -o allow_other,default_permissions,uid=1002,gid=1002
allow_other- 允许非挂载者(即 root 以外的用户)访问共享目录。allow_root- 与 allow_other 类似,但文件访问权限仅限于挂载该文件系统的用户和 root。
allow_root 和 allow_other 是互斥的。此外,您需要编辑 /etc/fuse.conf 并取消注释 user_allow_other 行,以允许所有用户使用这些选项。
default_permissions- 也可以使用该选项,因为 FUSE 默认不会检查文件访问权限(即使用远程文件系统上的实际权限)。这允许禁止 allow_other 赋予其他人的访问权限。
更改挂载点所有权
uid,gid- 将文件的报告所有权设置为指定值;uid 是您用户的数字用户 ID,gid 是您用户的数字组 ID。
技巧与提示
Chroot 环境
您可能希望将特定用户限制在远程系统的特定目录中。这可以通过编辑 /etc/ssh/sshd_config 来实现:
/etc/ssh/sshd_config
.....
Match User someuser
ChrootDirectory /chroot/%u
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
.....
另请参阅 SFTP chroot。有关 Match、ChrootDirectory 和 ForceCommand 的更多信息,请查阅 sshd_config(5) 手册页。
systemd
与其他文件系统挂载类似,请参阅 systemd.mount(5) 以及可能的 systemd.automount(5)。由于 FUSE 系统及其机制,您应该使用 用户单元。配置 SSH 使用公钥身份验证。
作为用户单元
delay_connect 选项模拟按需挂载行为。示例用户单元在 ~/share/data 中挂载 sshfs 文件系统,并使用了以下选项:
_netdev,user是从系统级配置继承而来的。以普通用户身份运行时可能无关紧要,但也无害。delay_connect使 sshfs 仅在访问目录时尝试连接服务器(类似于 systemd 自动挂载单元)。reconnect使 sshfs 在连接中断后尝试重新建立连接。这在从睡眠模式恢复时非常有用。ServerAliveInterval=15每 15 秒向服务器发送一个 TCP 保活包,有助于提高响应能力。dir_cache=yes启用 sshfs 目录缓存。这也有助于提高响应能力,特别是在桌面环境中。idmap=user将远程用户的 UID/GID 映射到挂载用户的 UID/GID。请参阅 sshfs(1) § user。follow_symlinks,transform_symlinks使符号链接按预期工作(可以追踪,且绝对符号链接可以访问远程系统上的文件)。compression=yes启用 SSH 压缩。根据所涉及的文件类型,这可以显著节省带宽。
${XDG_CONFIG_HOME}/systemd/user/home-user-share-data.mount
[Mount] What=user@remote:/mnt/data Where=%h/share/data Type=sshfs Options=_netdev,user,delay_connect,reconnect,ServerAliveInterval=15,dir_cache=yes,idmap=user,follow_symlinks,transform_symlinks,compression=yes [Install] WantedBy=default.target
使用带密码的 SSH 密钥
请参阅 SSH 密钥#使用 systemd 用户启动 ssh-agent。
生成 .mount 和 .automount 文件
在 /etc/fstab 中创建一个条目,至少包含 _netdev;仅当需要自动挂载功能时才需要 x-systemd.automount。
/etc/fstab
remoteuser@remotehost:/remote/folder /home/foo/local_folder fuse.sshfs _netdev,x-systemd.automount,x-systemd.idle-timeout=5min,rw 0 0
# systemctl daemon-reload
执行 daemon-reload 后,所有生成的文件位于 /run/systemd/generator/ 中。对于用户单元,您可以复制所需文件,删除 fstab 行并重新加载 systemd。
编写 .mount 和 .automount 文件
您需要 编写两个 systemd 单元:一个挂载单元和一个可选的自动挂载单元。启用自动挂载单元而不启用挂载单元本身,不会阻塞启动过程,只有在尝试访问文件系统时才会挂载。这些文件必须完全按照挂载点命名,路径中的文件夹使用“-”分隔。
挂载单元必须完全按挂载点命名(此处 /mnt/data 变为 mnt-data):
systemd-escape -p --suffix=mount "/mnt/data/"
mnt-data.mount
/etc/systemd/system/mnt-data.mount
[Unit] Description=SSHFS (remote.local) Before=remote-fs.target [Mount] What=user@remote.local:/mnt/data Where=/mnt/data Type=fuse.sshfs Options=_netdev,rw,nosuid,allow_other,uid=1000,gid=1000,default_permissions,follow_symlinks,idmap=user,identityfile=/home/user/.ssh/id_ed25519 [Install] WantedBy=remote-fs.target WantedBy=multi-user.target
自动挂载单元文件也必须完全按挂载点命名:
/etc/systemd/system/mnt-data.automount
[Unit] Description=Automount /mnt/data [Automount] Where=/mnt/data TimeoutIdleSec=0 [Install] WantedBy=multi-user.target
systemd root 挂载与多用户
自动挂载可以在开机时或按需(访问目录时)发生。两者都需要在 fstab 中进行设置。
.ssh/config 中配置的主机。要让 root 用户使用普通用户的 SSH 密钥,请在 IdentityFile 选项中指定其完整路径。
最重要的是,在客户端机器上以 root 身份手动至少挂载一次每个 sshfs 挂载点,以便将主机的签名添加到客户端的 /root/.ssh/known_hosts 文件中。或者,手动将一个或多个 SSH 服务器的公共主机密钥(/etc/ssh/ssh_host_*key.pub 文件)追加到 /root/.ssh/known_hosts 中。
按需挂载
使用 systemd,可以通过 /etc/fstab 条目实现按需挂载。
示例
user@host:/remote/path /local/path fuse.sshfs x-systemd.automount,_netdev,users,idmap=user,IdentityFile=/home/user/.ssh/id_rsa,allow_other,reconnect 0 0
这里重要的挂载选项是 x-systemd.automount,_netdev。
- x-systemd.automount 实现了按需挂载的神奇功能。
- _netdev 告诉它这是一个网络设备,而不是块设备(如果不加此项,可能会出现“No such device”错误)。
另请参阅 fstab#使用 systemd 自动挂载。
开机自动挂载
一个关于如何通过 /etc/fstab 使用 sshfs 挂载远程文件系统的示例:
user@host:/remote/path /local/path fuse.sshfs _netdev 0 0
以该 fstab 行为例:
llib@192.168.1.200:/home/llib/FAH /media/FAH2 fuse.sshfs _netdev 0 0
如果您为该用户使用了无密码的 SSH 密钥,上述设置将自动工作。请参阅 使用 SSH 密钥。
如果您想在多用户环境下使用 sshfs,请添加以下选项:
user@domain.org:/home/user /media/user fuse.sshfs allow_other,_netdev 0 0
为了确保在尝试挂载之前网络可用,除了设置 _netdev 挂载选项外,还要在相应的 网络等待在线服务 (wait-online service) 中添加 --any 或特定的 --interface 参数。
安全用户访问
通过 fstab 自动挂载时,文件系统通常由 root 挂载。如果您希望以普通用户身份访问并限制其他用户的访问,默认配置会产生不理想的结果。
挂载点配置示例:
user@host:/remote/path /local/path fuse.sshfs noauto,x-systemd.automount,_netdev,user,idmap=user,follow_symlinks,identityfile=/home/user/.ssh/id_rsa,allow_other,default_permissions,uid=USER_ID_N,gid=USER_GID_N 0 0
有关所用选项的说明,请参阅 #allow_root 或 allow_other。
故障排除
核对表
先阅读 OpenSSH#Checklist。还需要检查以下问题:
- 您的 SSH 登录是否发送了服务器
/etc/issue文件中的额外信息?这可能会混淆 SSHFS。您应该暂时禁用服务器的/etc/issue文件。$ mv /etc/issue /etc/issue.orig
- 请记住,网上找到的大多数 SSH 疑难解答文章都与 systemd 无关。通常
/etc/fstab的定义错误地以sshfs#user@host:/mnt/server/directory ... fuse ...
开头,而不是使用以下语法:user@host:/mnt/server/directory ... fuse.sshfs ... x-systemd, ...
- 检查服务器源目录及其内容的所有者是否为服务器对应的用户。
$ chown -R user_s: /mnt/servers/directory
- 服务器的用户 ID 可能与客户端不同。显然,两个用户名必须相同。您只需要注意客户端的用户 ID。SSHFS 会通过以下挂载选项为您转换 UID:
uid=USER_C_ID,gid=GROUP_C_ID
- 检查客户端的目标挂载点(目录)是否归客户端用户所有。该目录应具有与 SSHFS 挂载选项中定义的 UID 相同的用户 ID。
$ chown -R user_c: /mnt/client/directory
- 检查客户端的挂载点(目录)是否为空。默认情况下,您不能将 SSHFS 目录挂载到非空目录中。
Connection reset by peer (连接被对端重置)
- 如果您尝试通过主机名访问远程系统,请尝试使用 IP 地址,这可能是域名解析问题。确保在
/etc/hosts中填入了服务器详细信息。 - 确保您的用户可以登录服务器(特别是在使用
AllowUsers时)。 - 确保远程系统
/etc/ssh/sshd_config中启用了Subsystem sftp /usr/lib/ssh/sftp-server。 - 如果您使用的是非默认密钥名并将其作为
-i .ssh/my_key传递,这是行不通的。您必须使用-o IdentityFile=/home/user/.ssh/my_key,并提供密钥的完整路径。 - 如果您的
/root/.ssh/config/是一个符号链接,您也会遇到此错误。请参阅 此 Serverfault 主题。 - 添加
sshfs_debug选项(例如sshfs -o sshfs_debug user@server ...)有助于解决该问题。 - 如果这没有显示任何有用的信息,您也可以尝试添加
debug选项。 - 如果您尝试 sshfs 到运行 DD-WRT 或类似固件的路由器,此处有一个解决方案。(注意:可以使用
-osftp_server=/opt/libexec/sftp-server选项代替打补丁)。 - 如果仅在启动时看到此错误,可能是因为 systemd 在网络连接可用之前尝试挂载。为您的网络管理器启用适当的 网络等待在线服务 (wait-online service) 即可修复。
- 旧论坛主题:sshfs: Connection reset by peer。
sshfs -o sshfs_debug,IdentityFile=/path/to/key user@server ...。Remote host has disconnected (远程主机已断开连接)
如果您在尝试使用 sshfs 后直接收到此消息:
- 首先确保远程机器已安装 sftp!否则无法工作。
- 然后,检查远程机器
/etc/ssh/sshd_config中Subsystem sftp的路径是否有效。
fstab 挂载问题
要获取详细的调试输出,请将以下内容添加到挂载选项中:
ssh_command=ssh\040-vv,sshfs_debug,debug
\040 表示 fstab 用于分隔字段的空格。要能够运行 mount -av 并查看调试输出,请移除以下内容:
noauto,x-systemd.automount
某些目录为空
sshfs 默认不支持符号链接。如果这些目录碰巧是符号链接,请使用:
$ sshfs user@host:/remote/path /local/path -o follow_symlinks
文件未刷新
如果您在远程端看到旧内容,请考虑使用 dir_cache=no 选项。
$ sshfs user@host:/remote/path /local/path -o dir_cache=no
高速网络下传输速度受限
如果您发现传输速度低于网络带宽上限且文件拷贝端的 CPU 使用率很高,请禁用压缩(移除 -C 选项或设置 -o compression=no)。
参见
- 如何挂载 Chrooted SSH 文件系统,需特别注意所有者和权限问题。