☰
Ubuntu挂载Windows共享文件夹:SMB/CIFS权限与fstab自动挂载实战
2026/10/19 2:58:16 网站建设 项目流程

以前在Windows和Ubuntu双系统之间传文件,我用的还是最原始的办法:U盘拷一遍、改完再拷回去。直到有次帮同事排查问题,才发现Ubuntu挂载访问Windows的共享文件夹,一条mount命令就能稳定搞定,根本不用来回搬运。真正麻烦的不是命令本身,而是共享权限、SMB协议版本、还有那一堆不起眼的挂载参数。

这篇文章我给双系统用户、Linux新手、每天要在Windows和Ubuntu之间传文件的开发者看。我会从"为什么图形界面能打开、命令行却挂不上"讲起,把手动挂载、开机自动挂载、常见权限问题、网络报错排查全部走一遍,最后分享我自己沉淀下来的使用习惯。全部基于我在真实环境里反复试过的方案,不整虚的。

1. 为什么图形界面能打开Windows共享,命令行却老是挂不上

先说结论:Linux访问Windows共享,底层走的是SMB(Server Message Block)协议。协议在Linux圈子里还有个老名字叫CIFS,Linux内核里处理这个协议的模块叫cifs.ko,配套的用户态挂载工具叫cifs-utils。说人话就是,你的Ubuntu要作为SMB客户端,通过网络去读写Windows机器上SMB服务端共享出来的目录。这和访问NAS设备的原理完全一样,市面主流NAS的共享服务本质上就是SMB。

很多人第一次尝试的时候,会先去Ubuntu自带的文件管理器,在侧边栏的"网络"里找到Windows机器,或者直接在地址栏输入smb://192.168.1.100之类的路径,看到共享文件夹直接点进去,心里想:这不挺简单吗?可一旦打开终端敲mount命令,各种permission denied、Host is down就纷纷冒出来。

1.1 图形工具帮你干的那些隐形活

图形文件管理器看起来什么都没做就进去了,那是它在背后替你干了一堆事:自动发现局域网里的SMB主机、自动尝试多种协议版本协商、弹窗让你输账户密码、自动选合适的挂载参数。这相当于一位体贴的向导把你领到了目的地,但你自己开车走同一条路的时候,每一个路口都要自己做决定。

命令行挂载就不一样了,你得明确告诉系统:连接哪台机器的哪个共享名、用什么账户、SMB协议协商到哪个版本、挂载参数怎么给。漏掉任何一项,都可能得到一条不明不白的报错。这也是为什么同样一台机器,GUI能进去,命令行反而挂不上。了解了这一点,后面的参数配置你就能理解为什么每一项都不能省。

1.2 网络文件共享的"普通话":SMB/CIFS版本差异

SMB协议本身经历了1.0、2.0、2.1、3.0、3.1.1几个大版本。新版Windows默认只启用SMB2及以上版本,SMB1因为历史上出过严重安全漏洞基本被默认关闭;而一些老Windows系统或老款NAS设备,可能还停留在SMB1时代。Linux内核的cifs客户端虽然会自动协商,但在某些老设备和特殊网络环境下,自动协商依然会翻车。这就是为什么挂载参数里要留一手vers=。我一般会显式指定版本,避免内核在协议版本上来回试探浪费时间。

我个人实践下来的经验是:现代Windows环境直接用vers=3.0,老环境出了报错再尝试vers=2.0。SMB1能不用就不用,安全风险太大,除非你面对的是一台除了SMB1什么都不支持的老古董设备。

2. 动手之前:Windows侧把共享和权限设对,Ubuntu侧把工具装齐

挂载前不做好两头准备,后面必然踩坑。Windows侧决定你有没有权限访问,Ubuntu侧决定你能不能挂载成功,两侧缺一不可。

2.1 Windows端:共享名、用户权限与防火墙三个关键点

在Windows上先右键目标文件夹,选择"属性"进入"共享"选项卡,点击"高级共享",勾选"共享此文件夹"。这里我要特别强调共享名:尽量取一个简单好记的英文名,比如ShareData,不要带空格、不要带特殊符号。共享名会在Ubuntu挂载路径里直接出现,取太复杂后面自己都容易敲错。

