排查 Linux 中的 Azure 文件存储问题 (SMB)

本文列出了在 Linux 客户端使用 SMB Azure 文件共享时可能发生的常见问题。 并提供了这些问题的可能原因和解决方法。

可以使用 AzFileDiagnostics 自动检测症状,并确保 Linux 客户端具有正确的先决条件。 它有助于设置环境以获得最佳性能。 也可以在 Azure 文件共享疑难解答中找到此信息。

重要

本文仅适用于 SMB 共享。 有关 NFS 共享的详细信息,请参阅排查 NFS Azure 文件共享问题

适用于

文件共享类型 SMB NFS
标准文件共享 (GPv2)、LRS/ZRS
标准文件共享 (GPv2)、GRS/GZRS
高级文件共享 (FileStorage)、LRS/ZRS

复制文件时,时间戳丢失

在 Linux/Unix 平台上,如果不同的用户拥有文件 1 和文件 2,命令 cp -p 将失败。

原因

COPYFILE 中的强制标志 f 会导致在 Unix 上执行 cp -p -f 。 此命令也无法保留不归你拥有的文件的时间戳。

解决方法

使用存储帐户用户复制文件:

  • str_acc_name=[storage account name]
  • sudo useradd $str_acc_name
  • sudo passwd $str_acc_name
  • su $str_acc_name
  • cp -p filename.txt /share

ls: cannot access '<path>':Input/output error

尝试使用 ls 命令列出 Azure 文件共享中的文件时,命令在列出文件时挂起。 收到以下错误:

ls: cannot access'<path>':Input/output error

解决方案

将 Linux 内核升级到以下可解决此问题的版本:

  • 4.4.87+
  • 4.9.48+
  • 4.12.11+
  • 4\.13 或更高的所有版本

原因

默认情况下,使用 SMB 在 Linux 上装载 Azure 文件共享不会启用符号链接的支持。 可能出现如下错误:

sudo ln -s linked -n t
ln: failed to create symbolic link 't': Operation not supported

解决方案

Linux SMB 客户端不支持通过 SSMB 2 或 3 协议创建 Windows 样式符号链接。 Linux 客户端目前支持使用称作 Minshall+French 符号链接的另一种样式的符号链接来执行创建和跟踪操作。 需要符号链接的客户可以使用“mfsymlinks”装载选项。 我们推建议使用“mfsymlinks”,因为这也是 Macs 使用的格式。

若要使用符号链接,请将以下代码添加到 SMB 装载命令的末尾:

,mfsymlinks

因此,该命令如下所示:

sudo mount -t cifs //<storage-account-name>.file.core.windows.net/<share-name> <mount-point> -o vers=<smb-version>,username=<storage-account-name>,password=<storage-account-key>,dir_mode=0777,file_mode=0777,serverino,mfsymlinks

然后,可以按照 wiki 上的建议创建符号链接。

无法访问名称末尾带有空格或点的文件夹或文件

装载在 Linux 上时,无法从 Azure 文件共享访问文件夹或文件。 诸如 du 和 ls 之类的命令和/或第三方应用程序在访问该共享时可能会失败并显示“无此类文件或目录”错误,但是你能够通过 Azure 门户将文件上传到这些文件夹。

原因

文件夹或文件是从一个将名称末尾的字符编码为另一字符的系统上传的。 从 Macintosh 计算机上传的文件可能有“0xF028”或“0xF029”字符,而不是“0x20”(空格)或“0X2E”(点)字符。

解决方案

在 Linux 上装载共享时,请在共享上使用 mapchars 选项:

不使用:

sudo mount -t cifs $smbPath $mntPath -o vers=3.0,username=$storageAccountName,password=$storageAccountKey,serverino

使用:

sudo mount -t cifs $smbPath $mntPath -o vers=3.0,username=$storageAccountName,password=$storageAccountKey,serverino,mapchars

Azure 存储帐户实时迁移的 DNS 问题

装载的文件系统上的文件 I/O 开始出现“主机故障”或“权限被拒绝”错误。 客户端上的 Linux dmesg 日志将显示重复的错误,例如:

Status code returned 0xc000006d STATUS_LOGON_FAILURE
cifs_setup_session: 2 callbacks suppressed
CIFS VFS: \\contoso.file.core.windows.net Send error in SessSetup = -13

你还将看到服务器 FQDN 现在解析为与当前连接到的 IP 地址不同的 IP 地址。 在服务器 IP 地址可以更改(例如帐户迁移)的任何方案中,都可能出现此问题。 另一个已知方案是存储帐户故障转移,因为 DNS 映射可能会更改。

原因

出于容量负载均衡目的,存储帐户有时会从一个存储群集实时迁移到另一个存储群集。 通过将 DNS 映射更新为指向目标群集,帐户迁移会触发 Azure 文件存储流量从源群集重定向到目标群集。 这会阻止从该帐户到源群集的所有流量。 预计 SMB 客户端会选取 DNS 更新,并将进一步的流量重定向到目标群集。 但是,由于 Linux SMB 内核客户端中的 bug,此重定向不会生效。 因此,数据流量会继续转到源群集,源群集在迁移后已停止处理此帐户。

