1. 从一天插拔几十次U盘说起:共享文件夹在传文件方式里的真实位置
有段时间我在一台 Windows 主力机上做调试,代码在 Windows 的编辑器里写,编译、烧录、跑测试放在 Ubuntu 虚拟机里,日志和产物文件来回倒。一开始用 U 盘,后来用拖拽,再后来干脆架 SMB,没一个省心的。最后我还是回到VMware 共享文件夹,一天读写几十次,稳定得像本地盘。很多人对这个功能的印象停留在"时灵时不灵""Linux 下挂不上""重启就没了",实际上绝大多数问题出在 Tools 层和挂载层的细节上,而不是这个功能本身不行。
这篇东西我不打算写成产品说明书。我会按一个实际使用者的路径来讲:先讲清楚它和拖拽、SMB 的本质区别,再讲 VMware Tools 和 open-vm-tools 这个地基怎么打,然后是主机侧设置面板里每个字段到底意味着什么,接着分 Windows 客户机和 Linux 客户机两条线走,把"找不到文件""重启失效""权限不对"这些高频问题拆开。最后聊几个文档里基本不写、但会实实在在坑到你的点,比如软链接、快照回滚、大量小文件性能。如果你手上正好有一台 Workstation 和一台 Linux 虚拟机,跟着走一遍基本能跑通。
1.1 拖拽和剪贴板为什么撑不起日常开发
先说拖拽。它的体验在图形化桌面里看着挺美,但底层其实还是走 VMware 的宿主-客户机通道,跟共享文件夹是同一套机制的两种表现。这意味着共享文件夹挂了,拖拽大概率也挂了;反过来拖拽能用,说明底层通道是通的。更要命的是几个实际限制:大文件拖到一半断掉没有断点续传,只能从头再来;传输过程中界面经常假死,你不知道它是在传还是已经卡死;Linux 客户机上拖拽的支持依赖桌面环境和open-vm-tools-desktop,缺一个组件就是灰的。
剪贴板共享就更窄了,它本质是文本通道,传文件不现实。有人用它把文件内容复制成文本再粘过去,几十 KB 还行,上百兆的固件包就别想了,而且粘贴过程中编码一变内容就废了。
所以拖拽和剪贴板适合"偶尔传一个小文件",不适合"构建产物直接落盘"这种高频、大体积的场景。真正的开发流程里,你希望的是虚拟机里的编译输出目录,直接就是你主机上的一个文件夹,IDE 直接读、Git 直接提交、打包脚本直接扫,一步到位。这才是共享文件夹要解决的问题。
1.2 共享文件夹走的是私有通道,不是网络共享
这是最容易混淆的一点,也是很多人排查方向跑偏的根源。VMware 共享文件夹不是 SMB,不是 NFS,也不是什么网络协议,它是 VMware 自己的 HGFS(Host-Guest File System)机制。主机侧的vmx进程把指定目录暴露出来,客户机侧的驱动(Windows 下是 VMware HGFS 网络提供程序,Linux 下是vmhgfs-fuse这个 FUSE 驱动)把它挂成一个文件系统。
这个区别带来几个直接后果。第一,共享文件夹不依赖客户机的网络栈。你虚拟机的网卡没配好、IP 是 169.254 开头的、甚至干脆把网卡断开了,共享文件夹照样能用。第二,共享文件夹没法被局域网里其他物理机访问,因为它压根没有对外监听端口,数据只在这台主机和这台客户机之间流动。第三,Windows 客户机里访问它用的是\\vmware-host\Shared Folders\...这种看起来像 UNC 路径的写法,但解析它的不是 SMB 客户端,是 VMware 装的那个网络提供程序,所以它不需要输入账号密码,也不受 SMB 版本策略影响。
我列个表把三种方式摆在一起,你一眼就能看出各自的地盘:
| 维度 | VMware 共享文件夹 | SMB/CIFS 网络共享 | 拖拽/剪贴板 |
|---|---|---|---|
| 依赖 | VMware Tools / open-vm-tools | 客户机网络 + 主机共享服务 | VMware Tools |
| 跨物理机访问 | 不支持 | 支持 | 不支持 |
| 是否需要账号 | 不需要 | 需要(可保存凭证) | 不需要 |
| 断开网卡能否用 | 可以 | 不可以 | 可以 |
| 权限粒度 | 粗(只读/读写,uid/gid) | 细(ACL、用户组) | 无 |
| 大量小文件性能 | 中等 | 取决于网络和磁盘 | 差 |
| 断点续传 | 文件系统级读写,天然支持 | 同左 | 不支持 |
看这张表就能明白,共享文件夹的定位是"本机开发辅助",SMB 的定位是"多机协作"。用错场景,自然会觉得难用。
1.3 我在哪些场景里会毫不犹豫地开共享文件夹
第一类,构建产物直出。虚拟机里编译出来的二进制、镜像、安装包,直接写到共享目录,主机的 IDE 或打包脚本立刻能读到,省掉一次手动拷贝。第二类,源代码双向编辑。主机上用顺手的编辑器改代码,虚拟机里跑编译;或者反过来在虚拟机里改配置文件,主机上直接看 diff。第三类,日志和调试信息回传。虚拟机里跑的服务把日志写到共享目录,主机上用日志工具实时盯着。第四类,网络没配好但急着传文件的救急场景。
反过来,有几个场景我会刻意避开共享文件夹。需要给同事的机器访问的目录,走 SMB;需要精细到"某个组只能读某个子目录"的权限控制,走 SMB;需要在虚拟机里跑node_modules、Python 虚拟环境这种软链接满天飞的依赖目录,我会把依赖装在客户机本地磁盘,只把源码放共享目录。这些判断背后的原因,后面几节会一个一个拆开讲。
2. 地基先打牢:VMware Tools 和 open-vm-tools 到底该装哪个
共享文件夹功能的所有表现,最终都取决于客户机侧的 HGFS 驱动有没有正常工作。而驱动来自 VMware Tools。所以这一节是整篇的基础,Tools 没搞定,后面所有配置都是白费力气。
2.1 共享文件夹功能真正的依赖链路
拆开看,这条链路上有四个环节。第一,主机侧vmx进程读取虚拟机配置里sharedFolder那一段,决定对外暴露哪些目录、是只读还是可写。第二,客户机侧的 HGFS 驱动负责把.host:/这个伪路径解析成主机暴露的目录树。第三,Mount 层把它挂到一个具体路径上,Linux 下是/mnt/hgfs,Windows 下是一个网络位置。第四,权限层决定你当前登录的用户能不能读写。
四个环节里,最容易出问题的是第二和第三。第一环节基本由图形界面保证,第四环节是参数没配对。所以排查的时候,顺序应该是:先确认主机侧配置勾了没勾,再确认客户机里vmware-hgfsclient能不能列出共享名(这一步验证的就是第二环节),然后看挂载是否成功,最后才查权限。
2.2 Windows 客户机上的 Tools 装法
Workstation 菜单里点"虚拟机 > 安装 VMware Tools",它会把一个 ISO 挂到虚拟光驱上。进到客户机里打开光驱,运行setup.exe,一路下一步,装完重启。这里有个小坑:如果是 Windows 11 客户机,装完可能不会自动弹重启提示,你以为装好了直接去访问\\vmware-host,会发现什么都没有。老老实实手动重启一次。
验证装没装成功,看两个地方。设备管理器里应该能看到 VMware 相关的设备,没有黄色感叹号;服务列表里VMware Tools Service(服务名VMTools)应该是运行状态。这个服务很关键,它负责在系统启动早期把 HGFS 网络提供程序注册进去,服务没起来,浏览器里敲\\vmware-host就是"找不到网络路径"。
还有一点值得说:Windows 客户机里的共享文件夹是通过一个叫 VMware HGFS 的网络提供程序实现的,它在资源管理器里表现为"网络"节点下的vmware-host这台"计算机"。如果你在资源管理器里点"网络"看不到它,十有八九是客户机的网络发现被关了。网络发现这个开关本来是给 SMB 浏览用的,但资源管理器在网络节点下做枚举时也会受它影响。直接敲\\vmware-host反而更干脆,能绕过浏览枚举,直接走名称解析。
2.3 Linux 客户机:我更推荐 open-vm-tools
Linux 这边我强烈建议用发行版仓库里的open-vm-tools,别用 Workstation 挂进来的那套官方 Tools 安装包。原因很实际:官方 Tools 是编译安装的,内核一升级,编译出来的vmhgfs模块就和新内核对不上,得重新跑一遍安装脚本;而open-vm-tools走 DKMS 或者发行版的内核模块机制,apt upgrade或者dnf update的时候自动重建,省心太多。
Debian / Ubuntu / Kali 系:
sudo apt update sudo apt install -y open-vm-tools open-vm-tools-desktop fuse3RHEL / Rocky / 银河麒麟这类 RPM 系:
sudo dnf install -y open-vm-tools open-vm-tools-desktop fuse装完记得确认服务状态:
systemctl status open-vm-tools需要说明的是,open-vm-tools提供后台服务、时钟同步、内存气球这些能力,open-vm-tools-desktop提供拖拽、剪贴板、分辨率自适应。共享文件夹本身只依赖前者。所以如果你装的是最小化系统、跑的是服务器,只装open-vm-tools就够了,不需要拖桌面那套进来。这一点很多教程没说清楚,导致一堆人往服务器上装-desktop,平白多出一堆依赖。
2.4 "继续运行脚本未能在虚拟机中成功运行"这类报错怎么读
装官方 Tools 的过程中,经常蹦出一条提示,大意是脚本没能在虚拟机里成功运行,问你要不要继续。看到这个提示,很多人第一反应是"是不是要重装",其实这条信息的含义很窄:Tools 的安装脚本在最后阶段要编译并加载内核模块,这一步失败了。
常见的几个原因。编译工具链不全,缺gcc、make、perl;内核头文件没装,或者装的头文件和当前运行内核的版本对不上;Secure Boot 开着,自编译的内核模块签名不被信任,加载被拒;某些发行版默认不带dkms,模块没法自动重建。
排查顺序我一般是这样的:先uname -r看当前内核版本,再确认/lib/modules/$(uname -r)/build这个软链接指向的头文件目录存在且完整,然后确认gcc、make、perl都在。Secure Boot 的话,mokutil --sb-state一看便知,要么关掉,要么走签名流程。
不过说句实话,这条报错最省事的处理方式根本不是去修它,而是直接卸载官方 Tools,换 open-vm-tools。我经手过的环境里,凡是卡在这个提示上的,九成换成 open-vm-tools 之后五分钟解决。官方 Tools 在近几年的主流发行版上兼容性确实不如开源版,这不是我一个人的感受。
3. 主机侧设置面板:每个字段都在决定什么
配置入口在"虚拟机 > 设置 > 选项 > 共享文件夹"。这个面板字段不多,但每一个都有实际含义,填错了就会出现"明明勾了却看不见"的怪现象。
3.1 三个字段和两个复选框的准确含义
面板里最核心的是"文件夹名称"和"主机路径"。这里有个特别容易踩的坑:客户机里看到的目录名是"文件夹名称"这个字段的值,不是主机路径的最后一级目录名。很多人主机路径填D:\project\firmware,文件夹名称随手也填firmware,那没问题;但如果他填的是D:\project\firmware,名称填了fw,那客户机里就是/mnt/hgfs/fw,他跑去/mnt/hgfs/firmware找,自然找不到。这种"路径对不上"的困惑,我在群里见过太多次了。
"属性"里有两个勾:一个是"启用此共享",另一个是"只读"。还有个"始终启用"的选项,用于决定这个共享的生效时机,是当前会话一直有效,还是下次关机或挂起后就失效。我做长期开发环境时一律选"始终启用",避免某次重启后莫名其妙失效。
| 字段 / 选项 | 含义 | 常见误用 |
|---|---|---|
| 文件夹名称 | 客户机侧可见的目录名 | 与主机路径最后一级不一致,导致找不到 |
| 主机路径 | 主机上被暴露的真实目录 | 选了盘符根目录或系统目录 |
| 启用此共享 | 总开关 | 忘记勾选,却去排查驱动问题 |
| 只读 | 客户机侧禁止写入 | 需要写日志时误勾 |
| 始终启用 | 跨重启保持生效 | 选了临时启用,重启后失效 |
3.2 只读开关和实际文件权限的关系
只读这个勾选是在 HGFS 层拦截的,也就是客户机侧写操作直接返回权限错误,跟主机 NTFS 权限无关。它的好处是防止虚拟机里的进程误删主机文件,比如你在虚拟机里跑rm -rf的时候手抖打错路径。我在做不可逆操作前,习惯临时把共享改成只读,操作完再改回来,比事后恢复数据便宜得多。
需要注意的是,只读和 Linux 侧的uid/gid/fmask这些参数是叠加的。也就是说,即使你在客户机侧把挂载参数配成了全可写,主机侧勾了只读,一样写不进去。排查"为什么写不了"的时候,两边都要看,别只盯着客户机。
3.3 主机目录的选点原则
我自己的习惯是单独建一个目录,比如D:\vm-share,下面按项目再分子目录,然后把这一个大目录整体共享出去,客户机里一次挂载全都有。这样做的原因是共享项数量少、维护简单、日后迁移方便。
有些位置我坚决不选。盘符根目录,因为一旦挂出去,虚拟机里的任何误操作都可能波及整块盘;系统的用户目录,比如C:\Users\xxx,因为里面有一堆隐藏的系统文件,在客户机里看着乱,还可能触发权限问题;带有中文或空格的目录名,因为在 Linux 客户机里做挂载、写脚本、拼路径的时候,这几个字符经常给你带来额外的转义麻烦。名字用纯英文、数字、下划线、短横线,是最省事的做法。
还有一个必须提前想清楚的点:共享文件夹里的数据存在主机磁盘上,不在虚拟机的虚拟磁盘里,因此不受虚拟机快照影响。这意味着你给虚拟机打快照、回滚快照,共享目录里的文件不会跟着回滚。听起来是好事,但反过来讲,如果你在共享目录里改了配置文件,回滚虚拟机之后环境回到了旧状态、文件却是新的,两边对不上,会非常迷惑。我的做法是:共享目录只放"数据"和"产物",不放"环境配置",需要跟快照一起回滚的东西都放客户机本地磁盘。
4. Windows 客户机侧:从 \vmware-host 到"找不到网络路径"
Windows 客户机上的共享文件夹体验相对顺滑,但只要出问题,表现都差不多——找不到路径。
4.1 两种访问方式:直接敲路径和映射驱动器
最直接的访问方式是地址栏敲\\vmware-host\Shared Folders\,回车,下面就能看到主机侧启用的所有共享目录。这个写法的固定部分\\vmware-host\Shared Folders是恒定的,后面的目录名才跟着你的"文件夹名称"字段走。
如果经常用,映射个盘符会舒服很多:
net use Z: "\\vmware-host\Shared Folders\vm-share" /persistent:yes/persistent:yes的意思是记住这个映射,下次登录自动重建。这里有个细节:映射的持久化信息是记在用户配置文件里的,而 HGFS 网络提供程序是系统启动阶段由 VMware Tools 服务注册的。如果服务启动比用户登录慢,映射重建就会失败,表现为"每次开机都要重新映射一次"。遇到这种情况,要么加个登录脚本延迟几秒执行net use,要么干脆用批处理在启动项里重建。这点在实际使用中挺常见,尤其是机械硬盘加一堆开机启动项的老机器。
4.2 "找不到网络路径"到底有几种成因
这个报错在 Windows 客户机上有明确的几种成因,按可能性从高到低排一下。
第一种,主机侧那个共享项没勾"启用此共享",或者勾了但没生效。这种情况在客户机侧看起来就像路径不存在。
第二种,客户机里 VMware Tools 没装,或者VMTools服务没在跑。这时候vmware-host这个名字根本解析不了,报的就是找不到网络路径。
第三种,共享名称写错。主机侧文件夹名称是fw,你敲的是firmware,路径不存在。
第四种,把 HGFS 和普通 SMB 共享搞混了。有人看到"共享文件夹"四个字,下意识就在客户机里敲主机的 IP,比如\\192.168.1.10\...,那当然不行,因为 HGFS 根本不在网络上监听。这种情况下的报错往往不是"找不到网络路径",而是弹凭证框,或者提示"你不能访问此共享文件夹,因为你的组织的安全策略阻止未经身份验证的来宾访问"——那是 SMB 层面的策略,跟共享文件夹没有任何关系。
我特别想强调第四种,因为它太常见了。判断方法很简单:只要出现凭证输入框,说明你走的是 SMB,不是 HGFS。HGFS 不弹凭证框,因为它压根不需要认证,它的访问控制只由主机侧那个"只读"开关决定。有些朋友会问"怎么看共享文件夹的账号密码",这个问题本身就说明概念混了——HGFS 没有账号密码这回事。
4.3 重启之后共享文件夹消失的两种情况
第一种情况,共享项本身还在,只是映射的盘符没了。这属于前面说的映射重建时序问题,加延迟或者用脚本解决。
第二种情况,整个\\vmware-host都解析不了了。这时候先去服务里看VMTools服务的状态和启动类型。正常应该是自动启动。有些人为了开机快,用优化工具把一堆服务设成了手动,顺手把 VMware 相关的也关了,就会出现这个现象。我见过的几个案例都是这个原因,改回自动启动,重启一次就好。
5. Linux 客户机侧:/mnt/hgfs 是怎么挂上去的
Linux 这边的路径和 Windows 完全不同,也更容易出问题,值得单独用一节讲透。
5.1 先用 vmware-hgfsclient 做一次"是否存在"的验证
在动手挂载之前,先跑这一条:
vmware-hgfsclient它会把主机侧启用的所有共享名逐行打印出来。这一步的价值在于把问题范围一刀切开:如果这里能列出你期望的目录名,说明主机侧配置和 Tools 层都是通的,问题只可能出在挂载环节;如果什么都不输出,或者命令不存在,那就是 Tools 层没搞定,回头去装open-vm-tools。
命令不存在的话,确认一下open-vm-tools装了没有,RPM 系下这个可执行文件通常在/usr/bin/里。
5.2 手动挂载的完整命令与每个参数的作用
标准写法是先建挂载点,再挂:
sudo mkdir -p /mnt/hgfs sudo vmhgfs-fuse .host:/ /mnt/hgfs -o subtype=vmhgfs-fuse,allow_other这里几个东西值得逐个解释。.host:/是 HGFS 的伪路径,表示"主机上暴露的所有共享根",后面那个斜杠不能少。subtype=vmhgfs-fuse是给 FUSE 标明子类型,便于mount命令识别和展示。allow_other是最关键的参数,没有它的话,只有执行挂载的那个用户(通常是 root)能访问挂载点,普通用户进去会看到权限拒绝。这是 Linux 下"挂载成功了但看不到文件"最常见的根因,没有之一。
挂单个共享目录也是可以的:
sudo vmhgfs-fuse .host:/fw /mnt/hgfs/fw -o subtype=vmhgfs-fuse,allow_other验证挂载结果:
mount | grep hgfs正常应该能看到一行包含vmhgfs-fuse的输出。如果报的是unknown filesystem type 'vmhgfs-fuse',说明 FUSE 相关组件缺失,fuse或者fuse3包装一下;如果报unknown option,多半是用的参数在当前版本不支持,去掉可疑参数再试。
5.3 开机自动挂载的两条路线和各自的坑
手动挂载重启就没了,所以要做持久化。两条路线我都用过,各有取舍。
第一条是改/etc/fstab:
.host:/ /mnt/hgfs fuse.vmhgfs-fuse allow_other,defaults 0 0这条写法简单,但有个时序问题:vmhgfs-fuse依赖open-vm-tools服务提供的宿主通道,如果 fstab 挂载发生在服务就绪之前,就会失败。表现是开机后/mnt/hgfs是空的,手动mount -a一下又好了。解决思路是加x-systemd.automount做按需挂载,或者干脆用第二条路线。
第二条是写一个 systemd 挂载单元,比如/etc/systemd/system/mnt-hgfs.mount:
[Unit] Description=Mount VMware Shared Folders After=open-vm-tools.service Requires=open-vm-tools.service [Mount] What=.host:/ Where=/mnt/hgfs Type=fuse.vmhgfs-fuse Options=allow_other,defaults [Install] WantedBy=multi-user.target然后sudo systemctl daemon-reload && sudo systemctl enable --now mnt-hgfs.mount。这种方式的好处是能用After和Requires明确声明依赖顺序,不会出现抢跑。代价是单元文件名必须和挂载点路径严格对应,/mnt/hgfs对应mnt-hgfs.mount,中间的分隔符不能写错,写错了 systemd 会报找不到对应的单元。
注意:不少老教程里会提到
/run/vmblock-fuse这个目录,说要在 fstab 里挂它。那是拖拽拦截功能的挂载点,跟共享文件夹是两码事,照着抄通常没有效果,还容易把自己绕进去。
5.4 Kali、Rocky、银河麒麟上的实测差异
Kali 这边基本没脾气,apt install open-vm-tools之后vmhgfs-fuse就在/usr/bin下,直接挂就行。Kali 默认桌面是 XFCE,如果需要拖拽和剪贴板,额外装open-vm-tools-desktop。
Rocky Linux 需要注意 SELinux。默认策略下挂载点会被标成fusefs_t,普通用户读写一般没问题,但如果你在虚拟机里跑 Apache 或者 Nginx,让 Web 服务去读共享目录里的文件,大概率会被 SELinux 拦下来,日志里能看到 AVC 拒绝记录。处理方式:
sudo setsebool -P httpd_use_fusefs on改完不需要重启服务,重新访问一次就行。这个点很多教程不写,但真做 Web 开发环境的时候一定会撞上。
银河麒麟 V10 SP1 这类基于 RPM 的国产系统,官方源里通常能找到open-vm-tools,优先用包管理器装。如果源里版本太旧或者没有,再退回到编译方式,编译前先把gcc、make、perl、kernel-devel装齐,版本要和uname -r完全对上。我遇到过一次源里的kernel-devel比运行内核低一个版本,编译出来的模块加载不了,最后是手动对齐版本才解决。
6. CIFS 自动挂载重启后失效:另一条路,另一套坑
共享文件夹和 CIFS 挂载经常被放在一起讨论,因为两者都是"让两个系统共享文件"。但它们的故障模式完全不同。既然热词里反复出现"cifs 挂载共享文件夹重启后失效怎么办",我就把这条线单独讲清楚。
6.1 重启失效的三个根因
第一个根因是网络未就绪。systemd 并行启动,fstab的处理时机可能早于网卡拿到 IP。这时候 CIFS 挂载必然失败,而且失败后不会自动重试。表现就是开机后挂载点是空的,手动mount -a才行。解决办法是加_netdev选项,告诉 systemd 这个挂载需要网络,同时用x-systemd.automount做按需触发。
第二个根因是凭证文件权限。mount.cifs对credentials=指向的文件有安全要求,权限过宽会被拒绝执行。正确做法是:
sudo chmod 600 /etc/cifs.cred sudo chown root:root /etc/cifs.cred文件内容就三行:
username=youruser password=yourpass domain=WORKGROUP第三个根因是主机 IP 变化。家里路由器重启、DHCP 租约到期,主机 IP 变了,原先写在 fstab 里的 IP 就指不到地方了。开发环境里我建议主机侧配静态 IP,或者用主机名加 hosts 记录,别依赖 DHCP。
6.2 一份能扛住重启的 fstab 写法
//192.168.1.10/share /mnt/smb cifs credentials=/etc/cifs.cred,uid=1000,gid=1000,iocharset=utf8,file_mode=0644,dir_mode=0755,_netdev,nofail,x-systemd.automount,x-systemd.idle-timeout=120 0 0逐个说。uid和gid决定挂载后文件在客户机侧归属于哪个用户,不写的话默认归 root,普通用户读写会受限。iocharset=utf8保证中文文件名正常。file_mode和dir_mode决定客户机侧看到的权限位。_netdev声明网络依赖。nofail保证即使挂载失败也不阻塞开机。x-systemd.automount加x-systemd.idle-timeout是按需挂载,访问的时候才真正挂,闲置一段时间自动卸载,很适合笔记本这种经常断网的场景——网络断了也不会让整个开机流程卡住。
6.3 什么时候该用哪个
我的判断标准很简单。如果数据只在我这台机器的主机和虚拟机之间流动,用共享文件夹,省掉账号、权限、网络这一整套;如果数据要给第二台物理机、给同事、或者要给容器里的服务访问,用 CIFS。两者可以并存,一个挂/mnt/hgfs,一个挂/mnt/smb,互不干扰。
需要提醒的是,共享文件夹和 CIFS 在性能特征上不一样。CIFS 的瓶颈通常在网络往返和协议开销,共享文件夹的瓶颈更靠近主机磁盘和 HGFS 本身的实现。如果你要做大量小文件读写,两个都不算快,实测下来把依赖目录放客户机本地磁盘是最优解。
7. 权限、软链接、小文件性能:文档里基本不写的三个坑
前面讲的都是"能不能用",这一节讲"用得好不好"。
7.1 uid、gid 和掩码参数怎么配
Linux 下挂载共享文件夹之后,默认所有文件归属挂载者(root),普通用户能读不能写。这在开发场景里很难受。解决办法是在挂载参数里加:
sudo vmhgfs-fuse .host:/ /mnt/hgfs -o subtype=vmhgfs-fuse,allow_other,uid=1000,gid=1000,umask=022uid和gid用id 你的用户名查出来。umask=022表示新文件的默认权限是 644、目录是 755。也可以用fmask和dmask分别控制文件和目录,粒度更细。
注意:不同版本的
vmhgfs-fuse支持的参数不完全一样,有些老版本不认fmask/dmask,加了会报unknown option直接挂载失败。遇到这种情况先去掉这两个参数,用umask代替。
写到 fstab 里的版本就是把这串参数拼进 Options 字段。改完记得先跑sudo mount -a测试,别直接重启;mount -a能报错并提示具体哪一行有问题,比重启后对着空气发呆强得多。
7.2 软链接在共享目录里会出问题
这一点是我踩得最疼的坑。HGFS 对符号链接的支持有限,在共享目录里创建的软链接,跨主机-客户机边界之后经常会失效或者被当成普通文件。
这个特性会在哪些场景下咬你?最典型的是前端项目的node_modules。npm 和 pnpm 的依赖目录里存在大量软链接和.bin目录下的相对链接,放在共享文件夹里跑安装,十有八九报错或者装完之后二进制执行不了。Python 的 virtualenv 同理,venv/bin/python是软链接,跨边界后解析异常。
我的处理方式是把项目分两层:源码目录放共享文件夹,主机和虚拟机都能直接编辑;依赖目录(node_modules、venv、target)放在客户机本地磁盘,通过软链接指向项目内的路径——但注意,这个软链接要在客户机本地创建,不能在共享目录里创建。实际操作上,我通常是在客户机本地的/opt/deps/项目名/node_modules下装依赖,然后在项目里建一个指向它的链接。这样依赖走本地高速路径,源码走共享路径,两边的好处都拿到。
7.3 大量小文件的性能表现
共享文件夹在传大文件时体验还不错,几个 GB 的镜像拖过去速度可以接受;但成千上万个小文件的时候,性能下降很明显。原因是 HGFS 的每一次元数据操作都要经过宿主-客户机通道,往返开销叠加之后,目录遍历、状态查询、文件创建这些操作会变得很慢。
实测体感上,几万个小文件的目录做一次全量扫描,比在客户机本地磁盘上慢好几倍。所以如果你的构建过程需要频繁读写大量小文件,比如 Webpack 打包、Java 编译中间产物,把工作目录放客户机本地,构建完只把最终产物写到共享目录,是最合理的分工。我做过一次对比:同一份中型前端项目,源码和node_modules全在共享目录,构建耗时大概是全本地环境的几倍;调整成源码共享、依赖本地之后,差距缩到几乎感觉不出来。
8. 一份可以照着走的排查清单
前面讲了原理,这一节给你一份可执行的排查顺序。遇到"共享文件夹不工作",按这个顺序走,基本五分钟内能定位到是哪一层的问题。
| 症状 | 优先检查 | 具体操作 |
|---|---|---|
| 主机侧设置里没有共享项 | 虚拟机是否处于运行状态 | 部分选项需要虚拟机开机才能编辑 |
Linux 下vmware-hgfsclient无输出 | Tools 是否安装并运行 | systemctl status open-vm-tools |
| Linux 下命令不存在 | 包是否安装 | 重新安装 open-vm-tools |
| 挂载成功但普通用户读不了 | 是否加了allow_other | 重新挂载并加上该参数 |
| 挂载点为空,重启后消失 | 是否做了持久化 | 检查 fstab 或 systemd 单元 |
| Windows 下弹凭证框 | 是否误用了 SMB 路径 | 改用\\vmware-host\Shared Folders |
| Windows 下找不到网络路径 | VMTools 服务状态 | 设为自动启动并重启 |
| 能读不能写 | 主机侧只读开关 | 取消勾选"只读" |
| 能读能写但权限属主是 root | 挂载参数 | 补uid和gid |
| 构建时报软链接相关错误 | 依赖目录位置 | 把依赖移到客户机本地磁盘 |
清单里最后几条是我在实际项目里反复遇到的。尤其是最后一条,它不报错在挂载环节,而是报在构建工具里,错误信息五花八门,很容易让人以为是构建工具本身的问题,绕很远的路才找到根因。
还有一个维护上的小建议:如果你之后需要重装或者彻底卸载 Workstation,主机侧会残留一些虚拟网卡和驱动,官方的清理工具能处理得比较干净,普通卸载容易留尾巴,导致重装之后网络或驱动状态异常。虚拟机里的/mnt/hgfs挂载点在卸载 Tools 之后会变成一个空目录,不会自动清理,手动umount一下更整洁。
最后分享一个我自己固化下来的习惯:给每台开发虚拟机制作一份"环境说明"文本,记录共享文件夹的名称、主机路径、Linux 侧的挂载方式和参数。听起来有点多余,但当你手上有七八台虚拟机、隔几个月才回头用某一台的时候,这份说明能省下大量回忆时间。我吃过这个亏,某台 Rocky 虚拟机上的共享挂载参数是特殊配过的,隔了半年回去用,按默认参数怎么都写不进文件,翻记录才发现当时加了uid和umask。这种细节,不记下来就一定会忘。