真正容易坑人的是"权限"按钮。Windows默认共享权限通常只给Everyone只读,你后面Linux端参数配得再完美,也只能读不能写。所以在"权限"里选中对应的用户或Everyone,把"更改"和"读取"都勾上。比Everyone更稳妥的做法是指定一个具体的Windows账户,因为新版Windows默认禁用了guest访客访问,匿名方式经常连不上去。

网络和防火墙也不能忽略。建议把Windows的当前网络设为专用网络,并在"高级共享设置"里打开"网络发现"和"文件和打印机共享"。如果你Windows防火墙开得比较严,最简单的排查方式就是临时关闭防火墙确认问题,通了之后再加回规则,核心是放行TCP 445端口。很多挂载失败案例都是因为防火墙把445端口拦了,数据包根本进不来。

2.2 Ubuntu端:只需要装cifs-utils,外加一个排障用的smbclient

Ubuntu默认不带cifs-utils,需要先装。打开终端执行:

sudo apt update sudo apt install cifs-utils

顺手再把smbclient也装上,这工具用来探路非常方便,能直接列出Windows共享列表,排查挂载问题很有用:

sudo apt install smbclient

这里有个原理值得解释:mount -t cifs能识别cifs类型,依赖的就是cifs-utils里提供的挂载辅助程序。Linux内核确实自带cifs模块,但没有用户态工具配合,命令行挂载无从谈起。这就是为什么一些精简版系统里内核明明有cifs支持,你执行挂载却报unknown filesystem type 'cifs'之类错误的原因。

2.3 把IP、共享名、账号这三样东西确认到手

准备工作最后一步,收集三个关键信息。

Windows的IP:在Windows命令行里执行ipconfig,找到当前网络下的IPv4地址,通常是192.168.x.x或10.x.x.x网段。如果是虚拟机,直接用虚拟网卡的IP地址就行。共享名就是你在2.1里设置的名字,比如ShareData。账户就是允许访问共享的那个Windows用户名和密码。

这三个信息凑齐,才有资格进入下一步。习惯上我会优先用IP地址而不是主机名访问,少一个解析环节,排查防火墙和网络问题时更清晰。如果你的Windows这边IP是DHCP动态分配的,那用主机名更稳定,这一块看实际环境取舍。

3. 手动挂载一条命令全解析:从裸奔到读写自如的mount命令

配置自动挂载之前,我建议每个人都先手动挂载一次,亲眼看到整个流程跑通。手动挂载最直接,也能让你对每个参数的效果有体感。

3.1 先创建一个挂载点,再敲出第一行能用的mount命令

挂载点就是Ubuntu这边的一个空目录,Windows共享的内容会以目录树的形式出现在这里。我习惯建在 /mnt 下,放家目录里也完全没问题。执行:

sudo mkdir -p /mnt/win_share

然后执行我的标准挂载命令:

sudo mount -t cifs //192.168.1.100/ShareData /mnt/win_share -o username=yourname,password=yourpass,uid=1000,gid=1000,file_mode=0664,dir_mode=0775,iocharset=utf8

如果你的网络环境和Windows版本都比较标准,这条命令大概率一次成功。此时执行ls /mnt/win_share,就能看到Windows那边共享出来的文件了。注意ShareData是Windows侧设置的共享名,不是完整路径。这个位置写错也会报错,而且报错信息还容易误导人。

3.2 参数逐条拆解:uid/gid/file_mode/dir_mode才是权限大头

参数看着多,其实每条都有明确用途:

  • username/password:Windows账户和密码。密码直接写在命令行里会留在shell历史中,临时测试可以,长期使用建议用后面的credentials文件方案。
  • uid/gid:挂载后文件和目录在Linux侧显示的属主和属组。Ubuntu桌面版第一个用户的uid一般是1000,可以用id命令确认。这个参数可以说是"能看到文件但打不开"最常见解法:不写它,挂载出的文件权限归root,你的普通用户自然碰不了,更别提修改。
  • file_mode/dir_mode:控制挂载出来后的文件和目录权限。file_mode=0664表示普通文件所有者和同组可读写,其他人只读;dir_mode=0775表示目录所有者和同组有全部权限,其他人可读和执行但不能写。不写这两个参数,默认可能给你挂出755权限,看起来能进目录,但新建文件、修改内容就会报错。
  • iocharset=utf8:指定本地字符集转换,主要解决中文文件名乱码。大部分现代环境默认UTF-8,但保不齐某些环境或老locale会出幺蛾子,显式写上更放心。
  • vers=3.0:SMB协议版本。新版Windows默认SMB3.x,Linux客户端一般协商没问题;老设备或特殊网络环境才需要降到vers=2.0甚至vers=1.0。协议版本问题我会在第5章展开,这里先知道有这东西。
  • sec=ntlmssp:有遇到认证方式不match的时候,显式指定这个参数往往能救回来。新版Windows的认证走NTLMv2,Linux cifs客户端默认能协商,但某些情况下加了这个参数更稳。

