ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux挂载Windows共享目录:SMB/CIFS从原理到实操

Linux挂载Windows共享目录:SMB/CIFS从原理到实操 番外篇把Windows共享目录挂到Linux上这事没你想的那么玄混Linux圈子的人迟早会遇到这么个场景你手头一台Windows机器上堆着团队共享的文档、视频素材、代码包而你自己日常开发用的是Linux。想拷文件要么U盘倒腾要么每次用scp拉麻烦不说来回几次目录结构就乱得没法看。更常见的场景是公司内网有一台Windows文件服务器大家的项目资料都在上面你需要在Linux下随时读写。解决这个问题的标准动作就是把Windows的共享目录直接挂载到Linux的目录树上让它像一个本地文件夹一样使用。这个操作在Linux入门教程里经常被当成“进阶内容”一笔带过但说实话它真没多难——无非是搞清楚SMB/CIFS这套协议然后会用mount命令再加上几个关键参数。这篇文章就把整个流程掰开揉碎讲清楚从原理到实操再到各种翻车现场的排查一篇搞定。先说明一下适用人群刚把Linux装起来、正处在“啥都想试试”阶段的新手或者从Windows转过来但对网络文件共享不太熟的同学。文章里涉及的命令我会解释到“为什么这么写”的层面不用死记硬背。1. 动手之前先搞清楚这件事背后的逻辑1.1 为什么是SMB/CIFS而不是别的协议Windows里的“共享文件夹”底层用的是SMB协议Server Message Block这个协议最早是IBM发明的后来微软把它发扬光大广泛用于Windows系统的文件共享和打印共享。而CIFSCommon Internet File System是SMB协议的一个早期版本在很长一段时间里被当作SMB的代称。今天Linux内核里的cifs文件系统驱动实际支持的已经包含SMB1、SMB2、SMB2.1、SMB3.0等多个版本可以说“以CIFS之名行SMB之实”。你可能要问Linux挂载网络目录不是还有NFS吗为什么不用NFS原因很简单——Windows的共享目录默认就说SMB你用NFS去挂Windows的东西还得先在Windows上开启NFS服务、配置导出目录、处理权限映射Windows端的NFS实现并不是开箱即用那么友好折腾成本高得多。反过来SMB在Linux这边的支持已经很成熟了cifs驱动是内核自带的模块再配合cifs-utils这个工具包基本是开箱即用。用生活类比来理解SMB就像是你去邻居家吃饭用的公共餐具大家约定俗成Windows是主人家全套都有。Linux要借用这套餐具只需要掌握正确的使用方法就行而不需要把自家餐具NFS搬到邻居家。1.2 哪些场景下你会真正用到它我自己的使用经历里这几个场景最典型办公室环境公司文件服务器是Windows Server共享了公共盘、部门盘Linux工作站需要随时读取上面的资料。这种情况在混合IT环境里非常常见。开发调试写嵌入式或需要交叉编译的程序编译产物输出到Windows共享目录然后Windows上的其他工具接着处理。挂载后编译脚本里直接写/mnt/winshare/output/xxx就行少绕很多路。个人NAS很多NAS系统比如群晖、威联通、飞牛都支持SMB共享Linux设备挂载NAS目录做备份、存电影、跑下载任务一套SMB全搞定。虚拟机/容器场景Windows宿主机和Linux虚拟机之间传文件很多人用共享文件夹其实本质也是SMB。不管哪个场景核心需求都一样让Linux能像访问本地磁盘一样顺畅读写Windows共享出来的目录。1.3 挂载的本质是“客户端-服务器”模型这里还是要稍微说下原理不然遇到问题你会一脸懵。挂载Windows共享目录本质上就是Linux这台机器作为SMB客户端去连接Windows这台SMB服务器。客户端发起连接需要三样东西服务器地址、共享名称、认证凭据用户名和密码。连接成功后内核的cifs驱动会把远程文件系统映射到本地挂载点之后你ls、cp、rm、vim这些操作都会被翻译成SMB协议请求发送给服务器执行。这个过程跟你用ssh登录远程主机不一样——SSH是交互式的用完就断开挂载是长连接你打开的每一个文件操作都是实时的远程访问。这就引出了很多坑权限映射、协议版本、网络稳定性、编码格式每一项都可能让你在挂载时“翻车”。接下来一个个说。2. 准备工作Windows端和Linux端都要动一下2.1 Windows端把共享目录准备妥当Windows端要做的其实很简单就是“共享”和“授权”。先说共享在你要共享的文件夹上右键选择“属性” → “共享” → “高级共享”勾选“共享此文件夹”给它起一个共享名建议用英文字母和数字避免中文名省得后面Linux端处理起来麻烦还可能遇到编码问题。然后是授权。这一步很多人会犯迷糊其实Windows共享涉及两层权限共享权限和NTFS权限。简单理解共享权限是“门禁”NTFS权限是“房间里的规矩”最终生效的是两者中更严格的那个。对Linux挂载来说我建议你专门创建一个用于共享访问的Windows用户密码设置得复杂一点然后给它完整的读写权限同时控制好它的访问范围只让它能访问该共享的目录。不要图省事直接开Guest或Everyone一旦机器在内网被扫描到共享目录里的东西等于裸奔。最后确认一下Windows的内网IP地址用ipconfig就能看到。另外在生产环境里还要确保Windows防火墙放行了SMB服务的端口TCP 445一般默认是放行的但如果你之前手动加固过防火墙就需要检查一下。2.2 Linux端确认内核支持和必备工具在Linux上第一步要确认内核是否支持cifs文件系统。现在的发行版基本都支持但保险起见还是看一下modprobe cifs grep cifs /proc/filesystems如果grep结果里有nodev cifs说明内核已经支持。如果modprobe报错通常是你用的Linux发行版精简了内核模块比如某些定制版内核或容器环境会遇到这个问题。这种情况要么换内核要么改用smbfs老驱动不建议太老了要么老老实实用其他方案比如sshfs不过用的场景就变了。接下来安装cifs-utils这是挂载工具包提供mount.cifs这个辅助程序。不同发行版安装方式不一样# Debian / Ubuntu apt install cifs-utils # CentOS / RHEL / Rocky / Fedora yum install cifs-utils # 或 dnf install cifs-utils装完之后用mount.cifs --version验证一下能打印出版本号就说明OK了。最后还要创建一个本地挂载点。挂载点本质上就是一个空目录作用是承载远程文件系统的入口。按惯例放在/mnt或/media下比较多当然你喜欢的话放哪都行但要注意挂载点目录权限要允许当前用户读和执行否则挂载成功了你也进不去。sudo mkdir -p /mnt/winshare2.3 先做一次网络联通性检查正式挂载之前先确认Linux能访问到Windows的445端口。最简单的方式是用ping看网络通不通再用nc或telnet看端口通不通ping -c 3 192.168.1.100 nc -zv 192.168.1.100 445如果你看到Connection succeeded说明网络层没问题。这一步排查很重要很多人第一次挂载失败其实就是Windows防火墙挡了445端口白白在那折腾半天。3. 核心实操手动挂载Windows共享目录3.1 最简单但够用的挂载命令现在正式挂载。先看一下最基本的命令形态sudo mount -t cifs //192.168.1.100/shared /mnt/winshare -o usernamewinuser执行后系统会提示输入密码输入Windows用户winuser的密码回车就行。如果一切顺利你会回到Shell提示符然后ls /mnt/winshare就能看到Windows共享目录里的文件了。这里对新手解释一下//192.168.1.100/shared是UNC路径格式192.168.1.100是Windows主机的IPshared是你在Windows端设置的共享名。写成两个斜杠开头而不是一个是SMB协议家族的惯例与Linux本地路径完全不同注意别写错。3.2 密码和凭据的处理技巧把密码直接写在命令行里确实省事但不推荐在历史记录敏感的机器上这么干而且脚本里明文写密码也是非常坏的习惯。比较稳妥的做法是把用户名密码写进一个专门的凭据文件然后挂载时指定它cat ~/.smbcredentials EOF usernamewinuser passwordYourStrongPassword domainWORKGROUP EOF chmod 600 ~/.smbcredentials然后用这个凭据文件挂载sudo mount -t cifs //192.168.1.100/shared /mnt/winshare -o credentials/home/yourname/.smbcredentials注意chmod 600这步不是可选的——凭据文件里是明文密码如果权限太松任何本地用户都能读到。我甚至建议把凭据文件放在root专属目录/root下并用root权限创建和保管。3.3 关键参数逐个拆解不看会吃亏如果你只做到上面那步挂载是能成功了但用起来大概率会遇到权限错乱、文件没权限写、大文件传输卡顿、中文文件名乱码等问题。下面这些参数是保证体验的关键。协议版本versSMB协议有过SMB 1.0、2.0、2.1、3.0等版本。早期Windows比如XP、2003只支持SMB 1.0而SMB 1.0既有严重安全漏洞比如著名的“永恒之蓝”勒索病毒就是通过它传播的性能也差。现代系统基本都支持SMB 3.0及以上。挂载时可以显式指定-o vers3.0如果你的Windows版本比较老可能要降到vers2.0或vers2.1。不要默认不写——内核默认会先尝试SMB 3.0如果对端不支持再协商降级但有时候协商过程会出问题不如手动指明省心。本地权限映射uid/gid和file_mode/dir_mode这是新手最容易困惑的地方。Windows那边文件是有ACL的映射到Linux这边后你会看到文件的属主和权限可能很奇怪挂载点上所有文件的属主变成root普通用户写不进去或者所有文件权限是0755没法和本地用户直接协作。原因在于SMB的Windows ACL模型和Linux的POSIX权限模型不能直接等价。你需要告诉内核把远程文件的逻辑属主映射到本地哪个用户/组。比如当前Linux用户叫linuxuserUID是1000那就指定-o uid1000,gid1000,file_mode0644,dir_mode0755这样挂载上去之后所有远程文件在Linux侧看起来的「属主」是linuxuser目录可进文件可读可写取决于file_mode跟本地习惯就对齐了。编码与字符集iocharset中文目录名和文件名在共享里乱码多半是字符集没配对。现代Windows默认用的是UTF-8尤其是Win10/11的中文版Linux侧只要指定iocharsetutf8基本就能解决-o iocharsetutf8但如果你连的是一台老款Windows Server 2008或者对方共享里的文件名用了GBK编码很多老系统上生成的旧文件那么可以试试iocharsetcp936。在实际环境中我倾向于先在Windows端确认文件名的编码方式再决定Linux侧用什么解码。缓存与性能rsize/wsize/cache大文件传输慢通常可以调整SMB的读写块大小和缓存策略。rsize和wsize是用来指定读、写缓冲区大小的参数默认值在不同的内核版本上不一定最优。一般可以试试-o rsize1048576,wsize1048576把读写缓冲调到1MB对千兆内网来说吞吐量通常能明显提升。内核较新的版本里还有个cacheloose参数可以允许更激进的本地缓存适合读多写少、对一致性要求不高的场景比如看视频、读文档。但小心如果同一共享被多台机器同时写cacheloose可能让你看到陈旧数据生产环境慎用。其他几个值得了解的参数_netdev告诉系统这是网络设备启动时在网络就绪后再挂载避免开机挂载失败。对fstab自动挂载很关键。noexec不允许在这个文件系统上直接执行二进制文件。安全起见建议加上防止共享目录被当作病毒投放点。nobrl关闭POSIX字节范围锁解决某些Windows应用在同一文件上与Linux访问互相冲突的问题。但对多进程并发写同一份文件的场景这个参数可能引入风险。secntlmssp或secntlmsspi指定认证方式。多数情况下不需要手动指定但遇到「密码正确却认证失败」的怪问题时可以检查下是不是Windows端禁用了NTLM/NTLMv2协商必要时显式指定认证类型。3.4 挂载结果验证挂载完成后建议用几条命令检查状态# 查看挂载信息 mount | grep cifs # 查看文件系统使用情况 df -h /mnt/winshare # 简单读写测试 touch /mnt/winshare/test.txt ls -l /mnt/winshare/test.txt rm /mnt/winshare/test.txt如果读写测试出现Permission denied大概率是权限映射的问题回上面检查uid和file_mode。如果一切正常恭喜你已经完成了一次手动挂载。4. 让它开机自动挂载别每次手动输命令4.1 编辑fstab的正确姿势手动挂载只能生效一次重启就没了。要实现开机自动挂载需要把它写进/etc/fstab。fstab是Linux系统启动时自动挂载文件系统的总配置表每一行描述一个挂载项。网上很多教程直接让你往fstab里塞一句mount参数照着写了开机却起不来原因多半是没理解fstab的格式。先看一个最稳的fstab写法//192.168.1.100/shared /mnt/winshare cifs credentials/root/.smbcredentials,uid1000,gid1000,iocharsetutf8,file_mode0755,dir_mode0755,_netdev 0 0一行六列含义是设备名、挂载点、文件系统类型、挂载参数、dump开关、fsck检查顺序。设备名用//IP/共享名格式。挂载点是之前创建的/mnt/winshare。文件系统类型写cifs。挂载参数里注意加了_netdev这个参数保证系统在等待网络就绪后才执行挂载避免开机时网络还没起来就傻乎乎地去连SMB服务器导致挂载失败。最后两列的0 0表示不参与dump备份和fsck磁盘检查网络文件系统也不需要。改完fstab后先别急着重启用下面这条命令测试一下sudo mount -a-a参数表示重新加载fstab里所有配置的挂载项同时检查语法错误。如果没报错再df -h确认挂载成功那重启后大概率也没问题。4.2 解决开机挂载失败的几个思路即使你fstab写得没错生产环境还是会遇到开机挂载失败的问题。我踩过几次坑之后总结出下面几个对策方案一让挂载变成“按需”触发在fstab挂载参数里加x-systemd.automount系统启动时不会真正挂载而是在你第一次访问挂载点目录时才触发网络挂载。这样既保证了开机速度快又不会被网络延迟卡住//192.168.1.100/shared /mnt/winshare cifs credentials/root/.smbcredentials,_netdev,x-systemd.automount 0 0注意启用了automount之后挂载点目录会由systemd接管你在df -h里可能看不到它直到你真正cd进去触发挂载。这对使用习惯上稍微有点影响但稳定性提升非常明显。方案二绑到network服务之后如果你用的是SysVinit老系统或者是手动管理服务的发行版可以在fstab参数里加_netdev的前提下把挂载点目录的systemd服务写成依赖network-online.target。不过现在主流发行版都是systemd上面说的x-systemd.automount更省事这里就不再展开了。方案三把凭据文件检查好开机自动挂载用的是root权限如果你把凭据文件放在普通用户家目录可能因为权限问题读不到。稳妥的做法是复制一份到/root/.smbcredentialschmod 600后引用它。我在生产环境里见过不少fstab写得很规范、但凭据文件放在用户目录导致systemd拿不到权限而挂载失败的情况。4.3 卸载共享目录的正确方式不使用了卸载也讲究手法。如果确认没有进程正在访问挂载点直接udo umount /mnt/winshare如果提示target is busy说明有进程打开了里面的文件。用lsof f -- /mnt/winshare或fuser -vm /mnt/winshare找到占用的进程结束后再卸载。千万不要贸然执行umount -l懒卸载虽然它会强制解除关联但这可能让正在读写文件的进程陷入异常。5. 常见问题排查实录挂载翻车现场5.1 问题速查表下面这张表是我整理的高频问题基本覆盖了绝大多数挂载失败场景错误/现象可能原因解决办法mount error(112): Host is down网络不通或Windows防火墙拦截445端口用nc -zv IP 445测端口检查防火墙mount error(13): Permission denied用户名/密码错误或Windows共享权限不足确认凭据文件内容检查Windows共享权限和NTFS权限mount error(2): No such file or directory共享名写错或服务器共享未开启在Windows上确认共享名注意大小写mount error(6): No such device or addressSMB协议版本过旧/过新或IP不可达显式指定vers2.0/vers3.0检查IP挂载成功但中文乱码字符集不匹配挂载参数加iocharsetutf8必要时cp936挂载成功但无法写入Linux侧uid/gid或file_mode限制指定uid用户UID,gid用户GID,file_mode0664,dir_mode0775挂载成功但目录内文件显示为?Windows侧文件名用了文件系统不支持的特殊字符检查Windows侧是否启用了“8.3文件名兼容”或特殊字符策略开机自动挂载一直失败网络未就绪、凭据文件权限错误加_netdev或x-systemd.automount检查凭据文件属主和权限大文件复制到一半断掉网络抖动、SMB连接超时增加hard参数保持重试检查网络质量5.2 权限映射问题为什么挂上了还是没权限这是初学者最容易卡住的地方。明明在Windows那边把Everyone读写权限都开了在Linux挂载点里touch一个文件却提示权限不够。原因在第三节解释过SMB的Windows ACL和Linux的POSIX权限不是一回事。你需要在挂载时用uid、gid指定远程资源在Linux侧对应的属主再用file_mode、dir_mode指定默认权限位。举例当前Linux用户叫devUID是1000我想让挂载目录里所有文件属主都显示为dev并且用户可读写、组可读、其他人不可读写挂载参数这样写-o uid1000,gid1000,file_mode0664,dir_mode0775注意file_mode和dir_mode是给所有远程文件/目录统一设置的默认权限如果你需要根据每个文件原本的权限来映射就需要启用noperm参数但那样做有安全风险不推荐在没有理解后果前使用。5.3 连接动不动断SMB连接的长期稳定性在长时间挂载的使用中你可能发现复制大文件到一半就报错或者隔一段时间用着用着目录变成“不可用”。这类问题多半出在两点一是网络层不稳定比如无线网络断流二是SMB协议层面的超时和会话过期。对策有几个挂载参数加hard当连接断开时系统会持续重试而不是直接报I/O错误。默认是soft会在数次重试后放弃。对重要业务hard更可靠但注意如果是NFS/SMB网络文件系统hard模式下请求会阻塞进程如果网络长期不可达进程会一直卡住。挂载参数加serverino或nobrl这两个参数解决的是文件句柄和锁的问题在某些跨平台使用场景下能减少莫名“文件被占用”的报错。考虑加actimeo这个参数控制目录和文件属性缓存的时间默认较保守。如果目录里的文件经常被远程改动适当调低actimeo比如actimeo1能更及时看到变化代价是更多的网络请求。5.4 终极排查手段看内核日志很多SMB挂载问题在报错信息里看不明白这时候别瞎猜直接用dmesg | tail -50 journalctl -k -f日志里会有关键信息比如CIFS VFS: cifs_mount failed w/return code -13—— 认证或权限失败对照上面表格第一条。CIFS VFS: Dialect not supported by server. Consider specifying vers—— 协议版本协商失败按提示指定版本。CIFS VFS: No response for cmd—— 网络问题一般是超时或对端断开。学会看内核日志排查效率能提升一个量级。6. 几个使用中的实用建议讲完技术最后分享几个细节习惯都是长期使用中体会比较深的。为Linux挂载专门建一个Windows账号并给它最小权限。别用管理员账号也别开Everyone完全控制。单独建一个账号只授予它需要共享的那些目录的访问权密码定期更换。这样即使账号泄露影响范围也可控。写fstab之前先备份。cp /etc/fstab /etc/fstab.bak一行命令的事但关键时刻能救你一命。改完fstab一定要用mount -a先验证别直接重启。优先用SMB 3.0以上协议。不仅性能更好安全性也高一个台阶。SMB 1.0能不用就不用它身上漏洞太多公网和内网都有被利用的先例。如果你必须连老系统建议在内网VLAN里隔离使用。如果只是偶尔临时传几个文件别急着挂载。一条scp命令或一个python3 -m http.server临时HTTP服务可能更快。挂载适合长期稳定使用的场景频繁挂载卸载反而浪费时间和网络开销。把这个技能往后延伸一点同样的机制在Linux与NAS、Linux与Linux之间也能用甚至容器里访问宿主机的共享也能走SMB。你把这套原理吃透了以后遇到任何“网络共享目录挂载”类的问题都能举一反三。我个人在实际操作中最大的体会是挂载Windows共享目录这个动作本身不复杂复杂的永远是对权限模型的理解以及在网络环境不友好时怎么定位问题和选对参数。你把uid/gid、vers、credentials、_netdev这几个关键点吃透就足够应对绝大多数场景了。下一次看到挂着挂着突然“不翼而飞”的情况先查网络再查协议版本再查权限一步一步来问题总能解决。
返回列表