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属性 } });
警告截图

问题原因与解决方法
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
相关产品推荐
相关产品推荐