这里还有个操作小技巧:手动挂载时不想在命令行里输密码,只写username,系统会交互式提示你输入密码:

sudo mount -t cifs //192.168.1.100/ShareData /mnt/win_share -o username=yourname,uid=1000,gid=1000

3.3 验证挂载成功以及如何彻底卸载

挂载后建议做三件事确认状态:

df -h | grep cifs mount | grep cifs ls -l /mnt/win_share

df -h能确认这个挂载点的空间信息和挂载是否成功;mount | grep cifs可以完整查看当前挂载参数,确认uid/gid、文件权限、协议版本是否按预期生效,排障时这条命令信息量很大。ls -l主要看文件属主和权限位是否正常。

卸载只有一条命令:

sudo umount /mnt/win_share

如果系统提示 "target is busy",说明还有进程占着这个目录,比如你在里面打开过文件或者终端当前目录就在挂载点下。解决方式要么退出占用目录,要么用懒卸载:

sudo umount -l /mnt/win_share

-l的意思是先把挂载关系从目录树里解除,不阻塞等待底层连接释放,适用于网络连接已经假死、正常umount卡住的情况。

4. 开机自动挂载:fstab的坑、x-systemd.automount的妙处,以及systemd挂载单元

手动挂载成功只是第一步。重启一次,挂载点又空了,这谁受得了。所以大家自然会想到写进/etc/fstab,但这里恰恰是踩坑重灾区。

4.1 盲目填fstab为什么开机经常失败

fstab是系统启动时读取的自动挂载表。很多人照着手动命令抄一行进去,重启一看,没挂上,原因很简单:系统启动进行到挂载这一步时,网络还没就绪。Windows共享是网络文件系统,不是本地硬盘,开机瞬间连SMB服务器都ping不通,挂载怎么可能成功?网络都没起来,你让mount命令去哪儿找那台Windows机器。

解决的关键是给网络共享加两个参数:

  • _netdev:明确告诉系统这是网络设备,等网络就绪后再尝试挂载。
  • x-systemd.automount:让systemd对挂载点做按需触发。开机时不再主动挂载,而是当你第一次访问/mnt/win_share目录时,才触发背后的挂载动作。

加了这个参数,挂载动作被推迟到实际访问时,自然就避开了"开机瞬间网络还没好"的尴尬。即使某次网络服务慢、连不上,也不会阻塞开机流程。

4.2 用credentials文件把密码藏起来

fstab是系统启动时自动读取的文件,权限一般只有root能改,但文件内容所有用户都能看到。你把Windows密码明文写进去,等于把密码公开在所有能开机进入系统的用户面前,这显然不是好习惯。更好的做法是单独建一个凭证文件:

sudo mkdir -p /etc/samba sudo touch /etc/samba/credentials sudo chmod 600 /etc/samba/credentials

文件内容:

username=yourname password=yourpass

权限600,只有root能读。然后在挂载参数里用credentials=/etc/samba/credentials代替原来的 username/password。凭证文件还支持一行额外的 domain 配置,如果你的Windows账户属于域环境,可以在这里指定。可维护性也比直接改fstab强:Windows密码一换,只改这个文件就够,不用到处找fstab里的旧密码。

4.3 fstab标准写法与x-systemd.automount按需挂载

我长期使用的fstab配置长这样:

//192.168.1.100/ShareData /mnt/win_share cifs credentials=/etc/samba/credentials,uid=1000,gid=1000,file_mode=0664,dir_mode=0775,iocharset=utf8,vers=3.0,_netdev,x-systemd.automount,nofail 0 0

