做虚拟化开发的朋友应该都遇到过这个需求:Windows主机上装了个VMware Workstation,里面跑着Ubuntu或者CentOS7,写着写着就发现文件在两套系统之间来回倒腾特别痛苦。我最早用U盘拷贝,后来用拖拽,再后来开winscp传,折腾一圈下来,最省心的还是直接把虚拟机的共享文件夹打通。这篇文章就围绕VMware虚拟机共享文件夹这个事,把Ubuntu和CentOS7两种系统下的配置方法、挂载原理、自动挂载和排坑思路完整梳理一遍,适合刚入坑虚拟化开发、或者被共享文件夹折磨过但没时间系统排查的朋友参考。
1. 共享文件夹方案选型与适用场景
1.1 为什么需要共享文件夹,它解决什么问题
共享文件夹解决的是“文件在宿主机和虚拟机之间双向流动”的问题。做嵌入式开发、写Python脚本、调前端页面、跑数据分析,这些场景里代码通常保存在Windows宿主机上,但编译、执行、测试环境在Linux虚拟机里。如果没有共享文件夹,每次改完代码都要手动同步,轻则多敲几条scp命令,重则忘记同步导致排查半天才发现跑的是旧代码。
共享文件夹打通之后,宿主机里的项目目录直接出现在虚拟机的/mnt/hgfs下,两边看到的是同一份文件,改完即所见即所得。这个体验本质上和Windows的“映射网络驱动器”差不多,但底层走的是VMware虚拟机监视器提供的hgfs协议,不需要走网络栈,也不依赖SMB服务,配置成本低、部署干净。
除代码开发外,共享文件夹还很适合这几类场景:传递安装包和离线依赖(比如把下载好的.deb、.rpm直接丢进共享目录,虚拟机里dpkg -i或rpm -ivh就能装);共享日志和测试报告(虚拟机内产生的日志直接落盘到共享目录,Windows这边用编辑器打开就能看);迁移配置文件(比如把.ssh、.vimrc、.bashrc备份到共享目录,重装系统后一键恢复)。
有一点要提前说清楚:共享文件夹适合文件传输和轻量协作,不适合放数据库文件、版本仓库的.git目录或者需要大量随机读写的文件。原因是hgfs走的是FUSE用户态文件系统,性能比原生ext4/xfs差不少,而且对文件锁的支持不稳定,sqlite、postgresql这类应用容易出现锁异常或数据损坏。我自己踩过这个坑:把一个小型sqlite数据库放在共享文件夹里跑了三天,结果读出database is locked的错误,最后把数据库挪回虚拟机本地磁盘才恢复正常。
1.2 两条技术路线:VMware官方共享 vs Samba/CIFS
实现Windows和Linux共享文件,主流方案有两类:VMware官方的“共享文件夹”功能,以及在Linux里挂载Windows的SMB共享(Samba/CIFS)。两者看起来都是共享,但底层逻辑完全不同。
VMware共享文件夹的核心是hgfs(Host-Guest File System)。宿主机上的VMware Workstation把指定目录“借”给虚拟机,虚拟机通过vmhgfs驱动或open-vm-tools提供的FUSE组件访问这个目录。优势是配置简单、与VMware集成度高、不需要Windows开启任何额外服务;劣势是只能在宿主机和这台虚拟机之间用,换一台物理机或者别的虚拟机,就得重新配置。
Samba/CIFS走的是标准网络文件共享协议。宿主机Windows开启文件夹共享后,Linux虚拟机通过mount -t cifs挂载//宿主机IP/共享名到本地目录。优势是标准统一、可跨多台机器、可以不依赖VMware;劣势是配置步骤多,Windows这边要设置共享权限和防火墙,Linux这边要装cifs-utils,而且传输走虚拟网卡,性能受网络影响。
| 对比项 | VMware共享文件夹 | Samba/CIFS |
|---|---|---|
| 配置复杂度 | 低,GUI操作几个勾选 | 中,需配置共享权限+防火墙+cifs挂载 |
| 依赖组件 | VMware Tools / open-vm-tools | cifs-utils,Windows功能中开启SMB |
| 传输性能 | 中,适合文件级读写 | 中高,但受虚拟网卡和SMB协议开销影响 |
| 适用范围 | 仅当前宿主机+此虚拟机 | 支持多台机器同时访问同一共享 |
| 故障排查难度 | 较难直观,报错信息有限 | 错误信息规范,可用smbclient等工具排查 |
我的建议是:日常开发优先用VMware共享文件夹,省心;如果有多台Linux机器需要同时访问同一个Windows目录,或者想跑一些网络协议兼容性测试,再考虑Samba/CIFS。这篇文章后续主要讲VMware共享文件夹,但在排错部分也会补充CIFS挂载的常用方法,因为有些问题用VMware共享死活搞不定时,CIFS反而是一条稳定的退路。
2. 环境准备与前置检查
2.1 虚拟机配置与VMware Tools安装状态自检
在动手配置共享文件夹之前,先花两分钟确认环境状态。很多“共享文件夹无法使用”的问题,根子其实在VMware Tools没装好或者内核模块没加载。
第一步,确认虚拟机里Tools组件的版本和状态。在Ubuntu或CentOS7的终端里执行:
vmware-toolbox-cmd -v如果能输出版本号,比如11.3.5.18557794,说明VMware Tools命令行工具可用。如果提示命令不存在,说明Tools没装,后面会细说安装方法。
第二步,确认内核模块是否加载。hgfs在较老版本里是一个独立内核模块,在新版本里变成了FUSE用户态进程,但检查一下没有坏处:
lsmod | grep -E "vmhgfs|vmw_vmci|vmxnet"我遇到过内核升级之后模块没跟着编译的情况,vmhgfs那一行直接消失,共享文件夹自然就看不到。遇到这种情况,重装一次open-vm-tools或者重新编译内核模块就能解决。
第三步,检查共享目录是否已经存在。如果一切正常,执行:
ls /mnt/hgfs能列出目录就说明共享已经生效,剩下的只是权限和自动挂载的优化问题。如果提示No such file or directory,别急着建目录,说明挂载这步还没发生,后面会展开排错。
确认环境时还有个小习惯值得培养:装系统后第一时间装Tools,而不是等到需要共享文件时再补。因为内核模块编译和加载需要重启或者重新加载服务,越早处理,后续越省事。
2.2 Ubuntu与CentOS7安装Tools的正确姿势
VMware Tools的安装有两个来源:VMware自带的“安装VMware Tools”菜单(会挂载一个虚拟光驱,里面有tar包),以及Linux发行版软件源里的open-vm-tools。这两者优先用后者。
为什么推荐open-vm-tools?因为它是开源版本,由VMware官方维护但已经打进各发行版仓库里,和系统自带的kernel版本匹配度好,内核升级后会自动更新模块,不用每次手动重新编译。VMware自带那个tar包虽然能用,但内核小版本一升级就可能出现模块加载失败,而很多教程还在推荐它,属于历史遗留习惯。
Ubuntu下的安装命令:
sudo apt update sudo apt install -y open-vm-tools open-vm-tools-desktop注意,如果虚拟机有图形界面,尽量带上open-vm-tools-desktop,它额外提供分辨率自适应、剪贴板共享、拖拽文件这些增强功能。纯命令行服务器版可以只装open-vm-tools。
CentOS7下安装:
sudo yum install -y open-vm-toolsCentOS7的源里默认就有这个包,不需要额外配置epel。装完以后,执行:
sudo systemctl enable --now vmtoolsd sudo systemctl status vmtoolsd确认服务是active状态。
安装完成后,建议做一次完整的挂载测试。先在VMware里配置好共享文件夹(这一步见3.1节),然后回到虚拟机里执行:
mkdir -p /mnt/hgfs sudo vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other -o uid=$(id -u),gid=$(id -g) ls /mnt/hgfs正常情况下ls能看到VMware里配置的共享目录名。如果这一步成功,说明Tools和内核通道都是通的,后续就是如何自动化的问题。如果失败,请直接跳到第4章查错误。
3. 核心实操:开启共享文件夹并正确挂载
3.1 在VMware Workstation中配置共享文件夹
虚拟机里的Tools装好、服务跑起来之后,接下来在VMware Workstation的图形界面里配置共享文件夹。操作路径是:选中虚拟机,点击“编辑虚拟机设置”,切到“选项”标签页,找到“共享文件夹”。
这里有几个关键点:
- 选择“总是启用”,而不是“下次关机或挂起前启用”。前者是永久的,后者只在本次会话有效,重启虚拟机后配置消失。
- 点击“添加”按钮,指定Windows宿主机里的一个目录作为共享根目录。建议单独建一个干净的目录,比如
D:\vm-share,而不是直接把整个D盘共享出去。共享整个盘虽然能跑,但Windows侧文件变更监控非常频繁,虚拟机访问时会感觉明显卡顿。 - 为共享目录起一个名称。这个名称会直接显示在虚拟机的
/mnt/hgfs下面,建议用纯英文小写加下划线,比如code、packages、logs。我以前用过带中文和空格的名称,虽然现代版本支持,但某些老版本会莫名挂不上,纯英文最稳。 - 勾选“启用此共享”,然后确定保存。
如果你有多个目录要共享,可以重复“添加”步骤,最多能加几十个左右,但实际操作中共享2到3个目录就够了,共享越多,VMware的hgfs服务占用越高,特别是在Windows侧触发大量文件事件的时候。
配置完成后,不需要重启虚拟机,正常情况下几十秒内/mnt/hgfs下就会出现对应目录。如果没出现,到虚拟机里执行systemctl restart vmtoolsd(Ubuntu和CentOS7通用)或者重新登录一次,一般能解决。
3.2 Ubuntu与CentOS7挂载与自动挂载配置
VMware Tools装好之后,现代版本默认会根据配置自动挂载共享文件夹到/mnt/hgfs,不需要手动干预。但实际情况里经常遇到两种情况:自动挂载没生效,或者挂载了但权限不对。下面把手动挂载和自动挂载都讲透。
手动挂载的传统方式是:
sudo mkdir -p /mnt/hgfs sudo mount -t vmhgfs .host:/ /mnt/hgfs这种写法在老版本内核和部分CentOS7场景下依然可用,本质是走内核模块vmhgfs。但新版本open-vm-tools默认用FUSE实现,所以更通用的是:
sudo vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other -o uid=$(id -u),gid=$(id -g)解释一下参数:.host:/表示挂载宿主机侧所有共享目录的根节点;allow_other允许非root用户访问FUSE挂载点;uid和gid设置挂载点的属主和属组,如果不设置,默认归属root,普通用户进去会提示权限不足。
如果你只想挂载其中一个共享目录,比如VMware里起的名字是code,可以这样:
sudo vmhgfs-fuse .host:/code /mnt/hgfs/code -o allow_other这样可以控制只访问特定目录,避免挂在根节点后把宿主机所有共享都暴露出去。
手动挂载只能解决当前会话的问题,虚拟机重启后挂载会消失。要开机自动挂载,需要把挂载配置写入/etc/fstab。
主流配置写法有两种。如果你用的还是传统内核模块方式,在/etc/fstab末尾加:
.host:/ /mnt/hgfs vmhgfs defaults,allow_other 0 0如果你用的是新版FUSE方式,写成:
.host:/ /mnt/hgfs fuse.vmhgfs-fuse defaults,allow_other,uid=1000,gid=1000 0 0uid=1000,gid=1000要按你虚拟机里实际用户的uid来填,不确定就执行id命令查看。这一步很关键,我见过很多人用默认配置导致开机挂载成功但普通用户无权访问。
改完fstab后,先别急着重启,执行:
sudo mount -a如果没有任何报错,说明配置正确,之后重启就能自动挂载。如果报错,多半是fstab的挂载类型写错了,对照上面的写法逐字检查。
CentOS7和Ubuntu的配置完全相同,唯一区别是CentOS7的SELinux默认开启,如果遇到挂载了但访问被拒绝的情况,先确认SELinux状态:
getenforce如果是Enforcing,可以临时放行测试:sudo setenforce 0。确认是SELinux拦截后,再决定是长期关闭还是调整策略。不过在实际使用中,hgfs默认策略通常不会拦截本地访问,所以这个问题的出现概率并不高。
4. 常见问题与排查技巧实录
4.1 找不到共享目录、/mnt/hgfs不存在的排查步骤
这应该是共享文件夹问题里出现频率最高的一类。现象是VMware里已经配置好了共享目录,虚拟机里ls /mnt/hgfs却提示不存在,或者/mnt/hgfs是空的。排查思路可以按下面的顺序来。
先检查Tools状态,这是第一道关卡:
vmware-toolbox-cmd -v systemctl status vmtoolsd如果命令不存在或者服务是死的,直接跳到修复Tools。Ubuntu执行sudo apt install -y open-vm-tools open-vm-tools-desktop,CentOS7执行sudo yum install -y open-vm-tools,装完systemctl restart vmtoolsd。
Tools正常之后,再看内核模块。执行:
lsmod | grep vmhgfs如果现代FUSE版本没有这个内核模块是正常的,因为负载在用户态。但如果你看到模块状态是异常或者没有输出,可以尝试重新加载:
sudo modprobe vmhgfs如果模块加载失败,多半是内核头文件没装全,Ubuntu执行sudo apt install -y linux-headers-$(uname -r),CentOS7执行sudo yum install -y kernel-devel kernel-headers,然后重新安装一遍Tools。
接下来检查挂载状态:
mount | grep hgfs df -h | grep hgfs如果挂载点在但目录空,先确认VMware里的共享名称是不是写对了。在虚拟机里执行:
ls /mnt/hgfs空目录且有mount输出,说明共享名称和预期不一致,回到Windows侧VMware设置里检查共享名,或者直接查看宿主机侧配置。
最后一步是权限问题。挂载点是root所有时,普通用户ls可能看不到。执行:
sudo ls /mnt/hgfs如果能看到而普通用户不行,就是权限问题,重新用带uid,gid参数的方式挂载一次即可。
我遇到的另一个冷门场景是Windows安全软件拦截VMware的hgfs驱动,导致共享文件夹间歇性消失。排查方法很直接:临时退出安全软件,看共享文件夹是否稳定,稳定的话就把VMware相关进程加入白名单。
4.2 共享目录能访问但权限不对、文件不同步
共享文件夹挂载成功,但普通用户无法读写,这是新手最常见的问题。原因95%以上是挂载参数没有指定uid和gid,导致挂载点归属root。
遇到这种情况,不用重启,重新挂载一次就行:
sudo umount /mnt/hgfs sudo vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other -o uid=$(id -u),gid=$(id -g)这样当前用户就能正常读写。如果想让其他用户也能访问,把allow_other加上即可。
比权限更让人头疼的是“文件不同步”问题。表现是:Windows侧新建一个文件,虚拟机里ls半天看不到;或者虚拟机里改了文件,Windows侧没有变化。大部分情况下,hgfs是支持实时双向同步的,但有些场景会出现延迟,因为VMware出于性能考虑会做一定的缓存和延迟刷新。
简单粗暴的解决办法是手动刷新,在虚拟机里执行:
sync && ls -la /mnt/hgfs/大部分情况下能强制刷新出来。如果频繁遇到同步延迟,检查Windows侧是不是有第三方工具(比如Everything、Listary)频繁索引磁盘,量大时会影响hgfs的通知机制。
另一类是文件内容出现乱码或者换行符混乱。Windows记事本写得文本,Linux里用vim打开可能看到^M,这是Windows的CRLF换行符在作怪。反过来,Linux里生成的脚本拿到Windows侧用记事本打开,可能出现一行挤在一起。这个不是共享文件夹的问题,是文件编码和换行符的差异。解决办法是代码文件统一用LF换行,并在编辑器里设置autocrlf策略,比如Git全局配置:
git config --global core.autocrlf input设置完之后,Git会在提交时自动处理换行符,避免两边来回踩坑。
还有一点建议:不要把编译产物和目标文件(比如build/、node_modules/、__pycache__/)直接放在共享文件夹里。hgfs的性能和元数据操作能力不如本地磁盘,大量小文件编译时,耗时会翻倍增长。正确姿势是:源码放共享目录,编译输出到虚拟机本地目录,用符号链接或者构建脚本把产物映射回去。这样一来两边都能拿到最终结果,但构建速度不打折。
4.3 重启后失效与CIFS替代方案
fstab配置好之后重启就失效,这是个比较隐蔽的坑。
先说现象:fstab里挂载配置写得正确,sudo mount -a也能挂载成功,但只要重启,共享目录就是不出来,要手动执行一次挂载命令才行。
原因通常是systemd在执行fstab挂载时,网络或者FUSE服务还没就绪,挂载被延迟或跳过了。hgfs虽然不依赖网络,但open-vm-tools的vmtoolsd服务要跑起来之后,FUSE挂载才可能成功。如果systemd在vmtoolsd尚未启动时抢先挂载了fstab,就会失败。
解决办法是给fstab挂载项增加_netdev和x-systemd.automount选项:
.host:/ /mnt/hgfs fuse.vmhgfs-fuse allow_other,uid=1000,gid=1000,_netdev,defaults 0 0或者使用x-systemd.before=vmtoolsd.service来控制挂载时机,但配置起来更复杂,不如直接用一个systemd挂载单元来得干净。
我更推荐的方式是写一个简单的systemd服务,在vmtoolsd启动后再挂载。新建/etc/systemd/system/mnt-hgfs.mount(名字要和路径对应)或直接写一个oneshot服务:
sudo vim /etc/systemd/system/vmhgfs-mount.service内容如下:
[Unit] Description=Mount VMware shared folders After=vmtoolsd.service Requires=vmtoolsd.service [Service] Type=oneshot ExecStart=/usr/bin/vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other,uid=1000,gid=1000 RemainAfterExit=yes [Install] WantedBy=multi-user.target然后执行:
sudo systemctl daemon-reload sudo systemctl enable --now vmhgfs-mount.service这样VMware共享文件夹的挂载就变成系统服务管理,启动顺序可控,状态可查,比fstab的黑盒行为要可靠得多。Ubuntu和CentOS7都适用。
如果VMware共享文件夹排查到最后还是时好时坏,我会换一条路:直接用CIFS挂载Windows共享目录。这个方法不依赖VMware的hgfs,反而更稳定。
Windows侧先把目标目录设为共享,记下主机IP和共享名。Linux侧执行:
sudo yum install -y cifs-utils # CentOS7 sudo apt install -y cifs-utils # Ubuntu sudo mkdir -p /mnt/win-share sudo mount -t cifs //192.168.x.x/share /mnt/win-share -o username=yourname,password=yourpass,uid=$(id -u),gid=$(id -g),iocharset=utf8挂载路径里的IP是Windows宿主机的局域网IP,可以在Windows里执行ipconfig查看。如果你不想把密码明文写在命令里,可以单独建一个凭证文件:
sudo vim /etc/cifs-creds内容格式:
username=yourname password=yourpass domain=WORKGROUP然后挂载时引用:
sudo mount -t cifs //192.168.x.x/share /mnt/win-share -o credentials=/etc/cifs-creds,uid=$(id -u),gid=$(id -g),iocharset=utf8CIFS挂载重启后同样会失效,处理方法和上面一样,写进fstab或者systemd服务都可以。fstab写法:
//192.168.x.x/share /mnt/win-share cifs credentials=/etc/cifs-creds,uid=1000,gid=1000,iocharset=utf8,_netdev 0 0_netdev表示网络设备,等网络就绪后再挂载,这是CIFS/SMB挂载的标配参数。
选择CIFS方案时要考虑两个问题:一个是Windows侧的防火墙,如果挂载时报Connection refused,先检查防火墙是否放行了文件和打印机共享规则;另一个是SMB版本兼容,老旧的Windows系统可能默认SMB1,Linux新内核默认不再支持SMB1协议,遇到版本协商失败时,可以在挂载参数里明确指定vers=2.0或者vers=3.0。整体来说,CIFS是一条不依赖VMware的通用路径,适合作为第二方案备用。
我在实际使用中的体会是,VMware共享文件夹和CIFS共享并不是互斥关系,完全可以同时使用。日常改代码走VMware共享,速度快、路径短;需要跨机器分发文件或者推给其他服务器时,用CIFS。两条路都打通之后,虚拟机和宿主机之间的文件协作基本不会再有痛点。
最后再分享一个小技巧:共享文件夹的路径尽量保持固定,不要在Windows侧移动目录位置。我在一次换硬盘迁移时把共享目录从D:\vm-share挪到了E:\share,VMware里修改了配置,但/mnt/hgfs下面还残留着旧目录名的挂载缓存,导致每次开机都要手动清理一次。后来干脆把共享名称改成目录名完全一致,然后在虚拟机里删掉旧挂载点重建一遍,问题才彻底消失。共享配置改动的次数多了,就会发现“名字简单、路径固定、英文命名”这九个字能省下后面大量的排障时间。