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

Discord机器人出现“垃圾回收时关闭文件描述符3”警告求助

Discord机器人文件上传线程时出现“垃圾回收时关闭文件描述符3”警告的解决方法

我编写了一段Discord机器人的JavaScript代码,预期功能是读取指定文件夹中的所有文件,为每个文件创建一个Discord论坛线程并将文件上传至线程中。但运行代码时,出现了“垃圾回收时关闭文件描述符3”的警告。我尝试自行排查解决,但不确定如何修复该警告,甚至不知道如何忽略它,希望有人能提供相关信息、解决方法或忽略该警告的方案。

原代码

const { Client, Discord, GatewayIntentBits,  } = require('discord.js');
const fs = require('fs').promises;
const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
    GatewayIntentBits.GuildMembers,
    GatewayIntentBits.GuildModeration,
    GatewayIntentBits.GuildMembers, // 重复注册的意图
    GatewayIntentBits.AutoModerationConfiguration,
  ]
})
//const thread = '1099921205324173332'; // Replace with your channel ID

client.on('ready', () => {
  console.log(`Logged in as ${client.user.tag}!`);
});

client.on('messageCreate', async message => {
  // Check if the message author is the bot
  if (message.author.bot) return;

  // Check if the message contains the !upload command
  if (message.content.startsWith('!upload')) {
    // Get the directory path from the message content
    const dirPath = message.content.split(' ')[1];
    thread = "1099921205324173332"; // 未声明的全局变量
    // Check if the directory exists
    if (fs.open(dirPath) && fs.lstat(dirPath)) { // 异步方法直接判断,逻辑错误
      
      // The directory exists, so read all the files in the directory
      const fileNames = fs.readdir(dirPath); // 未加await,拿到的是Promise

      // Loop through each file and upload it to the channel
      for (let fileName of Object.values(fileNames)) { // 错误遍历Promise对象
        
       // const filePath = `${dirPath}/${fileName}`;
      //  const buffer = fs.readFileSync(filePath); // 同步方法和fs.promises混用
        GuildForumMessageRequired = 'GuildForumMessageRequired' // 未声明的全局变量
       {
      const threadChannel = message.guild.channels.cache.find(channel => channel.name === 'test'); // 用name找频道易出错
      threadChannel.threads.create({
        name: fileName.name, // fileName是字符串,没有name属性
        autoArchiveDuration: 60,
        type: 'GUILD_PUBLIC_THREAD',
         message: {
          content: `New thread created with file:` ,
          files: [fileName] // 直接传文件名,不是正确的文件对象
          },
     
      })}
        console.log(`Uploaded ${fileName} to ${message.channel.name}`);
      }
    }
     else 
     {
      // If the directory doesn't exist, send an error message
      message.reply('The specified directory does not exist.');
    }
  console.log(`Created thread: ${thread.name}`); // thread是字符串,没有name属性
  }
});

警告截图

垃圾回收时关闭文件描述符3警告


问题原因与解决方法

1. 核心问题:文件描述符泄漏

警告的本质是异步文件操作未正确等待完成,导致文件资源未被主动关闭,最终由垃圾回收器强制关闭。原代码中大量使用fs.promises方法却未加await,异步逻辑混乱,文件句柄无法正常释放。

2. 分步修复代码

(1)修正异步逻辑,所有fs.promises方法加await

(2)正确检查目录存在性(用try-catch处理异常)

(3)构造正确的文件上传对象

(4)修复变量声明与频道查找逻辑

修复后的完整代码:

const { Client, GatewayIntentBits } = require('discord.js');
const fs = require('fs').promises;
const path = require('path'); // 引入path模块处理路径

// 论坛频道ID(建议用ID而非name,避免重名)
const FORUM_CHANNEL_ID = '1099921205324173332';

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
    GatewayIntentBits.GuildMembers,
    GatewayIntentBits.GuildModeration,
    GatewayIntentBits.AutoModerationConfiguration,
  ]
});

client.on('ready', () => {
  console.log(`Logged in as ${client.user.tag}!`);
});

client.on('messageCreate', async message => {
  if (message.author.bot) return;

  if (message.content.startsWith('!upload')) {
    const dirPath = message.content.split(' ')[1];
    if (!dirPath) {
      return message.reply('请指定要上传的文件夹路径!');
    }

    try {
      // 检查目录是否存在且是文件夹
      const stats = await fs.lstat(dirPath);
      if (!stats.isDirectory()) {
        return message.reply('指定的路径不是文件夹!');
      }

      // 读取文件夹内的所有文件
      const fileNames = await fs.readdir(dirPath);
      const forumChannel = message.guild.channels.cache.get(FORUM_CHANNEL_ID);
      
      if (!forumChannel) {
        return message.reply('找不到目标论坛频道!');
      }

      // 遍历文件创建线程并上传
      for (const fileName of fileNames) {
        const filePath = path.join(dirPath, fileName);
        // 确保是文件而非子文件夹
        const fileStats = await fs.lstat(filePath);
        if (fileStats.isFile()) {
          try {
            await forumChannel.threads.create({
              name: fileName,
              autoArchiveDuration: 60,
              message: {
                content: `新线程:${fileName}`,
                files: [{
                  attachment: filePath,
                  name: fileName
                }]
              }
            });
            console.log(`已为文件${fileName}创建线程并上传`);
          } catch (threadErr) {
            console.error(`创建线程失败:${threadErr.message}`);
            message.reply(`文件${fileName}上传失败:${threadErr.message}`);
          }
        }
      }
      message.reply('所有文件处理完成!');
    } catch (err) {
      console.error(`文件夹处理失败:${err.message}`);
      message.reply(`文件夹不存在或无法访问:${err.message}`);
    }
  }
});

// 记得添加登录代码
// client.login('你的机器人Token');

3. 忽略警告的临时方案(不推荐)

如果只是想临时屏蔽该警告,可以在代码开头添加:

// 屏蔽所有警告(不推荐,会错过其他重要问题)
process.removeAllListeners('warning');

// 或仅屏蔽特定警告(更安全)
process.on('warning', (warning) => {
  if (warning.message.includes('Closing file descriptor 3 on garbage collection')) {
    return;
  }
  console.warn(warning);
});

注意:忽略警告只是治标不治本,文件描述符泄漏可能导致程序运行一段时间后出现资源耗尽问题,建议优先修复代码逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:24:54