每个参数前面都解释过,不再重复。重点说一下nofail。加上它以后,如果你的笔记本不在Windows所在的网络环境里(比如带去公司,不在家里网段),开机时这一行fstab也不会报错或卡住启动。这个选项我强烈建议加上。

写完执行测试:

sudo mount -a

mount -a会按照fstab内容把所有待挂载条目尝试挂载一遍,语法或参数有问题,这里立刻暴露。然后再执行:

systemctl daemon-reload

让systemd重新读取fstab转换出来的挂载单元。确认无误后,下次重启就能按预期自动挂载了。

4.4 改用systemd挂载单元,依赖关系更清晰

如果你不喜欢fstab的隐式处理,也可以为这个共享单独创建systemd挂载单元。挂载点是/mnt/win_share,对应的单元文件名是mnt-win_share.mount(路径中的斜杠 / 转成中划线 -),放在/etc/systemd/system/目录下:

[Unit] Description=Mount Windows Share After=network-online.target Wants=network-online.target [Mount] What=//192.168.1.100/ShareData Where=/mnt/win_share Type=cifs Options=credentials=/etc/samba/credentials,uid=1000,gid=1000,file_mode=0664,dir_mode=0775,iocharset=utf8,vers=3.0,_netdev [Install] WantedBy=multi-user.target

然后执行:

sudo systemctl daemon-reload sudo systemctl enable --now mnt-win_share.mount

systemd单元能更精确地控制启动顺序和依赖关系,尤其适合开机时需要等某个网络目标或服务就绪的机器。它还有一个好处是可以用systemctl status mnt-win_share.mount查看挂载状态、出错日志,排查问题时比看fstab直观得多。不过对普通用户来说,fstab加_netdev,x-systemd.automount,nofail已经足够稳,不用为了单元而单元。

两种方式的对比我总结如下:

对比项fstab + x-systemd.automountsystemd挂载单元
配置复杂度低中
按需挂载天生支持需额外配置automount单元
依赖控制简单精细
排障直观度一般高
适合场景个人电脑、双系统服务器、有编排需求的机器

5. 挂载之后的翻车现场与排查路径:写权限、协议版本、乱码与断线

挂载成功只是开始,接下来大概率会遇到几个经典问题。我按真实环境里出现频率从高到低逐个说。

5.1 挂是挂上了,但只能读不能写

这是被问得最多的问题。症状统一:ls能看到Windows里的文件,打开也能看,可新建文件、修改内容统统失败。我第一次遇到也卡了很久,后来总结出排查顺序。

第一,去Windows端确认共享权限和NTFS权限。右键共享文件夹 → 属性 → 共享 → 高级共享 → 权限,看相应用户是否勾选"更改"。这里如果只有"读取",Linux端再怎么折腾都没用。另外,文件夹本身的"安全"选项卡里,NTFS权限也要给"修改"。这两层权限,任何一个卡住都会导致写不进去。

第二,检查Linux侧挂载参数。如果uid/gid没设,挂载出来的文件所有者是root,你的登录用户完全没有写权限;如果file_mode/dir_mode给成偏保守的值,也一样写不了。改参数重新挂载:

sudo umount /mnt/win_share sudo mount -t cifs //192.168.1.100/ShareData /mnt/win_share -o username=yourname,uid=$(id -u),gid=$(id -g),file_mode=0775,dir_mode=0775

这里用$(id -u)能自动替换成你当前的uid,省得手动查。理论上参数和Windows权限都正确,写权限就通了。

还有一招叫noperm,意思是让Linux客户端不再检查文件权限,把权限判断完全交给服务器端。遇到"Windows权限没问题、Linux参数也没问题、就是死活写不了"的疑难杂症,可以临时加noperm试试。但提醒一句,noperm会让本机所有能访问挂载点的用户都获得与服务器凭据一致的权限,存在安全风险,不推荐长期使用,只建议排障时用。

5.2 mount error(13)和error(112):认证失败还是网络不通?

挂载阶段最常见的两个报错,定位思路完全不同。

mount error(13): Permission denied,认证阶段被拒。常见原因有三个:Windows账户密码不对;guest访问被禁用且你没提供有效账户;SMB1被禁用导致协议协商版本不匹配。排查时先执行:

smbclient -L //192.168.1.100 -U yourname