解决方法

通过重新启动客户端 OS 可以缓解此问题,但如果不将客户端 OS 升级到具有帐户迁移支持的 Linux 发行版,则可能会再次遇到此问题。

虽然卸载和重新装载共享似乎暂时解决了该问题,但这不是永久的解决方案。 当客户端重新连接到服务器时,可能会再次出现问题。 出现临时缓解是因为新的装载操作会绕过 SMB 内核缓存并解析用户空间中的 DNS 地址。 但是,内核 DNS 缓存在任何网络断开连接恢复期间都使用,这可能会导致问题再次出现。 即使在存储帐户迁移之外,此行为也会持续存在。

若要更好地解决此问题,请清除内核 DNS 解析程序缓存:

  1. 运行以下命令显示内核 dns_resolver 模块的状态:

    grep '.dns_resolver' /proc/keys
    

    应会看到类似于以下示例的命令输出:

    132b6bbf I------     1 perm 1f030000     0     0 keyring   .dns_resolver: 1
    
  2. 运行以下命令清除内核 DNS 解析程序缓存:

    sudo keyctl clear $((16#$(grep '.dns_resolver' /proc/keys | cut -f1 -d\ ) ))
    
  3. 再次显示内核 dns_resolver 模块的状态:

    grep '.dns_resolver' /proc/keys
    

    应会看到类似于以下示例的命令输出,指示缓存现在为空:

    132b6bbf I------     1 perm 1f030000     0     0 keyring   .dns_resolver: empty
    
  4. 卸载并重新装载共享以缓解此问题。

注意

在某些较旧的 Linux 发行版中,上述缓解步骤可能不起作用。 在这种情况下,重新启动客户端 OS 是唯一已知的缓解措施。

解决方案

要进行永久修复,请将客户端 OS 升级到具有帐户迁移支持的 Linux 发行版。 已将 Linux SMB 内核客户端的几个修补程序提交到主线 Linux 内核。 以下发行版具有修补程序:

  • Ubuntu:20.04、22.04、24.04 和 AKS 22.04(修补程序已在内核版本 5.15.0-1068 中推出)
  • RHEL:8.6+
  • SLES:15SP2、15SP3、15SP4 和 15SP5
  • Azure Linux:2.0(在内核版本 5.15.159.1 中推出修补程序)和 3.0

一些发行版已向后移植这些修补程序。 可以检查正在使用的发行版版本中是否存在以下修补程序:

启用 FIPS 时无法装载 SMB 文件共享

在 Linux VM 中启用联邦信息处理标准(FIPS),无法装载 SMB 文件共享。 客户端上的 Linux dmesg 日志显示错误,例如:

kernel: CIFS: VFS: Could not allocate crypto hmac(md5)
kernel: CIFS: VFS: Error -2 during NTLMSSP authentication
kernel: CIFS: VFS: \\contoso.file.core.windows.net Send error in SessSetup = -2
kernel: CIFS: VFS: cifs_mount failed w/return code = -2

重要

FIPS 是美国政府用来确保计算机系统安全性和完整性的一套标准。 当系统处于 FIPS 模式时,它遵循这些标准概述的特定加密要求。

原因

SMB 文件共享的客户端使用 NTLMSSP 身份验证,这需要 MD5 哈希算法。 但是,在 FIPS 模式下,MD5 算法受到限制,因为它不符合 FIPS。 MD5 是一个广泛使用的哈希函数,用于生成 128 位哈希值。 但是,出于加密目的,MD5 被视为不安全。

如何检查是否已启用 FIPS 模式

若要验证是否已在客户端上启用 FIPS 模式,请运行以下命令。 如果该值设置为 1,则启用 FIPS。

sudo cat /proc/sys/crypto/fips_enabled

解决方案

若要解决此问题,请为 SMB 文件共享启用 Kerberos 身份验证。 如果无意中启用了 FIPS,请参阅 option2 将其禁用。

选项 1:为 SMB 文件共享启用 Kerberos 身份验证

若要在启用了 FIPS 的 Linux VM 上装载 SMB 文件共享,请使用 Kerberos/Azure AD 身份验证。 有关详细信息,请参阅通过 SMB 为访问 Azure 文件存储的 Linux 客户端启用 Active Directory 身份验证

选项 2:禁用 FIPS 以装载 Samba 共享

  1. 将 sysctl 值crypto.fips_enabled更改为 0。/etc/sysctl.conf

  2. GRUB_CMDLINE_LINUX_DEFAULT修改文件中/etc/default/grub的参数并删除参数fips=1

  3. 使用以下命令重新生成 grub2 配置文件:

    sudo grub2-mkconfig -o /boot/grub2/grub.cfg
    
  4. 使用以下命令重新生成 initramfs 映像:

    sudo dracut -fv
    
  5. 重启 VM。

有关详细信息,请参阅 Linux 分发服务器提供的以下文档:

需要帮助?

如果仍需帮助,请联系支持人员,以快速解决问题。

另请参阅

联系我们寻求帮助

如果你有任何疑问或需要帮助,请创建支持请求联系 Azure 社区支持。 你还可以将产品反馈提交到 Azure 反馈社区