玩VirtualBox装Ubuntu,前几周最难受的不是命令不熟,而是文件传递。剪贴板经常失效,U盘拷来拷去又怕中病毒,NAT网络模式下想从宿主机直接拖文件进虚拟机,基本靠缘分。其实VirtualBox自带一个非常实用的功能——共享文件夹,把宿主机的一个目录直接映射到虚拟机里,Ubuntu里挂载一下就能双向读写。但这玩意儿坑也不少:设置了半天Ubuntu里看不见、挂载报错、权限拒绝都是高频问题。这篇文章我把整个流程从零走一遍,包括VirtualBox里的设置、Ubuntu的挂载和开机自动挂载、常见问题的排查方法,全程用我实测过的命令和参数,照着抄基本能一次跑通。标题里写的“unbuntu”我按Ubuntu处理,VirtualBox 7.x + Ubuntu 22.04 LTS实测,老版本流程几乎一样,命令也通用。
1. 前期准备与环境确认
共享文件夹这个功能,很多人以为只要在VirtualBox界面里“添加共享文件夹”再勾个“自动挂载”就结束了,结果重启虚拟机一看,/media下面空荡荡。原因很简单:共享文件夹依赖VirtualBox的增强功能(Guest Additions),增强功能没装好,后面所有操作都是白搭。所以我建议动手前先把环境状态摸清楚。
1.1 先确认版本,再决定怎么设置
不同的VirtualBox版本、不同的Ubuntu版本,共享文件夹的挂载方式略有不同,但底层逻辑是一致的。我先给你一套查看版本信息的命令,建议在终端里挨个跑一遍:
bash复制# 查看Ubuntu系统版本
lsb_release -a
# 查看当前内核版本
uname -r
# 查看增强功能相关内核模块是否加载
lsmod | grep vbox
为什么要看内核版本?因为增强功能里的vboxsf、vboxguest、vboxdrv这些模块,需要匹配当前运行内核才能编译成功。如果你之前装过增强功能,但后来用apt upgrade升级过内核,那旧模块大概率已经失效了,lsmod | grep vbox输出里可能什么都看不到,或者版本对不上。这种场景特别多,我后面会详细讲。
VirtualBox本身的版本在宿主机上查看,Windows下是“帮助 → 关于VirtualBox”,Linux宿主机可以跑vboxmanage --version。记住这个版本号,它要和增强功能的版本一致。VirtualBox从7.x开始,增强功能和主程序打包在一起,装完主程序,Guest Additions镜像就在安装目录里,不需要另外下载。老版本6.x也是这样。
1.2 把增强功能装好,这是共享文件夹的地基
确认完版本,接下来就是把增强功能装干净。VirtualBox的“设备”菜单里有“安装增强功能”选项,点击后Ubuntu桌面会自动挂载一个光盘镜像(VBoxGuestAdditions.iso)。如果没自动弹出,可以手动挂载:
bash复制# 创建一个挂载点,把光盘挂上去
sudo mkdir -p /mnt/cdrom
sudo mount /dev/cdrom /mnt/cdrom
# 进入光盘目录运行安装脚本
cd /mnt/cdrom
sudo ./VBoxLinuxAdditions.run
安装过程中最容易出的问题,就是提示缺编译环境。增强功能需要把内核模块编译进当前运行的内核,所以必须有gcc、make、perl以及和当前内核完全匹配的linux-headers。提前装好这些依赖,能省很多事:
bash复制sudo apt update
sudo apt install -y build-essential dkms linux-headers-$(uname -r)
注意linux-headers-$(uname -r)这里的命令替换,它会把当前内核版本自动带入。如果后面你升级了内核,重启之后内核版本变了,就需要重新执行一遍这个安装命令。这是共享文件夹后续突然失效的头号原因。
装完之后重启虚拟机,再跑一遍lsmod | grep vbox,如果能看到vboxsf、vboxguest、vboxdrv,说明增强功能装好了。这里说句扎心的话:VirtualBox升级主版本后,增强功能必须重新安装。别问我是怎么知道的,有次从VirtualBox 6.1升到7.0,虚拟机里所有共享文件夹全部失效,排查了大半天。
注意:安装增强功能时,如果提示“Building the main Guest Additions module ... FAILED”,先别急着找错,大概率是linux-headers没装。装上之后重新运行
VBoxLinuxAdditions.run,它会自己清理并重编译。查看安装日志用/var/log/vboxadd-setup.log,里面会写明具体缺什么。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 两类共享文件夹设置方式,总有一种适合你
增强功能装好之后,才能真正开始在VirtualBox里配置共享文件夹。这一步有两种方式:图形界面点选和命令行设置。如果你只配置一台虚拟机,GUI够用了;如果涉及批量配置或者脚本自动化,命令行方式能节省大量时间。
2.1 图形界面设置:推荐新手使用
在VirtualBox窗口里,选中要设置的虚拟机(注意是关机状态还是运行状态都行,运行中设置也能生效,但需要重新挂载),点击菜单栏“设备 → 共享文件夹 → 共享文件夹设置”,然后点右上角的“添加共享文件夹”图标。
弹出的窗口里需要填几个关键信息:
- 文件夹路径:宿主机上要被共享的目录,点“其他”选择即可。
- 文件夹名称:这个就是虚拟机里看到的共享名,我强烈建议全小写、不含空格,比如
share、workspace、projects。如果你填“My Share”这种带空格的,后面mount命令就得加引号,麻烦不说,还容易踩各种奇奇怪怪的坑。 - 自动挂载:勾上之后,Ubuntu开机时会自动挂载到
/media/sf_共享名,省得手动执行mount。 - 固定分配:这个选项的意思是共享配置永久保存在虚拟机配置里。如果你不勾,它就是个临时共享,虚拟机重启后配置就没了。建议勾上,除非你只想临时传一次文件。
设置完点确定,虚拟机如果正在运行,通常需要注销重新登录或重启虚拟机才能看到新的共享目录。这里插一句:很多人在这里设置完,跑到/media下面翻,发现根本没有sf_share目录,就开始怀疑设置错了。其实不是没设对,是当前登录用户没有权限,或者挂载还没触发。后面会专门讲权限问题。
2.2 命令行方式:批量配置和脚本自动化更友好
如果你跟虚拟机打交道比较多,建议把命令行方式也掌握。VBoxManage是VirtualBox自带的命令行工具,在宿主机上执行,不是虚拟机里。比如我要给名为UbuntuVM的虚拟机添加一个共享文件夹:
bash复制# 在宿主机上执行
VBoxManage sharedfolder add "UbuntuVM" --name "share" --hostpath "/home/username/data" --automount
参数说明:
--name:共享名,规则同上,全小写、无空格。--hostpath:宿主机目录绝对路径。--automount:让虚拟机开机自动挂载。- 如果想设置临时共享(重启失效),加
--transient参数;如果想固定,加--permanent参数。默认情况下,如果虚拟机正在运行,命令会要求加--transient,要不就关机后再执行。
查看虚拟机的共享配置列表:
bash复制VBoxManage sharedfolder list "UbuntuVM"
输出里能看到共享名、宿主机路径以及是否自动挂载。写部署脚本的时候,这套命令比GUI点选靠谱得多。我自己在调试多台测试虚拟机时,都是写一个Shell脚本循环执行,几秒钟就能批量配置好。
另外,有个容易忽略的点:共享名和宿主机路径里如果有特殊字符或者空格,命令行方式必须用引号包裹,而且共享名最好不要用大写字母。Linux对大小写敏感,Windows里的共享名如果是大写,在Ubuntu里访问时会直接提示找不到目录。
2.3 挂载路径与权限的底层逻辑
不管用哪种方式设置,共享文件夹在Ubuntu里的默认挂载点都是/media/sf_共享名。这个目录的所有者是root,所属组是vboxsf,权限默认是drwxr-x---,也就是说普通用户压根没有读写权限。
很多新手在这里卡住,明明能看到目录,但打开后里面是空的,或者提示“Permission denied”。解决办法是把当前用户加入vboxsf组:
bash复制sudo usermod -aG vboxsf $USER
执行完这个命令后,必须注销重新登录,组权限才会在当前会话生效。这是Linux组权限的基本机制——用户所属组是在登录时确定的,不是实时刷新的。有次我在群里帮人排查,他执行完usermod没重登,过了半小时又来问为什么还是没权限,就是这个坑。
如果你不想折腾组权限,也可以手动挂载时指定uid和gid,直接让某个用户成为共享目录的属主,这个下面会讲。
3. 挂载实操与开机自动挂载
增强功能装好、共享文件夹也添加了,但Ubuntu里能不能稳定地用,取决于挂载方式和权限控制。有些人习惯把共享目录当作数据盘天天读写,有些人只是偶尔传个文件,两种情况的最佳实践不一样。
3.1 手动挂载:精确控制挂载点和权限
如果你不打算依赖默认的/media/sf_共享名路径,而是想把共享目录挂到自定义位置,比如/mnt/share,可以这样操作:
bash复制# 先创建挂载点目录
sudo mkdir -p /mnt/share
# 手动挂载共享文件夹
sudo mount -t vboxsf share /mnt/share
这里的share就是VirtualBox里设置的“文件夹名称”,不是宿主机路径。挂载成功后,/mnt/share里就是宿主机目录的内容了。卸载用sudo umount /mnt/share。
手动挂载最大的好处是能精细控制权限。比如你希望共享目录属于当前用户(假设UID是1000),目录权限750、文件权限640,这样同一个组的人能读,其他人看不到,尤其适合开发协作场景:
bash复制sudo mount -t vboxsf share /mnt/share -o uid=1000,gid=1000,dmask=027,fmask=137
参数解释:
uid=1000/gid=1000:把共享目录的文件属主和属组指定为UID/GID 1000的用户。查自己UID用id -u。dmask=027:目录权限掩码,意味着目录是750(755减去027的掩码效果)。fmask=137:文件权限掩码,意味着文件是640。
这些参数不熟悉的人容易搞混,简单记法:dmask管目录、fmask管文件,值越大权限越小。如果你只是个人单机使用,直接sudo mount -t vboxsf share /mnt/share -o uid=$USER,gid=$USER就行,省心。
3.2 开机自动挂载:fstab和systemd两种方案
自动挂载有三种实现路径,我挨个说,你自己选顺手的。
方案一:VirtualBox自带的“自动挂载”选项
GUI或命令行设置里勾上--automount后,Ubuntu开机后会在/media下生成sf_共享名目录并自动挂载。这是最省事的方法,不需要写配置文件。缺点是你没法自定义挂载点路径,权限也固定在root:vboxsf,需要加组权限才能正常读写。
方案二:/etc/fstab挂载
如果你想要自定义路径和权限,fstab是常见做法。用编辑器打开/etc/fstab,在末尾加一行:
bash复制share /mnt/share vboxsf defaults,uid=1000,gid=1000,dmask=027,fmask=137 0 0
字段依次是:共享名、挂载点、文件系统类型(vboxsf)、挂载选项、是否dump、是否fsck。加完先别急着重启,手动执行一下:
bash复制sudo mount -a
如果没有任何提示,说明fstab配置语法正确。有报错就检查共享名和挂载点路径。fstab挂载最容易翻车的场景是:开机时vboxsf模块还没加载完,导致系统提示“unknown filesystem type 'vboxsf'”。这种情况在系统启动顺序里很常见,尤其当虚拟机里启用了某些高级电源管理或fast boot时。偶发挂载失败后,/mnt/share是空的,运行sudo mount -a又能恢复。
方案三:systemd挂载单元
如果你对systemd比较熟悉,也可以写一个mount单元,能更好地控制启动顺序和依赖。在/etc/systemd/system/下新建mnt-share.mount文件:
ini复制[Unit]
Description=Mount VirtualBox shared folder
After=systemd-modules-load.service
[Mount]
What=share
Where=/mnt/share
Type=vboxsf
Options=uid=1000,gid=1000,dmask=027,fmask=137
[Install]
WantedBy=multi-user.target
然后执行:
bash复制sudo systemctl daemon-reload
sudo systemctl enable --now mnt-share.mount
说实话,对一个单机使用场景,方案三有点重。我自己的习惯是:如果路径无所谓,就用VirtualBox自带的automount;如果必须自定义路径,fstab一行搞定,出问题再排查。systemd单元更适合那些对稳定性要求极高、需要清楚看到挂载状态的服务器场景。
提示:不管用哪种自动挂载方式,如果设置了固定挂载点(比如/mnt/share),建议在该目录下放一个临时文件测试一下重启后是否正常,别等真要用的时候才发现挂载失败。
4. 踩坑实录:常见问题与排查方法汇总
共享文件夹这个功能,论坛里求助帖最多的几种现象,我基本都遇到过。我把它们集中整理一下,给一个可以直接对着查的清单。
4.1 Ubuntu里看不到共享文件夹,或者/media/sf_xxx目录不存在
这种问题大概率出在三个环节,按顺序排查:
- 增强功能是否正常:
lsmod | grep vboxsf,没有任何输出就是模块缺失。解决方案是重新安装增强功能,重点看/var/log/vboxadd-setup.log的报错。 - 是否有权限:
ls -ld /media/sf_*查看目录权限,属组应该是vboxsf,如果不是,检查用户是否在vboxsf组里:id $USER,输出里没vboxsf就去加组。 - 共享名是否匹配:查看VirtualBox共享配置:
VBoxManage sharedfolder list "虚拟机名",确认共享名和你在Ubuntu里访问的名字完全一致,注意大小写。
有个隐蔽坑:VirtualBox设置页里的“自动挂载”勾选后,系统会在/media下创建目录,但这个动作发生在用户登录阶段。如果Ubuntu是用SDDM或LightDM这类登录管理器,某些版本的虚拟机上,挂载可能因为Polkit策略问题被跳过。这种情况下,手动挂载一次sudo mount -t vboxsf share /mnt/share,然后去看/media下有没有目录生成。
4.2 mount时报错:unknown filesystem type 'vboxsf'
这个报错几乎可以断定是vboxsf内核模块没加载,也就是增强功能安装不成功或已失效。处理思路:
bash复制# 检查模块是否加载
lsmod | grep vboxsf
# 尝试手动加载
sudo modprobe vboxsf
如果modprobe报错,说明模块不存在。回到增强功能,重新安装:
bash复制cd /mnt/cdrom
sudo ./VBoxLinuxAdditions.run
安装脚本运行完,再看/var/log/vboxadd-setup.log。如果里面出现“Unable to find the kernel source tree”之类的字样,就是内核头文件没装。先sudo apt install linux-headers-$(uname -r)再重跑安装脚本。内核升级之后尤其容易遇到这个问题,因为旧模块对应的是旧内核,新内核缺模块。
还有一种情况是虚拟机启动时内核模块加载顺序不对,即使模块装好了,fstab挂载得太早也会报这个错。解决办法是fstab里加上x-systemd.automount选项,让挂载动作延迟到登录时再去触发:
bash复制share /mnt/share vboxsf defaults,x-systemd.automount,uid=1000,gid=1000 0 0
4.3 目录能看到,但打开提示“Permission denied”
这个在2.3里提过,九成是组权限问题。但你还需要检查另一个点:共享目录本身的权限可能被宿主机端的权限设置卡住了。
比如宿主机是Windows,共享目录里的文件如果被NTFS ACL设置为仅某个Windows用户可读,虚拟机端即使有vboxsf组权限,也可能访问不了部分文件。这种跨系统权限不一致的问题,唯一的办法是去宿主机把目录权限放开,或者统一权限参数挂载:
bash复制sudo mount -t vboxsf share /mnt/share -o rw,exec,uid=1000,gid=1000,dmask=000,fmask=000
dmask=000和fmask=000的意思是目录和文件都给予777权限,个人单机测试环境无所谓,生产环境慎重。
4.4 增强功能装完之后,重启直接黑屏或进不了图形界面
这个坑比较小众,但遇到一次就够呛。某些Ubuntu版本(特别是较新的发行版,比如23.04之后的版本)与VirtualBox增强功能的显卡驱动存在兼容性问题。安装后重启,画面卡在登录界面之后黑屏,或者花屏。
如果遇到,先在虚拟机的GRUB菜单选择“恢复模式(Recovery Mode)”,进入命令行,然后:
bash复制# 禁用或移除增强功能的显卡相关组件
sudo apt purge virtualbox-guest-* 2>/dev/null
sudo apt autoremove -y
然后重新启动,进普通桌面模式。需要说明的是,这种问题不是普遍现象,更多是特定内核版本和VirtualBox版本的组合问题。我一般建议是:先确保VirtualBox主程序是最新版本,再安装增强功能;装完后如果图形界面异常,优先考虑是OpenGL/3D加速模块的问题,在显示设置里把“启用3D加速”取消试试,这个选项在“显示 → 屏幕 → 硬件加速”里。
4.5 共享文件夹性能特别差,大文件拷贝极慢
共享文件夹的底层是VirtualBox的vboxsf文件系统驱动,它走的是虚拟机与宿主机的通信通道,不是虚拟SATA或者虚拟NVMe磁盘。所以I/O性能天然比虚拟磁盘差,尤其大量小文件读写时尤为明显。这是正常现象,不是故障。
我的使用建议:
| 使用场景 | 推荐做法 |
|---|---|
| 传几个大文件 | 共享文件夹没毛病,直接拷贝 |
| 大量小文件同步(源码、素材) | 用rsync同步到虚拟机磁盘再操作 |
| 编译、构建项目 | 千万别把源码直接放共享目录里编译,慢得怀疑人生 |
| 数据库文件 | 不建议放共享目录,文件锁和I/O导致的问题足够你排查一整天 |
| 日常代码编辑 | 可以在共享目录里改,但版本库操作前最好先同步到磁盘 |
如果你必须在共享目录里做频繁读写,可以尝试调整一下挂载参数,比如去掉不必要的atime更新、增加缓存:
bash复制sudo mount -t vboxsf share /mnt/share -o rw,uid=1000,gid=1000,noatime,nodiratime
noatime减少了对访问时间的写回,对小文件操作有点帮助。
5. 从共享文件夹延伸出去的几种扩展用法
共享文件夹解决了“宿主机和虚拟机之间怎么传文件”这个基本问题,但实际项目开发中,光有文件互访还不够。我顺手分享几个延伸技巧,都是实际使用中总结的。
5.1 给共享目录建个软链接,日常访问更方便
默认挂载路径在/media/sf_xxx,每次敲路径都带一长串。在用户目录下建一个软链,用起来顺手很多:
bash复制ln -s /media/sf_share ~/share
这样在终端里输入cd ~/share就能进入共享目录。如果你手动挂载到了/mnt/share,同样可以建软链:
bash复制ln -s /mnt/share ~/project-data
5.2 在共享目录里用Git,记得关掉fileMode检测
如果宿主机是Windows,虚拟机是Linux,在共享目录里克隆或修改Git仓库,会频繁出现“old mode 100644 / new mode 100755”的诡异提示。原因是Windows文件系统和Linux文件系统的权限处理逻辑不一样,Git默认会检测文件模式变化,而这种跨系统场景下检测结果并不靠谱。解决办法:
bash复制git config core.fileMode false
这个配置只对当前仓库生效,不会影响全局。提交代码之前建议再执行git config --get core.fileMode确认一下。
Windows和Linux之间共享目录里还有一个隐性问题:换行符。Windows下文件可能是CRLF,Linux工具链未必能顺畅处理。如果你在共享目录里写脚本、改配置文件,建议把编辑器的“自动转换换行符”关掉,或者统一用Git的core.autocrlf配置来管理。
5.3 共享文件夹和Samba的选型区别
VirtualBox的共享文件夹是“宿主机与虚拟机之间”的专属通道,只服务于当前这台虚拟机。如果虚拟机里跑了一些服务,需要和局域网中其他设备交换文件,共享文件夹就帮不上忙了,因为其他机器访问不到这个通道。
这种场景下可以考虑在Ubuntu里装Samba,直接把虚拟机里的目录变成网络共享。Samba配置不算复杂,装好之后用smbpasswd设置用户密码,然后编辑/etc/samba/smb.conf,把要共享的目录加进去,重启smbd服务即可。和vboxsf相比,Samba的优势是跨设备访问,但配置门槛更高,走网络协议速度也不占优势。
我的建议是:如果只是宿主机和虚拟机之间的文件互访,用VirtualBox共享文件夹;如果虚拟机作为一个小型服务器,需要给局域网其他设备提供文件服务,那就上Samba。两个不冲突,甚至可以在共享文件夹里跑Samba,但一般没这个必要。
5.4 数据库文件和磁盘镜像不要长期放在共享目录里
这一点值得单独强调。共享文件夹在虚拟机里看上去是一个目录,但它不是块设备,文件锁支持也比较弱。数据库(比如SQLite、MySQL的数据目录、Docker的volume)如果放在共享目录里,轻则性能差,重则出现文件损坏、锁冲突导致服务起不来。
有次我把一个测试用的Docker容器挂在共享目录下,跑了两天容器直接提示“No space left on device”,但宿主机空间明明是够的。后来才发现是共享目录的文件系统不支持某种稀疏文件的处理,重新把数据迁回虚拟磁盘才正常。所以,数据目录、数据库文件、虚拟机磁盘镜像这类东西,老老实实放在虚拟机内部磁盘里,备份时再用共享文件夹或Samba导出即可。
我个人调试VirtualBox + Ubuntu的几年时间里,共享文件夹是使用频率最高的功能之一。它的坑不算多,但每一个坑都特别容易让人怀疑人生。尤其是“明明设了共享却看不到目录”“明明加了组权限却还是Permission denied”这两类问题,几乎每周都有人问。后来我总结下来就是:先验证增强功能,再检查组权限,最后才怀疑配置。顺序对了,一切都很顺畅。最后再分享一个压箱底的小技巧:如果你只是偶尔想传一个文件,最快的办法其实是VirtualBox的“拖拽”功能,前提是开启了双向拖拽;但一旦进入日常项目开发,共享文件夹依然是效率最高、最稳的方案。希望这篇文章能帮你一次把这条链路跑顺。