如果smbclient能列出共享,说明认证没问题,问题多半出在mount参数上;如果smbclient也报access denied,那就得回Windows侧检查账户和共享权限。遇到认证协商相关的复杂情况,显式加sec=ntlmssp或者vers=3.0往往能绕开。

mount error(112): Host is down,语义是主机不可达,绝大多数是网络和端口问题。先ping:

ping -c 4 192.168.1.100

ping不通查物理链路和网段配置;ping通但一直报112,基本可以锁定TCP 445端口被防火墙或中间设备拦了。去Windows防火墙放行"文件和打印机共享"规则,或者临时关闭防火墙再试,马上见分晓。还要检查Windows的SMB服务是否被优化软件或组策略禁用,端口根本没监听,外面自然连不进去。

整个排查链路我推荐按顺序执行这三步:

ping -c 4 192.168.1.100 nc -zv 192.168.1.100 445 smbclient -L //192.168.1.100 -U yourname

三步走完,八成问题都能定位清楚。

5.3 中文文件名乱码的根子不在挂载参数

中文文件名变成一串乱码,看起来像编码问题,实际是字符集转换问题。SMB协议现在内部用UTF-16传输,Linux侧显示时再转换成本地编码。如果你的系统locale不是UTF-8,或者挂载参数漏了iocharset=utf8,乱码就会出现。

先看系统locale:

locale

如果输出不是UTF-8结尾,就要先在挂载参数里补iocharset=utf8再重新挂载。绝大多数情况下,加了utf8乱码就消失了。如果还乱,那要考虑是不是Windows端共享文件夹里某些中文文件名来自老编码环境,Windows侧看着正常,跨协议传输后字符映射本身就丢了信息。这种情况只能在共享系统里手动改一次文件名。

常见误区是觉得问题出在Windows的GBK编码上。其实SMB 2.1以上的共享文件名传输已经是UTF-16,配合Linux侧的iocharset=utf8转换就能正常显示。现在乱码的根子反而容易出在Linux侧的locale上,别先怀疑Windows。

5.4 网络断了、机器重启后的恢复与懒卸载

无线网络、睡眠唤醒、网络切换,是让挂载点"假死"的三大元凶。表现很典型:挂载点还在df -h里,但访问时整个卡住,ls半天不返回,文件管理器跟着无响应。本质是连接断了,但内核还没重新协商,挂载会话处于僵尸状态。

遇到假死,先尝试懒卸载:

sudo umount -l /mnt/win_share

把挂载点先从目录树里摘掉,不阻塞等待底层连接释放。然后重新mount一次,基本就恢复了。如果不想手动救,fstab里保留x-systemd.automount会在下次访问时重新触发挂载,对无线环境相当友好。

网络不稳定时还有一个调节选项:挂载参数加cache=loose或cache=none可以改变缓存策略。cache=none会比较慢,但能减少"文件明明改了,Windows那边却不更新"的体验落差。我如果经常在Ubuntu里编辑同一个文件,会优先保证一致性,而不是追求性能。

6. 按照实际使用场景,我给自己定下的挂载习惯

折腾过这么多台机器、帮人排查过各种奇奇怪怪的问题之后,我现在面对挂载访问Windows共享这件事,基本按使用场景直接分流:

临时拷一次文件,直接在GUI地址栏输smb://IP/共享名,或者手动mount时不写密码、交互式输入,用完立刻umount。每天都要用的共享,用fstab加_netdev,x-systemd.automount,nofail,凭据走credentials文件,uid/gid设成自己用户,file_mode/dir_mode按是否多人协作调整。服务器上常驻访问,优先用systemd挂载单元,依赖关系写清楚,出错能用systemctl status看到原因。

安全上再提醒几个点:不要图省事把Windows共享权限设成Everyone完全控制;不要用SMB1协议访问任何设备,SMB1的安全性在今天已经拿不上台面;credentials文件记得600权限;noperm能用但别当常态配置用。

最后分享一个顺手的小技巧:在Ubuntu的/etc/hosts里给经常访问的Windows机器加一行静态解析,比如192.168.1.100 filehost,之后挂载就写//filehost/ShareData。IP一旦变化,只改hosts一处,比满世界替换IP省心很多。挂载访问Windows共享这件事本身不难,难的是把每个参数背后的数据链路和权限模型想明白,想明白了,再遇到新报错,排查思路自然就顺了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询