You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js调用fs.copyFile在挂载目录复制文件报ENOTSUP socket错误如何解决

问题原因分析
  1. 待复制的文件列表中包含socket、命名管道、设备文件等特殊文件类型,Node.js原生fs.copyFile仅支持复制普通常规文件,无法处理这类特殊文件。
  2. 操作的目录属于网络挂载文件系统(如SMB、NFS、sshfs等),fs.copyFile底层默认调用的copy_file_range系统调用对跨挂载点、网络文件系统的兼容性较差,会触发该类报错。
  3. 原有代码存在逻辑问题:chmod修改的是源文件权限,如果你需要给目标文件设置777权限,需要改为修改目标路径的权限。
可行解决方案

方案1:先过滤特殊文件再复制

适用于文件列表混入特殊文件的场景,复制前先校验文件类型,仅处理普通文件:

const fs = require('fs/promises');
const path = require('path');

async ({ destDir, files }) => {
  return await Promise.all(
    files.map(async (filePath) => {
      const stat = await fs.lstat(filePath);
      // 只处理普通文件,跳过socket、目录、链接、管道等特殊文件
      if (!stat.isFile()) return;
      const fileName = path.basename(filePath);
      const destPath = path.join(destDir, fileName);
      await fs.copyFile(filePath, destPath);
      // 给目标文件设置777权限
      await fs.chmod(destPath, "777");
    })
  );
}

方案2:改用流方式复制文件

适用于网络挂载目录场景,规避copy_file_range系统调用的兼容性问题:

const fs = require('fs');
const path = require('path');
const { pipeline } = require('stream/promises');

async ({ destDir, files }) => {
  return await Promise.all(
    files.map(async (filePath) => {
      const stat = await fs.promises.lstat(filePath);
      if (!stat.isFile()) return;
      const fileName = path.basename(filePath);
      const destPath = path.join(destDir, fileName);
      // 用流复制,替代copyFile
      await pipeline(
        fs.createReadStream(filePath),
        fs.createWriteStream(destPath, { mode: 0o777 })
      );
    })
  );
}

如果需要确保权限生效,可在流复制完成后额外调用fs.chmod修改目标文件权限。

内容的提问来源于stack exchange,提问作者Valu3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 23:06:04