diff --git a/server/.eslintrc.js b/server/.eslintrc.js index 7aa2cca..d60d29d 100644 --- a/server/.eslintrc.js +++ b/server/.eslintrc.js @@ -1,7 +1,7 @@ // 规则参见:https://cn.eslint.org/docs/rules/ module.exports = { root: true, // 当前配置文件不能往父级查找 - 'globals': { 'consola': true }, + 'globals': { 'logger': true }, env: { node: true, es6: true diff --git a/server/app/config/index.js b/server/app/config/index.js index 075bde5..06be6fe 100644 --- a/server/app/config/index.js +++ b/server/app/config/index.js @@ -1,7 +1,5 @@ const path = require('path') -consola.info('debug日志:', process.env.DEBUG === '1' ? '开启' : '关闭') - module.exports = { httpPort: 8082, uploadDir: path.join(process.cwd(),'app/db'), @@ -28,6 +26,6 @@ module.exports = { apiPrefix: '/api/v1', logConfig: { outDir: path.join(process.cwd(),'./app/db/logs'), - recordLog: process.env.DEBUG === '1' // 是否记录日志 + DEBUG: process.env.DEBUG === '1' || process.env.DEBUG === 'true' // 是否记录日志 } } diff --git a/server/app/controller/host.js b/server/app/controller/host.js index a66bd2c..af14cda 100644 --- a/server/app/controller/host.js +++ b/server/app/controller/host.js @@ -14,7 +14,7 @@ async function getHostList({ res }) { const isConfig = Boolean(authType && item[authType]) Object.assign(item, { id, isConfig, password: '', privateKey: '', credential }) } catch (error) { - consola.error('getHostList error: ', error.message) + logger.error('getHostList error: ', error.message) } } res.success({ data }) diff --git a/server/app/controller/plus.js b/server/app/controller/plus.js index 81bc550..98fbfe8 100644 --- a/server/app/controller/plus.js +++ b/server/app/controller/plus.js @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/server/app/controller/ssh.js b/server/app/controller/ssh.js index d9d805e..26c999e 100644 --- a/server/app/controller/ssh.js +++ b/server/app/controller/ssh.js @@ -30,7 +30,7 @@ const addSSH = async ({ res, request }) => { record[authType] = await AESEncryptAsync(clearSSHKey) // console.log(`${ authType }__commonKey加密存储: `, record[authType]) await credentialsDB.insertAsync({ ...record, date: Date.now() }) - consola.info('添加凭证:', name) + logger.info('添加凭证:', name) res.success({ data: '保存成功' }) } @@ -54,7 +54,7 @@ const updateSSH = async ({ res, request }) => { // console.log(`${ authType }__commonKey加密存储: `, record[authType]) } await credentialsDB.updateAsync({ _id: id }, record) - consola.info('修改凭证:', name) + logger.info('修改凭证:', name) res.success({ data: '保存成功' }) } @@ -75,7 +75,7 @@ const removeSSH = async ({ res, request }) => { } } await hostListDB.compactDatafileAsync() - consola.info('移除凭证:', id) + logger.info('移除凭证:', id) await credentialsDB.removeAsync({ _id: id }) res.success({ data: '移除成功' }) } @@ -85,7 +85,7 @@ const getCommand = async ({ res, request }) => { if (!hostId) return res.fail({ data: false, msg: '参数错误' }) let hostInfo = await hostListDB.findAsync({}) let record = hostInfo?.find(item => item._id === hostId) - consola.info('查询登录后执行的指令:', hostId) + logger.info('查询登录后执行的指令:', hostId) if (!record) return res.fail({ data: false, msg: 'host not found' }) const { command } = record if (!command) return res.success({ data: false }) diff --git a/server/app/controller/user.js b/server/app/controller/user.js index e4e27e5..6a76c4e 100644 --- a/server/app/controller/user.js +++ b/server/app/controller/user.js @@ -82,7 +82,7 @@ const login = async ({ res, request }) => { const beforeLoginHandler = async (clientIp, jwtExpires) => { loginErrCount = loginErrTotal = 0 // 登录成功, 清空错误次数 - // consola.success('登录成功, 准备生成token', new Date()) + logger.info('登录成功, 准备生成token') // 生产token let { commonKey, user } = await keyDB.findOneAsync({}) let token = jwt.sign({ date: Date.now() }, `${ user }-${ commonKey }`, { expiresIn: jwtExpires }) // 生成token @@ -91,7 +91,7 @@ const beforeLoginHandler = async (clientIp, jwtExpires) => { // 记录客户端登录IP(用于判断是否异地且只保留最近10次) const clientIPInfo = await getNetIPInfo(clientIp) const { ip, country, city } = clientIPInfo || {} - consola.info('登录成功:', new Date(), { ip, country, city }) + logger.info('登录成功:', new Date(), { ip, country, city }) // 登录通知 sendNoticeAsync('login', '登录提醒', `地点:${ country + city }\nIP: ${ ip }`) @@ -122,7 +122,7 @@ const getEasynodeVersion = async ({ res }) => { const { data } = await axios.get('https://get-easynode-latest-version.chaoszhu.workers.dev/version') res.success({ data, msg: 'success' }) } catch (error) { - consola.error('Failed to fetch Easynode latest version:', error) + logger.error('Failed to fetch Easynode latest version:', error) res.fail({ msg: 'Failed to fetch Easynode latest version' }) } } @@ -155,7 +155,7 @@ const enableMFA2 = async ({ res, request }) => { await keyDB.updateAsync({ _id: keyConfig._id }, { $set: keyConfig }) res.success({ msg: '验证成功' }) } catch (error) { - consola.error('MFA2验证失败:', error.message) + logger.error('MFA2验证失败:', error.message) res.fail({ msg: `验证失败: ${ error.message }` }) } } @@ -178,7 +178,7 @@ const disableMFA2 = async ({ res, request }) => { await keyDB.updateAsync({ _id: keyConfig._id }, { $set: keyConfig }) res.success({ msg: '禁用成功' }) } catch (error) { - consola.error('禁用MFA2失败:', error.message) + logger.error('禁用MFA2失败:', error.message) res.fail({ msg: `禁用失败: ${ error.message }` }) } } @@ -202,11 +202,11 @@ const getPlusDiscount = async ({ res } = {}) => { } // 如果是403或其他错误状态码 - consola.error('获取折扣信息失败,状态码:', response.status) + logger.error('获取折扣信息失败,状态码:', response.status) return res.success({ discount: false }) } catch (error) { - consola.error('获取折扣信息失败:', error.message) + logger.error('获取折扣信息失败:', error.message) return res.success({ discount: false }) } } diff --git a/server/app/db.js b/server/app/db.js index 54c1a48..6f7690a 100644 --- a/server/app/db.js +++ b/server/app/db.js @@ -10,7 +10,7 @@ async function initKeyDB() { const { _id, ipWhiteList = [] } = keyData let allowedIPs = process.env.ALLOWED_IPS ? process.env.ALLOWED_IPS.split(',') : [] if (allowedIPs.length > 0) { - consola.info('[存在白名单IP环境变量,合并到本地数据库中]') + logger.info('[存在白名单IP环境变量,合并到本地数据库中]') allowedIPs = [...new Set([...ipWhiteList, ...allowedIPs])].filter(item => item) await keyDB.updateAsync({ _id }, { $set: { ipWhiteList: allowedIPs } }) } @@ -18,9 +18,9 @@ async function initKeyDB() { let { ipWhiteList = [] } = await keyDB.findOneAsync({}) if (ipWhiteList.length > 0) global.ALLOWED_IPS = ipWhiteList } catch (error) { - consola.error('设置全局IP白名单失败:', error) + logger.error('设置全局IP白名单失败:', error) } - consola.info('公私钥已存在[重新生成会导致已保存的ssh密钥信息失效]') + logger.info('公私钥已存在[重新生成会导致已保存的ssh密钥信息失效]') return } @@ -44,20 +44,19 @@ async function initKeyDB() { await keyDB.updateAsync({}, { $set: newConfig }, { upsert: true }) // 在控制台打印随机生成的账号密码 - consola.info('========================================') - consola.info('EasyNode 默认登录凭据 (请及时更改):') - consola.info(`用户名: ${ randomUsername }`) - consola.info(`密码: ${ randomPassword }`) - consola.info('========================================') + logger.info('========================================') + logger.info('EasyNode 默认登录凭据 (请及时更改):') + logger.info(`用户名: ${ randomUsername }`) + logger.info(`密码: ${ randomPassword }`) + logger.info('========================================') - consola.info('Task: 已生成新的非对称加密公私钥') } async function initGroupDB() { const groupDB = new GroupDB().getInstance() let count = await groupDB.countAsync({}) if (count === 0) { - consola.log('初始化groupDB✔') + logger.info('初始化groupDB✔') const defaultData = [{ '_id': 'default', 'name': '默认分组', 'index': 0 }] return groupDB.insertAsync(defaultData) } @@ -68,7 +67,7 @@ async function initNotifyDB() { const notifyDB = new NotifyDB().getInstance() let count = await notifyDB.countAsync({}) if (count !== 0) return - consola.log('初始化notifyDB✔') + logger.info('初始化notifyDB✔') let defaultData = [{ 'type': 'login', 'desc': '登录面板提醒', @@ -100,7 +99,7 @@ async function initNotifyDB() { async function initNotifyConfigDB() { const notifyConfigDB = new NotifyConfigDB().getInstance() let notifyConfig = await notifyConfigDB.findOneAsync({}) - consola.log('初始化NotifyConfigDB✔') + logger.info('初始化NotifyConfigDB✔') const defaultData = { type: 'sct', sct: { @@ -128,7 +127,7 @@ async function initScriptGroupDB() { const scriptGroupDB = new ScriptGroupDB().getInstance() let count = await scriptGroupDB.countAsync({}) if (count === 0) { - consola.log('初始化ScriptGroupDB✔') + logger.info('初始化ScriptGroupDB✔') const defaultData = [ { '_id': 'default', 'name': '默认分组', 'index': 0 }, { '_id': 'builtin', 'name': '内置脚本', 'index': -1 } diff --git a/server/app/logs.js b/server/app/logs.js new file mode 100644 index 0000000..6f543f4 --- /dev/null +++ b/server/app/logs.js @@ -0,0 +1,29 @@ +const log4js = require('log4js') +const { outDir } = require('./config').logConfig +log4js.configure({ + appenders: { + console: { + type: 'stdout', + layout: { + type: 'pattern', + pattern: '%[%d{yyyy-MM-dd hh:mm:ss.SSS} [%p] -%] %m' + } + }, + file: { + type: 'file', + maxLogSize: 10 * 1024 * 10, // 10MB + filename: `${ outDir }/debug.log`, + backups: 10, + compress: true, + keepFileExt: true + } + }, + categories: { + default: { + appenders: ['console', 'file'], + level: 'debug' + } + } +}) +const logger = log4js.getLogger() +global.logger = logger \ No newline at end of file diff --git a/server/app/main.js b/server/app/main.js index fc1dc6c..d177949 100644 --- a/server/app/main.js +++ b/server/app/main.js @@ -1,3 +1,4 @@ +require('./logs') const { httpServer } = require('./server') const initDB = require('./db') const scheduleJob = require('./schedule') diff --git a/server/app/middlewares/auth.js b/server/app/middlewares/auth.js index e15962a..1cf487e 100644 --- a/server/app/middlewares/auth.js +++ b/server/app/middlewares/auth.js @@ -5,11 +5,11 @@ let whitePath = [ '/login', '/get-pub-pem' ].map(item => (apiPrefix + item)) -consola.info('路由白名单:', whitePath) +logger.warn('路由白名单:', whitePath) const useAuth = async ({ request, res }, next) => { const { path, headers: { token, uid } } = request - // consola.info('verify path: ', path) + logger.info('verify path: ', path) if (whitePath.includes(path)) return next() if (!token) return res.fail({ msg: '未登录(token)', status: 401 }) if (!uid) return res.fail({ msg: '未登录(uid)', status: 401 }) @@ -23,7 +23,7 @@ const useAuth = async ({ request, res }, next) => { case enumLoginCode.ERROR_TOKEN: return res.fail({ msg: 'TOKEN校验失败, 请重新登录', status: 401 }) case enumLoginCode.ERROR_UID: - consola.warn('用户id校验失败(可能存在外部攻击): ', path) + logger.error('用户id校验失败(可能存在外部攻击): ', path) return res.fail({ msg: 'UID错误!!!', status: 403 }) } } diff --git a/server/app/middlewares/index.js b/server/app/middlewares/index.js index 949d7c8..b116917 100644 --- a/server/app/middlewares/index.js +++ b/server/app/middlewares/index.js @@ -2,7 +2,7 @@ const ipFilter = require('./ipFilter') // IP过滤 const responseHandler = require('./response') // 统一返回格式, 错误捕获 const useAuth = require('./auth') // 鉴权 // const useCors = require('./cors') // 处理跨域[暂时禁止] -const useLog = require('./log4') // 记录日志,需要等待路由处理完成,所以得放路由前 +const useLog = require('./useLog') // 记录日志,需要等待路由处理完成,所以得放路由前 const useKoaBody = require('./body') // 处理body参数 【请求需先走该中间件】 const { useRoutes, useAllowedMethods } = require('./router') // 路由管理 const useStatic = require('./static') // 静态目录 diff --git a/server/app/middlewares/log4.js b/server/app/middlewares/log4.js deleted file mode 100644 index aeee7f4..0000000 --- a/server/app/middlewares/log4.js +++ /dev/null @@ -1,62 +0,0 @@ -const log4js = require('log4js') -const { outDir, recordLog } = require('../config').logConfig - -log4js.configure({ - appenders: { - console: { - type: 'stdout', - layout: { - type: 'pattern', - pattern: '%[%d{yyyy-MM-dd hh:mm:ss.SSS} [%p] -%] %m' - } - }, - cheese: { - type: 'file', - maxLogSize: 10 * 1024 * 1024, // unit: bytes 1KB = 1024bytes - filename: `${ outDir }/debug.log`, - backups: 10, - compress: true, - keepFileExt: true - } - }, - categories: { - default: { - appenders: ['console', 'cheese'], - level: 'debug' - } - } -}) - -const logger = log4js.getLogger() - -const useLog = () => { - return async (ctx, next) => { - const { method, path, origin, query, body, headers, ip } = ctx.request - const data = { - method, - path, - origin, - query, - body, - ip, - headers - } - await next() // 等待路由处理完成,再开始记录日志 - // 是否记录日志 - if (recordLog) { - const { status, params } = ctx - data.status = status - data.params = params - data.result = ctx.body || 'no content' - if (String(status).startsWith(4) || String(status).startsWith(5)) - logger.error(JSON.stringify(data)) - else - logger.info(JSON.stringify(data)) - } - } -} - -module.exports = useLog() - -// 可以先测试一下日志是否正常工作 -logger.info('日志系统启动') \ No newline at end of file diff --git a/server/app/middlewares/rdp-proxy.js b/server/app/middlewares/rdp-proxy.js index 7977905..aebe289 100644 --- a/server/app/middlewares/rdp-proxy.js +++ b/server/app/middlewares/rdp-proxy.js @@ -9,11 +9,11 @@ const createRdpProxyMiddleware = () => { const RDP_HOST = process.env.RDP_HOST || '127.0.0.1' // 使用127.0.0.1更可靠 const target = `http://${ RDP_HOST }:${ RDP_PORT }` - console.log('Creating RDP proxy middleware with target:', target) + logger.info('创建RDP代理转发:', target) // 创建WebSocket代理 const wsProxy = createProxyMiddleware({ - target: target, + target, ws: true, changeOrigin: true, pathRewrite: { diff --git a/server/app/middlewares/response.js b/server/app/middlewares/response.js index 67f2091..1c54d7d 100644 --- a/server/app/middlewares/response.js +++ b/server/app/middlewares/response.js @@ -23,7 +23,7 @@ const responseHandler = async (ctx, next) => { await next() // 每个中间件都需等待next完成调用,不然会返回404给前端!!! } catch (err) { console.dir(err) - consola.error('中间件错误:', err) + logger.error('中间件错误:', err) if (err.status) ctx.res.fail({ status: err.status, msg: err.message }) // 自己主动抛出的错误 throwError else diff --git a/server/app/middlewares/useLog.js b/server/app/middlewares/useLog.js new file mode 100644 index 0000000..b81ed3e --- /dev/null +++ b/server/app/middlewares/useLog.js @@ -0,0 +1,169 @@ +// log4.js +const { DEBUG } = require('../config').logConfig + +// ------------------ 脱敏 ------------------ +// 可能包含敏感信息的 header key(小写比较) +const SENSITIVE_HEADER_KEYS = ['authorization', 'cookie', 'token', 'uid'] +// 需要打码的 body 字段(小写比较) +const SENSITIVE_BODY_KEYS = [ + 'password', 'pwd', 'code', 'captcha', 'token', + 'oldloginname', 'oldpwd', 'newloginname', 'newpwd', + 'loginname', 'ciphertext', 'jwtexpires', 'mfa2token' +] + +const MAX_BODY_LOG_LEN = 1000 // 请求 body 最多记录长度 +const MAX_RESULT_LOG_LEN = 1000 // 响应体最多记录长度 + +function maskSensitiveHeaders(headers = {}) { + const safeHeaders = {} + for (const [key, value] of Object.entries(headers)) { + const lowerKey = key.toLowerCase() + if (SENSITIVE_HEADER_KEYS.includes(lowerKey)) { + safeHeaders[key] = '[MASKED]' + } else { + safeHeaders[key] = value + } + } + return safeHeaders +} + +function maskSensitiveBody(body) { + if (!body || typeof body !== 'object') return body + + // 简单深拷贝 + 递归打码 + const clone = Array.isArray(body) ? [] : {} + for (const [key, value] of Object.entries(body)) { + const lowerKey = key.toLowerCase() + + if (SENSITIVE_BODY_KEYS.includes(lowerKey)) { + clone[key] = '[MASKED]' + } else if (value && typeof value === 'object') { + clone[key] = maskSensitiveBody(value) + } else { + clone[key] = value + } + } + + return clone +} + +function truncateString(str, maxLen) { + if (typeof str !== 'string') return str + if (!maxLen || str.length <= maxLen) return str + return str.slice(0, maxLen) + '... [truncated]' +} + +function safeStringify(obj, maxLen) { + try { + const json = JSON.stringify(obj) + return truncateString(json, maxLen) // 避免循环引用 + } catch (e) { + return '[Unserializable object]' + } +} + +// 格式化请求 body,用于写入日志 +function formatBodyForLog(body) { + if (!body) return 'no body' + + // 如果是字符串,直接截断 + if (typeof body === 'string') { + return truncateString(body, MAX_BODY_LOG_LEN) + } + + // 其它类型(对象、数组等)先脱敏再 stringify + const masked = maskSensitiveBody(body) + return safeStringify(masked, MAX_BODY_LOG_LEN) +} + +// 格式化响应 result,用于写入日志 +function formatResultForLog(result) { + if (result === null) return 'no content' + + // 字符串直接截断 + if (typeof result === 'string') { + return truncateString(result, MAX_RESULT_LOG_LEN) + } + + // Buffer + if (Buffer.isBuffer(result)) { + return `[buffer length=${ result.length }]` + } + + // Stream(简单判断) + if (result && typeof result.pipe === 'function') { + return '[stream]' + } + + // 其它对象,直接 stringify 截断 + return safeStringify(result, MAX_RESULT_LOG_LEN) +} + +const useLog = () => { + return async (ctx, next) => { + const { + method, + path, + origin, + query, + body, + headers, + ip + } = ctx.request + + const start = Date.now() + + // 先让后续中间件 / 路由处理 + try { + await next() + } catch (err) { + ctx._logError = err + throw err + } finally { + // eslint-disable-next-line no-unsafe-finally + if (!DEBUG) return + + const cost = Date.now() - start + + const logData = { + method, + path, + origin, + ip, + query, + cost, // 花费时间 ms + headers: maskSensitiveHeaders(headers), + body: formatBodyForLog(body), + status: ctx.status, + params: ctx.params, + result: formatResultForLog(ctx.body) + } + + // 如果有未捕获异常,可以顺带记一下 + if (ctx._logError) { + logData.error = { + message: ctx._logError.message, + stack: ctx._logError.stack + } + } + + // 状态码分级:5xx error,4xx warn,其它 info + const status = Number(ctx.status) || 0 + const text = safeStringify(logData) + + try { + if (status >= 500) { + logger.error(text) + } else if (status >= 400) { + logger.warn(text) + } else { + logger.info(text) + } + } catch (e) { + logger.error('记录日志时发生错误', e) + } + } + } +} + +module.exports = useLog() diff --git a/server/app/rdp-server.js b/server/app/rdp-server.js index c4abe02..7b71b45 100644 --- a/server/app/rdp-server.js +++ b/server/app/rdp-server.js @@ -30,18 +30,18 @@ const startRdpServer = () => { const guacamole = new GuacamoleLite(websocketOptions, guacdOptions, clientOptions) guacamole.on('connection', () => { - consola.success('✔ RDP guacamole连接成功') + logger.info('✔ RDP guacamole连接成功') }) guacamole.on('error', (err) => { - consola.error('❌ RDP guacamole连接错误', err) + logger.error('❌ RDP guacamole连接错误', err) }) rdpServer.listen(RDP_PORT, () => { - consola.success(`RDP服务运行在端口: ${ RDP_PORT }`) + logger.info(`RDP服务运行在端口: ${ RDP_PORT }`) }) } catch (error) { - consola.error('❌ RDP 初始化失败:', error.message) + logger.error('❌ RDP 初始化失败:', error.message) } } diff --git a/server/app/schedule/index.js b/server/app/schedule/index.js index 275dd64..da85aa1 100644 --- a/server/app/schedule/index.js +++ b/server/app/schedule/index.js @@ -5,7 +5,7 @@ const { HostListDB } = require('../utils/db-class') const hostListDB = new HostListDB().getInstance() const expiredNotifyJob = async () => { - consola.info('=====开始检测服务器到期时间=====', new Date()) + logger.info('=====开始检测服务器到期时间=====', new Date()) const hostList = await hostListDB.findAsync({}) for (const item of hostList) { if (!item.expiredNotify) continue diff --git a/server/app/server.js b/server/app/server.js index 095e008..d9ec30c 100644 --- a/server/app/server.js +++ b/server/app/server.js @@ -31,7 +31,7 @@ const httpServer = () => { // ws一直报跨域的错误:参照官方文档使用createServer API创建服务 server.listen(httpPort, () => { - consola.success(`Server(http) is running on: http://localhost:${ httpPort }`) + logger.info(`Server(http) is running on: http://localhost:${ httpPort }`) }) // 启动独立的RDP服务 diff --git a/server/app/socket/docker.js b/server/app/socket/docker.js index 4da6470..e272bfc 100644 --- a/server/app/socket/docker.js +++ b/server/app/socket/docker.js @@ -17,7 +17,7 @@ function executeDockerLogsCommand(targetSSHClient, command) { return new Promise((resolve, reject) => { targetSSHClient.exec(command, (err, stream) => { if (err) { - consola.error('执行Docker logs命令失败:', err) + logger.error('执行Docker logs命令失败:', err) return reject(err) } @@ -27,12 +27,12 @@ function executeDockerLogsCommand(targetSSHClient, command) { stream.on('close', () => { // code // Docker logs 的输出主要在 stderr,合并所有输出 const allData = stdoutData + stderrData - // consola.info(`Docker logs 命令完成, 退出码: ${ code }, 输出长度: ${ allData.length }`) + // logger.info(`Docker logs 命令完成, 退出码: ${ code }, 输出长度: ${ allData.length }`) if (allData.trim()) { resolve(allData) } else { - consola.warn('Docker logs 无输出:', command) + logger.warn('Docker logs 无输出:', command) resolve('') } }) @@ -46,7 +46,7 @@ function executeDockerLogsCommand(targetSSHClient, command) { }) stream.on('error', (err) => { - consola.error('Docker logs stream 错误:', err) + logger.error('Docker logs stream 错误:', err) reject(err) }) }) @@ -140,7 +140,7 @@ module.exports = (httpServer) => { return } connectionCount++ - consola.success(`docker websocket 已连接 - 当前连接数: ${ connectionCount }`) + logger.info(`docker websocket 已连接 - 当前连接数: ${ connectionCount }`) let targetSSHClient = null let jumpSshClients = [] @@ -197,7 +197,7 @@ module.exports = (httpServer) => { jumpSshClients?.forEach(sshClient => sshClient && sshClient.end()) targetSSHClient = null jumpSshClients = null - consola.info(`docker websocket 连接断开: ${ reason } - 当前连接数: ${ connectionCount }`) + logger.info(`docker websocket 连接断开: ${ reason } - 当前连接数: ${ connectionCount }`) }) }) } diff --git a/server/app/socket/file-transfer.js b/server/app/socket/file-transfer.js index 2410e00..e7c83ad 100644 --- a/server/app/socket/file-transfer.js +++ b/server/app/socket/file-transfer.js @@ -1,7 +1,6 @@ const path = require('path') const { Server } = require('socket.io') const { Client: SSHClient } = require('ssh2') -const consola = require('consola') const { verifyAuthSync } = require('../utils/verify-auth') const { isAllowedIp, fileTransferThrottle } = require('../utils/tools') const { getConnectionOptions } = require('./terminal') @@ -67,7 +66,7 @@ module.exports = (httpServer) => { transferIo.on('connection', async (socket) => { connectionCount++ connectedSockets.add(socket) - consola.success(`file-transfer websocket 已连接 - 当前连接数: ${ connectionCount }`) + logger.info(`file-transfer websocket 已连接 - 当前连接数: ${ connectionCount }`) // IP白名单检查 const requestIP = socket.handshake.headers['x-forwarded-for'] || socket.handshake.address @@ -113,7 +112,7 @@ module.exports = (httpServer) => { const updatedTasks = await getSortedTasksList() socket.emit('tasks_list', updatedTasks) } catch (error) { - consola.error('启动传输任务失败:', error) + logger.error('启动传输任务失败:', error) socket.emit('task_failed', { taskId: transferConfig.taskId, message: error.message @@ -217,7 +216,7 @@ module.exports = (httpServer) => { // 清理该socket的进度广播定时器 stopProgressBroadcast(socket) - consola.info(`file-transfer websocket 断开连接 - 当前连接数: ${ connectionCount }`) + logger.info(`file-transfer websocket 断开连接 - 当前连接数: ${ connectionCount }`) }) }) @@ -261,7 +260,7 @@ async function executeTransfer(taskData, socket) { await updateTaskStatus(taskId, 'completed', socket) } catch (error) { - consola.error(`传输任务 ${ taskId } 失败:`, error) + logger.error(`传输任务 ${ taskId } 失败:`, error) await updateTaskStatus(taskId, 'failed', socket, error.message) } finally { // 清理资源 @@ -284,7 +283,7 @@ async function executeRsyncTransfer(taskData, sshClient, socket) { const targetOptions = targetConnectionData.authInfo const targetHostAuthType = targetOptions.password ? 'password' : 'privateKey' - consola.info(`目标主机认证方式: ${ targetHostAuthType }`) + logger.info(`目标主机认证方式: ${ targetHostAuthType }`) // 构建Rsync命令 let rsyncCmd = [] @@ -358,9 +357,9 @@ async function executeRsyncTransfer(taskData, sshClient, socket) { rsyncCmd.push(...sourcePaths.map(item => item.path)) rsyncCmd.push(`${ targetOptions.username }@${ targetOptions.host }:"${ targetPath }"`) - consola.info(`执行Rsync命令: ${ rsyncCmd.join(' ') }`) + logger.info(`执行Rsync命令: ${ rsyncCmd.join(' ') }`) if (Object.keys(envVars).length > 0) { - consola.info(`环境变量: ${ Object.keys(envVars).join(', ') }`) + logger.info(`环境变量: ${ Object.keys(envVars).join(', ') }`) } return new Promise((resolve, reject) => { @@ -375,7 +374,7 @@ async function executeRsyncTransfer(taskData, sshClient, socket) { finalCommand = `${ envString } ${ finalCommand }` } - // consola.info(`最终Rsync命令: ${ finalCommand }`) + // logger.info(`最终Rsync命令: ${ finalCommand }`) let start = false sshClient.exec(finalCommand, (err, stream) => { if (err) { @@ -394,10 +393,10 @@ async function executeRsyncTransfer(taskData, sshClient, socket) { activeTask.progressTracker.isVerifying = true await updateTaskProgress(taskId, activeTask.progressTracker, socket) } - consola.success(`Rsync传输完成: ${ taskId }`) + logger.info(`Rsync传输完成: ${ taskId }`) resolve() } else { - consola.error(`Rsync传输失败: ${ taskId }, 退出码: ${ code }`) + logger.error(`Rsync传输失败: ${ taskId }, 退出码: ${ code }`) reject(new Error(`Rsync传输失败: ${ errorOutput || '未知错误' }`)) } }) @@ -425,7 +424,7 @@ async function executeRsyncTransfer(taskData, sshClient, socket) { } const output = data.toString() errorOutput += output - consola.warn(`Rsync stderr: ${ output }`) + logger.warn(`Rsync stderr: ${ output }`) // 解析错误信息中的进度信息 fileTransferThrottle(parseRsyncProgress(output, taskId, socket)) @@ -460,7 +459,7 @@ function parseRsyncProgress(output, taskId, socket) { const outputLine = output.trim() // 添加调试日志 - consola.info(`Rsync输出 [${ taskId }]: "${ outputLine }"`) + logger.info(`Rsync输出 [${ taskId }]: "${ outputLine }"`) // 检测是否在校验阶段 if (outputLine.includes('verifying') || @@ -490,7 +489,7 @@ function parseRsyncProgress(output, taskId, socket) { status: 'transferring' }) } - consola.info(`单文件传输初始化: ${ tracker.currentFile }`) + logger.info(`单文件传输初始化: ${ tracker.currentFile }`) } } @@ -509,7 +508,7 @@ function parseRsyncProgress(output, taskId, socket) { status: 'transferring' }) } - consola.info(`检测到新文件传输(itemize格式): ${ filePath }`) + logger.info(`检测到新文件传输(itemize格式): ${ filePath }`) return } @@ -527,7 +526,7 @@ function parseRsyncProgress(output, taskId, socket) { status: 'transferring' }) } - consola.info(`检测到新文件传输(传统格式): ${ filePath }`) + logger.info(`检测到新文件传输(传统格式): ${ filePath }`) return } @@ -546,7 +545,7 @@ function parseRsyncProgress(output, taskId, socket) { const unitFactor = { 'B/s': 1, 'KB/s': 1024, 'MB/s': 1024 ** 2, 'GB/s': 1024 ** 3, 'TB/s': 1024 ** 4 } speed = parseFloat(speedVal) * (unitFactor[speedUnit] || 1) eta = parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(seconds) - consola.info(`Rsync标准格式解析 [${ taskId }]: ${ fileProgress }%, 速度: ${ speedVal }${ speedUnit }, ETA: ${ eta }s`) + logger.info(`Rsync标准格式解析 [${ taskId }]: ${ fileProgress }%, 速度: ${ speedVal }${ speedUnit }, ETA: ${ eta }s`) } else { // 模式2: 简化格式 - 100% 1.23MB/s match = outputLine.match(/(\d+)%\s+([\d.]+)([KMGT]?B\/s)/) @@ -555,13 +554,13 @@ function parseRsyncProgress(output, taskId, socket) { const unit = match[3] const unitFactor = { 'B/s': 1, 'KB/s': 1024, 'MB/s': 1024 ** 2, 'GB/s': 1024 ** 3, 'TB/s': 1024 ** 4 } speed = parseFloat(match[2]) * (unitFactor[unit] || 1) - consola.info(`Rsync简化格式解析 [${ taskId }]: ${ fileProgress }%, 速度: ${ match[2] }${ unit }`) + logger.info(`Rsync简化格式解析 [${ taskId }]: ${ fileProgress }%, 速度: ${ match[2] }${ unit }`) } else { // 模式3: 最简格式 - 只有百分比 match = outputLine.match(/(\d+)%/) if (match) { fileProgress = parseInt(match[1]) - consola.info(`Rsync百分比解析 [${ taskId }]: ${ fileProgress }%`) + logger.info(`Rsync百分比解析 [${ taskId }]: ${ fileProgress }%`) } } } @@ -582,12 +581,12 @@ function parseRsyncProgress(output, taskId, socket) { fileInfo.status = 'completed' fileInfo.transferred = transferred // 清除当前文件,为下一个文件做准备 - consola.info(`文件传输完成: ${ tracker.currentFile }`) + logger.info(`文件传输完成: ${ tracker.currentFile }`) tracker.currentFile = null } } - consola.info(`传输进度: ${ completed }/${ total } 文件完成`) + logger.info(`传输进度: ${ completed }/${ total } 文件完成`) } // 更新当前文件进度 @@ -613,13 +612,13 @@ function parseRsyncProgress(output, taskId, socket) { if (fileProgress === 100) { fileInfo.status = 'completed' // 文件完成后清除当前文件,为下一个文件做准备 - consola.info(`文件传输完成: ${ tracker.currentFile }`) + logger.info(`文件传输完成: ${ tracker.currentFile }`) tracker.currentFile = null } } } else { // 如果仍然没有当前文件,记录警告但继续处理 - consola.warn(`收到进度信息但没有当前文件 [${ taskId }]: ${ fileProgress }%`) + logger.warn(`收到进度信息但没有当前文件 [${ taskId }]: ${ fileProgress }%`) } } @@ -692,7 +691,7 @@ async function updateTaskProgress(taskId, progressTracker, socket) { })) } - consola.info(`推送进度更新 [${ taskId }]:`, { + logger.info(`推送进度更新 [${ taskId }]:`, { overall: progressData.overallProgress, files: `${ progressData.completedFiles }/${ progressData.totalFiles }`, current: progressData.currentFile, @@ -705,7 +704,7 @@ async function updateTaskProgress(taskId, progressTracker, socket) { socket.emit('task_progress', progressData) } } catch (error) { - consola.error('更新任务进度失败:', error) + logger.error('更新任务进度失败:', error) } } @@ -739,7 +738,7 @@ async function updateTaskStatus(taskId, status, socket, errorMessage = null) { errorMessage }) } catch (error) { - consola.error('更新任务状态失败:', error) + logger.error('更新任务状态失败:', error) } } @@ -848,14 +847,14 @@ async function createRemoteTempKeyFile(sshClient, privateKey) { function cleanupRemoteKeyFile(sshClient, keyFile) { if (!keyFile || !sshClient) return - consola.info(`清理远程密钥文件: ${ keyFile }`) + logger.info(`清理远程密钥文件: ${ keyFile }`) // 先删除文件,再验证删除 // const cleanupCmd = `rm -f "${ keyFile }" && if [ -f "${ keyFile }" ]; then echo "CLEANUP_FAILED"; else echo "CLEANUP_SUCCESS"; fi` const cleanupCmd = 'cd /tmp && rm -f easynode_key_* && if ls easynode_key_* 2>/dev/null; then echo "CLEANUP_FAILED"; else echo "CLEANUP_SUCCESS"; fi' sshClient.exec(cleanupCmd, (err, stream) => { if (err) { - consola.error('清理密钥文件时SSH错误:', err) + logger.error('清理密钥文件时SSH错误:', err) return } @@ -866,21 +865,21 @@ function cleanupRemoteKeyFile(sshClient, keyFile) { stream.on('close', () => { if (output.includes('CLEANUP_SUCCESS')) { - consola.success(`密钥文件清理成功: ${ keyFile }`) + logger.info(`密钥文件清理成功: ${ keyFile }`) } else if (output.includes('CLEANUP_FAILED')) { - consola.error(`密钥文件清理失败: ${ keyFile }`) + logger.error(`密钥文件清理失败: ${ keyFile }`) // 强制清理尝试 - 覆盖后删除 const forceCleanup = `echo "" > "${ keyFile }" && rm -f "${ keyFile }"` sshClient.exec(forceCleanup, () => { - consola.info(`强制清理密钥文件: ${ keyFile }`) + logger.info(`强制清理密钥文件: ${ keyFile }`) }) } else { - consola.warn(`密钥文件清理状态未知: ${ keyFile }`) + logger.warn(`密钥文件清理状态未知: ${ keyFile }`) } }) stream.stderr.on('data', (data) => { - consola.warn('清理密钥文件stderr:', data.toString()) + logger.warn('清理密钥文件stderr:', data.toString()) }) }) } @@ -902,7 +901,7 @@ function startProgressBroadcast(socket) { const runningTasks = Array.from(activeTasks.values()).filter(task => task.status === 'running') if (runningTasks.length === 0) { // 没有运行中的任务,停止广播 - consola.info('没有运行中的任务,停止进度广播') + logger.info('没有运行中的任务,停止进度广播') stopProgressBroadcast(socket) return } @@ -931,13 +930,13 @@ function startProgressBroadcast(socket) { } } } catch (error) { - consola.error('进度广播出错:', error) + logger.error('进度广播出错:', error) stopProgressBroadcast(socket) } }, 1500) progressBroadcastTimers.set(socket, timer) - consola.info('已启动进度广播定时器') + logger.info('已启动进度广播定时器') } // 停止进度广播 @@ -946,7 +945,7 @@ function stopProgressBroadcast(socket) { if (timer) { clearInterval(timer) progressBroadcastTimers.delete(socket) - consola.info('已停止进度广播定时器') + logger.info('已停止进度广播定时器') } } diff --git a/server/app/socket/onekey.js b/server/app/socket/onekey.js index c8e0fa3..ad57b27 100644 --- a/server/app/socket/onekey.js +++ b/server/app/socket/onekey.js @@ -112,7 +112,7 @@ module.exports = (httpServer) => { socket.disconnect() return } - consola.success('onekey-terminal websocket 已连接') + logger.info('onekey-terminal websocket 已连接') if (isExecuting) { socket.emit('create_fail', '正在执行中, 请稍后再试') socket.disconnect() @@ -157,19 +157,19 @@ module.exports = (httpServer) => { return } - consola.info('准备连接终端执行一次性指令:', host) - consola.log('连接信息', { username: targetConnectionOptions.username, port: targetConnectionOptions.port, authType: hostInfo.authType }) + logger.info('准备连接终端执行一次性指令:', host) + logger.info('连接信息', { username: targetConnectionOptions.username, port: targetConnectionOptions.port, authType: hostInfo.authType }) let sshClient = new SSHClient() execClient.push(sshClient) sshClient .on('ready', () => { - consola.success('连接终端成功:', host) + logger.info('连接终端成功:', host) execShell(socket, sshClient, curRes, resolve) }) .on('error', (err) => { console.log(err) - consola.error('onekey终端连接失败:', err.level) + logger.error('onekey终端连接失败:', err.level) curRes.status = execStatusEnum.connectFail curRes.result += err.message socket.emit('output', execResult) @@ -185,7 +185,7 @@ module.exports = (httpServer) => { ...targetConnectionOptions }) } catch (err) { - consola.error('创建终端错误:', err.message) + logger.error('创建终端错误:', err.message) curRes.status = execStatusEnum.connectFail curRes.result += err.message socket.emit('output', execResult) @@ -197,11 +197,11 @@ module.exports = (httpServer) => { }) try { await Promise.all(execPromise) - consola.success('onekey执行完成') + logger.info('onekey执行完成') socket.emit('exec_complete') sendNoticeAsync('onekey_complete', '批量指令执行完成', '请登录面板查看执行结果') } catch (error) { - consola.error('onekey执行超时:', error) + logger.error('onekey执行超时:', error) const { connecting, executing } = execStatusEnum execResult.forEach(item => { // 连接中和执行中的状态变更为超时状态 @@ -218,7 +218,7 @@ module.exports = (httpServer) => { }) socket.on('disconnect', async (reason) => { - consola.info('onekey终端连接断开:', reason) + logger.info('onekey终端连接断开:', reason) disconnectAllExecClient() const { execSuccess, connectFail, execFail, execTimeout } = execStatusEnum execResult.forEach(item => { diff --git a/server/app/socket/plus.js b/server/app/socket/plus.js index 5237bc2..8787314 100644 --- a/server/app/socket/plus.js +++ b/server/app/socket/plus.js @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/server/app/socket/server-status.js b/server/app/socket/server-status.js index 8726725..0b7ff72 100644 --- a/server/app/socket/server-status.js +++ b/server/app/socket/server-status.js @@ -46,7 +46,7 @@ module.exports = (httpServer) => { } connectionCount++ - consola.success(`server-status websocket 已连接 - 当前连接数: ${ connectionCount }`) + logger.info(`server-status websocket 已连接 - 当前连接数: ${ connectionCount }`) let targetSSHClient = null let jumpSshClients = [] @@ -92,7 +92,7 @@ module.exports = (httpServer) => { // 如果有正在创建的连接,等待它完成 if (pendingConnections.has(monitorKey)) { try { - consola.info(`等待现有连接创建完成: ${ monitorKey }`) + logger.info(`等待现有连接创建完成: ${ monitorKey }`) await pendingConnections.get(monitorKey) // 连接创建完成后,应该能在monitorMap中找到了 if (monitorMap.has(monitorKey)) { @@ -109,7 +109,7 @@ module.exports = (httpServer) => { return } } catch (error) { - consola.error(`等待连接创建失败,继续创建: ${ error.message }`) + logger.error(`等待连接创建失败,继续创建: ${ error.message }`) } } @@ -139,10 +139,10 @@ module.exports = (httpServer) => { stopAll() monitorMap.delete(monitorKey) } - consola.info(`server-status socket断开: ${ reason }`) + logger.info(`server-status socket断开: ${ reason }`) }) - consola.success(`成功创建服务器监控: ${ monitorKey }`) + logger.info(`成功创建服务器监控: ${ monitorKey }`) return entryObj } finally { @@ -158,7 +158,7 @@ module.exports = (httpServer) => { await createConnectionPromise } catch (error) { - consola.error('ws_server_status 事件处理失败:', error.message) + logger.error('ws_server_status 事件处理失败:', error.message) socket.emit('server_status_error', `连接失败: ${ error.message }`) // 全面清理资源,防止泄漏 @@ -169,7 +169,7 @@ module.exports = (httpServer) => { pendingConnections.delete(monitorKey) } - consola.info(`连接失败后已清理资源: ${ monitorKey || 'unknown' }`) + logger.info(`连接失败后已清理资源: ${ monitorKey || 'unknown' }`) } }) @@ -181,14 +181,14 @@ module.exports = (httpServer) => { targetSSHClient.exec('/bin/bash --noprofile --norc -i', (err, stream) => { if (err) { - consola.error('创建持久化 shell 失败:', err.message) + logger.error('创建持久化 shell 失败:', err.message) return reject(err) } persistentShell = stream shellReady = true persistentShell.write('unset HISTFILE\n') - consola.info('server-status: 持久化 shell 已就绪') + logger.info('server-status: 持久化 shell 已就绪') let buffer = '' const handleData = (data) => { @@ -219,7 +219,7 @@ module.exports = (httpServer) => { stream.on('close', () => { shellReady = false persistentShell = null - consola.warn('server-status: 持久化 shell 已关闭') + logger.warn('server-status: 持久化 shell 已关闭') }) resolve() }) @@ -313,7 +313,7 @@ module.exports = (httpServer) => { pendingConnections.delete(monitorKey) } - consola.info(`已清理服务器监控资源: ${ monitorKey || 'unknown' } - 原因: ${ reason }`) + logger.info(`已清理服务器监控资源: ${ monitorKey || 'unknown' } - 原因: ${ reason }`) } // 检查是否是关键的服务器错误 @@ -353,7 +353,7 @@ module.exports = (httpServer) => { cpuCount = cpuCountMatch ? parseInt(cpuCountMatch[1]) : 0 } } catch (error) { - consola.warn('获取CPU核心数失败:', error.message) + logger.warn('获取CPU核心数失败:', error.message) } // 获取CPU型号 @@ -369,11 +369,11 @@ module.exports = (httpServer) => { cpuModel = lscpuModelMatch ? lscpuModelMatch[1].trim() : 'Unknown' } } catch (error) { - consola.warn('获取CPU型号失败:', error.message) + logger.warn('获取CPU型号失败:', error.message) // 检查是否是关键错误 if (isServerCriticalError(error.message)) { - consola.error(`执行命令失败:cat /proc/cpuinfo: ${ error.message }`) + logger.error(`执行命令失败:cat /proc/cpuinfo: ${ error.message }`) return { cpuCount: 0, cpuModel: 'Unknown' } } } @@ -431,11 +431,11 @@ module.exports = (httpServer) => { previousCpuStats = { ...currentCpuStats, timestamp: now } } } catch (error) { - consola.warn('获取CPU使用率失败:', error.message) + logger.warn('获取CPU使用率失败:', error.message) // 检查是否是关键错误 if (isServerCriticalError(error.message)) { - consola.error(`执行命令失败:cat /proc/stat: ${ error.message }`) + logger.error(`执行命令失败:cat /proc/stat: ${ error.message }`) return { cpuUsage: 0, cpuCount: 0, cpuModel: 'Unknown' } } } @@ -559,11 +559,11 @@ module.exports = (httpServer) => { return { memInfo, swapInfo } } catch (error) { - consola.error('获取内存信息失败:', error.message) + logger.error('获取内存信息失败:', error.message) // 检查是否是关键错误 if (isServerCriticalError(error.message)) { - consola.error(`执行命令失败:free -m: ${ error.message }`) + logger.error(`执行命令失败:free -m: ${ error.message }`) } return defaultReturn @@ -597,7 +597,7 @@ module.exports = (httpServer) => { }) return drives } catch (error) { - consola.error('获取磁盘信息失败:', error.message) + logger.error('获取磁盘信息失败:', error.message) return [] } } @@ -685,7 +685,7 @@ module.exports = (httpServer) => { return stats } catch (error) { - consola.error('parseNetworkStats 失败:', error.message) + logger.error('parseNetworkStats 失败:', error.message) return null } } @@ -785,11 +785,11 @@ module.exports = (httpServer) => { return netstatInfo } catch (error) { - consola.error('获取网络信息失败:', error.message) + logger.error('获取网络信息失败:', error.message) // 检查是否是关键错误 if (isServerCriticalError(error.message)) { - consola.error(`执行命令失败:cat /proc/net/dev: ${ error.message }`) + logger.error(`执行命令失败:cat /proc/net/dev: ${ error.message }`) return { total: { inputMb: '0.000', outputMb: '0.000' } } } @@ -817,7 +817,7 @@ module.exports = (httpServer) => { try { hostname = await executeCommand('hostname') || 'Unknown' } catch (e) { - consola.warn('获取hostname失败:', e.message) + logger.warn('获取hostname失败:', e.message) } // 通过读取 /etc/os-release 文件获取操作系统信息 @@ -850,18 +850,18 @@ module.exports = (httpServer) => { } }) } catch (e) { - consola.warn('读取 /etc/os-release 失败,尝试使用 uname 命令:', e.message) + logger.warn('读取 /etc/os-release 失败,尝试使用 uname 命令:', e.message) // 如果读取 /etc/os-release 失败,回退到 uname 命令 try { type = await executeCommand('uname -s') || 'Linux' } catch (e2) { - consola.warn('获取系统类型失败:', e2.message) + logger.warn('获取系统类型失败:', e2.message) } try { release = await executeCommand('uname -r') || 'Unknown' } catch (e2) { - consola.warn('获取系统版本失败:', e2.message) + logger.warn('获取系统版本失败:', e2.message) } } @@ -869,7 +869,7 @@ module.exports = (httpServer) => { try { arch = await executeCommand('uname -m') || 'Unknown' } catch (e) { - consola.warn('获取系统架构失败:', e.message) + logger.warn('获取系统架构失败:', e.message) } const staticInfo = { @@ -884,7 +884,7 @@ module.exports = (httpServer) => { staticSystemInfo.osInfo = staticInfo return staticInfo } catch (error) { - consola.error('获取静态系统信息失败:', error.message) + logger.error('获取静态系统信息失败:', error.message) staticSystemInfo.osInfo = defaultStaticInfo return defaultStaticInfo } @@ -902,11 +902,11 @@ module.exports = (httpServer) => { const uptimeStr = await executeCommand('cat /proc/uptime | cut -d" " -f1') || '0' uptime = parseFloat(uptimeStr) || 0 } catch (e) { - consola.warn('获取系统运行时间失败:', e.message) + logger.warn('获取系统运行时间失败:', e.message) // 检查是否是关键错误 if (isServerCriticalError(e.message)) { - consola.error(`执行命令失败:cat /proc/uptime: ${ e.message }`) + logger.error(`执行命令失败:cat /proc/uptime: ${ e.message }`) return { ...staticInfo, uptime: 0 } } } @@ -916,7 +916,7 @@ module.exports = (httpServer) => { uptime } } catch (error) { - consola.error('获取系统信息失败:', error.message) + logger.error('获取系统信息失败:', error.message) return { hostname: 'Unknown', type: 'Linux', @@ -935,7 +935,7 @@ module.exports = (httpServer) => { statusData.cpuInfo = cpuInfo statusData.connect = true // 标记连接状态 } catch (error) { - consola.error('更新CPU信息失败:', error.message) + logger.error('更新CPU信息失败:', error.message) statusData.cpuInfo = {} } } @@ -948,7 +948,7 @@ module.exports = (httpServer) => { statusData.swapInfo = swapInfo statusData.connect = true } catch (error) { - consola.error('更新内存信息失败:', error.message) + logger.error('更新内存信息失败:', error.message) statusData.memInfo = {} statusData.swapInfo = {} } @@ -961,7 +961,7 @@ module.exports = (httpServer) => { statusData.drivesInfo = drives statusData.connect = true } catch (error) { - consola.error('更新磁盘信息失败:', error.message) + logger.error('更新磁盘信息失败:', error.message) statusData.drivesInfo = [] } } @@ -973,7 +973,7 @@ module.exports = (httpServer) => { statusData.netstatInfo = netstatInfo statusData.connect = true } catch (error) { - consola.error('更新网络信息失败:', error.message) + logger.error('更新网络信息失败:', error.message) statusData.netstatInfo = {} } } @@ -985,7 +985,7 @@ module.exports = (httpServer) => { statusData.osInfo = osInfo statusData.connect = true } catch (error) { - consola.error('更新系统信息失败:', error.message) + logger.error('更新系统信息失败:', error.message) statusData.osInfo = {} } } @@ -1013,7 +1013,7 @@ module.exports = (httpServer) => { } } catch (error) { - consola.error('更新服务器状态过程中出错:', error.message) + logger.error('更新服务器状态过程中出错:', error.message) statusData.connect = false } } @@ -1026,7 +1026,7 @@ module.exports = (httpServer) => { // 更新全局statusData await updateServerStatus() } catch (error) { - consola.error('数据收集过程中出错:', error.message) + logger.error('数据收集过程中出错:', error.message) } } @@ -1042,7 +1042,7 @@ module.exports = (httpServer) => { } } } catch (error) { - consola.error('数据发送过程中出错:', error.message) + logger.error('数据发送过程中出错:', error.message) } } @@ -1071,7 +1071,7 @@ module.exports = (httpServer) => { cleanupResources('socket断开') } - consola.info(`server-status websocket 连接断开: ${ reason } - 当前连接数: ${ connectionCount }`) + logger.info(`server-status websocket 连接断开: ${ reason } - 当前连接数: ${ connectionCount }`) }) }) } \ No newline at end of file diff --git a/server/app/socket/sftp-v2.js b/server/app/socket/sftp-v2.js index 2c84bcc..fdc18c8 100644 --- a/server/app/socket/sftp-v2.js +++ b/server/app/socket/sftp-v2.js @@ -82,7 +82,7 @@ function detectEncoding(buffer) { const confidence = Math.round(topResult.confidence || 50) - consola.info(`编码检测结果: ${ normalizedEncoding } (置信度: ${ confidence }%)`) + logger.info(`编码检测结果: ${ normalizedEncoding } (置信度: ${ confidence }%)`) return { encoding: normalizedEncoding, @@ -90,7 +90,7 @@ function detectEncoding(buffer) { reason: `chardet 检测为 ${ detected }` } } catch (error) { - consola.error('编码检测失败:', error.message) + logger.error('编码检测失败:', error.message) return { encoding: 'utf8', confidence: 30, reason: '检测异常,默认 UTF-8' } } } @@ -271,7 +271,7 @@ const listenAction = (sftpClient, socket) => { try { sftpClient.client.exec(cmd, (err, stream) => { if (err) { - consola.error('执行命令失败:', cmd, err.message) + logger.error('执行命令失败:', cmd, err.message) // 检查是否是连接相关错误 if (err.message.includes('Not connected') || err.message.includes('Connection lost')) { return rej(new Error('SSH连接已断开,无法执行命令')) @@ -300,7 +300,7 @@ const listenAction = (sftpClient, socket) => { stream.destroy() } } catch (cleanupErr) { - consola.warn('清理stream失败:', cleanupErr.message) + logger.warn('清理stream失败:', cleanupErr.message) } } } @@ -320,7 +320,7 @@ const listenAction = (sftpClient, socket) => { // 设置超时保护(60秒) timeout = setTimeout(() => { - consola.warn('命令执行超时:', cmd) + logger.warn('命令执行超时:', cmd) resolveOnce(new Error(`命令执行超时: ${ cmd }`), true) }, 60000) @@ -331,7 +331,7 @@ const listenAction = (sftpClient, socket) => { // 处理错误事件 stream.on('error', (streamErr) => { - consola.error('Stream错误:', cmd, streamErr.message) + logger.error('Stream错误:', cmd, streamErr.message) if (streamErr.message.includes('Not connected')) { resolveOnce(new Error('SSH连接在命令执行过程中断开'), true) } else { @@ -342,10 +342,10 @@ const listenAction = (sftpClient, socket) => { // 处理连接断开 stream.on('close', (code) => { if (errMsg) { - consola.error('命令执行错误:', cmd, errMsg) + logger.error('命令执行错误:', cmd, errMsg) resolveOnce(new Error(`命令执行失败: ${ code }: ${ errMsg }`), true) } else { - consola.info('命令执行完成:', cmd) + logger.info('命令执行完成:', cmd) resolveOnce('success') } }) @@ -353,11 +353,11 @@ const listenAction = (sftpClient, socket) => { // 处理命令退出 stream.on('exit', (code) => { if (code === 0) { - consola.info('命令执行成功:', cmd) + logger.info('命令执行成功:', cmd) resolveOnce() // 成功 } else { const errorMessage = errMsg || `命令退出码: ${ code }` - consola.error('命令执行失败:', cmd, errorMessage) + logger.error('命令执行失败:', cmd, errorMessage) resolveOnce(new Error(errorMessage), true) } }) @@ -366,7 +366,7 @@ const listenAction = (sftpClient, socket) => { stream.on('data', () => {}) }) } catch (execErr) { - consola.error('execCommand异常:', cmd, execErr.message) + logger.error('execCommand异常:', cmd, execErr.message) rej(execErr) } }) @@ -387,7 +387,7 @@ const listenAction = (sftpClient, socket) => { const formattedDirLs = formatFileList(dirLs) socket.emit('dir_ls', formattedDirLs, dirPath) } catch (err) { - consola.error('copy error:', err.message) + logger.error('copy error:', err.message) socket.emit('copy_fail', err.message) } }) @@ -416,11 +416,11 @@ const listenAction = (sftpClient, socket) => { } if (type === 'folder') { - consola.info(`创建文件夹: ${ targetPath }`) + logger.info(`创建文件夹: ${ targetPath }`) await sftpClient.mkdir(targetPath) socket.emit('create_success', `文件夹 "${ trimmedName }" 创建成功`) } else if (type === 'file') { - consola.info(`创建文件: ${ targetPath }`) + logger.info(`创建文件: ${ targetPath }`) // 创建空文件,使用 touch 命令 const cmd = `touch "${ targetPath }"` await execCommand(cmd) @@ -434,7 +434,7 @@ const listenAction = (sftpClient, socket) => { const formattedDirLs = formatFileList(dirLs) socket.emit('dir_ls', formattedDirLs, dirPath) } catch (err) { - consola.error('create error:', err.message) + logger.error('create error:', err.message) socket.emit('create_fail', err.message) } }) @@ -472,9 +472,9 @@ const listenAction = (sftpClient, socket) => { // 使用 tar 命令压缩 const tarCmd = `cd "${ dirPath }" && tar -czf "${ trimmedArchiveName }" ${ fileNames }` - consola.info(`开始压缩文件: ${ targets.map(t => t.name).join(', ') } -> ${ trimmedArchiveName }`) + logger.info(`开始压缩文件: ${ targets.map(t => t.name).join(', ') } -> ${ trimmedArchiveName }`) await execCommand(tarCmd) - consola.info(`压缩完成: ${ trimmedArchiveName }`) + logger.info(`压缩完成: ${ trimmedArchiveName }`) socket.emit('compress_success', `压缩文件 "${ trimmedArchiveName }" 创建成功`) @@ -483,7 +483,7 @@ const listenAction = (sftpClient, socket) => { const formattedDirLs = formatFileList(dirLs) socket.emit('dir_ls', formattedDirLs, dirPath) } catch (err) { - consola.error('compress error:', err.message) + logger.error('compress error:', err.message) socket.emit('compress_fail', err.message) } }) @@ -527,7 +527,7 @@ const listenAction = (sftpClient, socket) => { // 创建目标文件夹 await sftpClient.mkdir(targetDir) - consola.info(`创建目标文件夹: ${ targetDir }`) + logger.info(`创建目标文件夹: ${ targetDir }`) } // 根据文件扩展名选择解压命令 @@ -555,9 +555,9 @@ const listenAction = (sftpClient, socket) => { } } - consola.info(`开始解压文件: ${ trimmedFileName } -> ${ targetDirName }`) + logger.info(`开始解压文件: ${ trimmedFileName } -> ${ targetDirName }`) await execCommand(decompressCmd) - consola.info(`解压完成: ${ trimmedFileName } -> ${ targetDirName }`) + logger.info(`解压完成: ${ trimmedFileName } -> ${ targetDirName }`) socket.emit('decompress_success', `文件 "${ trimmedFileName }" 解压到${ targetDirName }成功`) @@ -566,7 +566,7 @@ const listenAction = (sftpClient, socket) => { const formattedDirLs = formatFileList(dirLs) socket.emit('dir_ls', formattedDirLs, dirPath) } catch (err) { - consola.error('decompress error:', err.message) + logger.error('decompress error:', err.message) socket.emit('decompress_fail', err.message) } }) @@ -615,13 +615,13 @@ const listenAction = (sftpClient, socket) => { } // 在远端打包 - consola.info(`开始打包文件夹: ${ srcPath }`) + logger.info(`开始打包文件夹: ${ srcPath }`) const tarCmd = `cd "${ dirPath }" && tar -czf "${ remoteTarPath }" "${ target.name }"` try { await execCommand(tarCmd) - consola.info(`打包文件夹: ${ srcPath } 成功`) + logger.info(`打包文件夹: ${ srcPath } 成功`) } catch (tarErr) { - consola.error('打包文件夹失败:', tarErr.message) + logger.error('打包文件夹失败:', tarErr.message) throw new Error(`打包文件夹失败: ${ tarErr.message }`) } @@ -670,12 +670,12 @@ const listenAction = (sftpClient, socket) => { const fileNames = targets.map(t => `"${ t.name }"`).join(' ') const tarCmd = `cd "${ dirPath }" && tar -czf "${ remoteTarPath }" ${ fileNames }` - consola.info(`开始打包多个文件: ${ targets.map(t => t.name).join(', ') }`) + logger.info(`开始打包多个文件: ${ targets.map(t => t.name).join(', ') }`) try { await execCommand(tarCmd) - consola.info('打包多个文件成功') + logger.info('打包多个文件成功') } catch (tarErr) { - consola.error('打包失败:', tarErr.message) + logger.error('打包失败:', tarErr.message) throw new Error(`打包失败: ${ tarErr.message }`) } @@ -695,7 +695,7 @@ const listenAction = (sftpClient, socket) => { downloadTasks.delete(taskId) } catch (err) { - consola.error('下载失败:', err.message) + logger.error('下载失败:', err.message) socket.emit('download_fail', err.message) // 清理远程临时文件(如果还存在) @@ -715,9 +715,9 @@ const listenAction = (sftpClient, socket) => { if (!remoteTarPath) return try { await execCommand(`rm -f "${ remoteTarPath }"`) - consola.info(`已清理远程临时文件: ${ remoteTarPath }`) + logger.info(`已清理远程临时文件: ${ remoteTarPath }`) } catch (cleanupErr) { - consola.warn('清理远程临时文件失败:', remoteTarPath, cleanupErr.message) + logger.warn('清理远程临时文件失败:', remoteTarPath, cleanupErr.message) } } @@ -740,9 +740,9 @@ const listenAction = (sftpClient, socket) => { const cleanupCacheDir = () => { try { fs.emptyDirSync(sftpCacheDir) - consola.success('已清理 sftpCacheDir:', sftpCacheDir) + logger.info('已清理 sftpCacheDir:', sftpCacheDir) } catch (err) { - consola.warn('清理缓存目录失败:', err.message) + logger.warn('清理缓存目录失败:', err.message) } } @@ -754,7 +754,7 @@ const listenAction = (sftpClient, socket) => { const favorites = await favoriteSftpDB.findAsync({ hostId }, { sort: { createTime: -1 } }) socket.emit('favorites_list', favorites) } catch (err) { - consola.error('获取收藏列表失败:', err.message) + logger.error('获取收藏列表失败:', err.message) socket.emit('favorite_error', '获取收藏列表失败') } }) @@ -785,9 +785,9 @@ const listenAction = (sftpClient, socket) => { await favoriteSftpDB.insertAsync(newFavorite) socket.emit('favorite_added', `收藏 "${ name }" 成功`) - consola.info(`用户收藏了路径: ${ path }`) + logger.info(`用户收藏了路径: ${ path }`) } catch (err) { - consola.error('添加收藏失败:', err.message) + logger.error('添加收藏失败:', err.message) socket.emit('favorite_error', err.message) } }) @@ -807,9 +807,9 @@ const listenAction = (sftpClient, socket) => { } socket.emit('favorite_removed', '取消收藏成功') - consola.info(`用户取消收藏路径: ${ path }`) + logger.info(`用户取消收藏路径: ${ path }`) } catch (err) { - consola.error('删除收藏失败:', err.message) + logger.error('删除收藏失败:', err.message) socket.emit('favorite_error', err.message) } }) @@ -820,9 +820,9 @@ const listenAction = (sftpClient, socket) => { socket.on('resolve_symlink', async ({ symlinkPath }) => { try { // 获取软链接的真实路径 - consola.info(`解析软链接: ${ symlinkPath }`) + logger.info(`解析软链接: ${ symlinkPath }`) const realPath = await sftpClient.realPath(symlinkPath) - consola.info(`软链接真实路径: ${ realPath }`) + logger.info(`软链接真实路径: ${ realPath }`) // 检查真实路径是否存在 const stats = await sftpClient.stat(realPath) @@ -834,10 +834,10 @@ const listenAction = (sftpClient, socket) => { symlinkPath }) - consola.info(`软链接解析成功: ${ symlinkPath } -> ${ realPath } (${ isDirectory ? '目录' : '文件' })`) + logger.info(`软链接解析成功: ${ symlinkPath } -> ${ realPath } (${ isDirectory ? '目录' : '文件' })`) } catch (err) { - consola.error('软链接解析失败:', err.message) + logger.error('软链接解析失败:', err.message) socket.emit('symlink_resolve_error', { error: err.message, symlinkPath @@ -869,23 +869,23 @@ const listenAction = (sftpClient, socket) => { return } - consola.info(`开始智能检测文件编码: ${ filePath }`) + logger.info(`开始智能检测文件编码: ${ filePath }`) const buffer = await sftpClient.get(filePath) const { encoding: detectedEncoding, confidence, reason } = detectEncoding(buffer) - consola.info(`检测结果: ${ detectedEncoding.toUpperCase() } (置信度: ${ confidence }%) - ${ reason }`) + logger.info(`检测结果: ${ detectedEncoding.toUpperCase() } (置信度: ${ confidence }%) - ${ reason }`) // 根据检测到的编码解码文件内容 let content try { content = decodeBuffer(buffer, detectedEncoding) } catch (decodeErr) { - consola.error('使用检测编码解码失败,尝试 UTF-8:', decodeErr.message) + logger.error('使用检测编码解码失败,尝试 UTF-8:', decodeErr.message) // 解码失败,降级为 UTF-8 content = buffer.toString('utf8') } - consola.info(`文件读取成功: ${ filePath },大小: ${ content.length } 字符,使用编码: ${ detectedEncoding.toUpperCase() }`) + logger.info(`文件读取成功: ${ filePath },大小: ${ content.length } 字符,使用编码: ${ detectedEncoding.toUpperCase() }`) socket.emit('file_content_with_encoding', { content, @@ -895,7 +895,7 @@ const listenAction = (sftpClient, socket) => { }) } catch (err) { - consola.error('智能读取文件失败:', err.message) + logger.error('智能读取文件失败:', err.message) socket.emit('file_read_error', { error: err.message, filePath @@ -917,7 +917,7 @@ const listenAction = (sftpClient, socket) => { } // 读取文件内容 - consola.info(`开始读取文件: ${ filePath },使用编码: ${ encoding.toUpperCase() }`) + logger.info(`开始读取文件: ${ filePath },使用编码: ${ encoding.toUpperCase() }`) const buffer = await sftpClient.get(filePath) // 根据编码解码文件内容 @@ -925,7 +925,7 @@ const listenAction = (sftpClient, socket) => { try { content = decodeBuffer(buffer, encoding) } catch (decodeErr) { - consola.error(`文件解码失败(编码: ${ encoding }):`, decodeErr.message) + logger.error(`文件解码失败(编码: ${ encoding }):`, decodeErr.message) socket.emit('file_read_error', { error: `文件解码失败,可能不是 ${ encoding.toUpperCase() } 编码`, filePath @@ -933,11 +933,11 @@ const listenAction = (sftpClient, socket) => { return } - consola.info(`文件读取成功: ${ filePath },大小: ${ content.length } 字符`) + logger.info(`文件读取成功: ${ filePath },大小: ${ content.length } 字符`) socket.emit('file_content', { content, filePath }) } catch (err) { - consola.error('读取文件失败:', err.message) + logger.error('读取文件失败:', err.message) socket.emit('file_read_error', { error: err.message, filePath @@ -987,7 +987,7 @@ const listenAction = (sftpClient, socket) => { const cacheFileName = `image_${ timestamp }_${ fileName }` const localImagePath = rawPath.join(sftpCacheDir, cacheFileName) - consola.info(`开始下载图片到缓存: ${ filePath } -> ${ localImagePath }`) + logger.info(`开始下载图片到缓存: ${ filePath } -> ${ localImagePath }`) // 下载图片到本地缓存 await sftpClient.fastGet(filePath, localImagePath) @@ -995,7 +995,7 @@ const listenAction = (sftpClient, socket) => { // 生成访问URL const imageUrl = `/sftp-cache/${ cacheFileName }` - consola.info(`图片下载成功: ${ filePath },缓存路径: ${ localImagePath }`) + logger.info(`图片下载成功: ${ filePath },缓存路径: ${ localImagePath }`) socket.emit('image_content', { imageUrl, @@ -1005,7 +1005,7 @@ const listenAction = (sftpClient, socket) => { }) } catch (err) { - consola.error('图片预览失败:', err.message) + logger.error('图片预览失败:', err.message) socket.emit('image_read_error', { error: err.message, filePath @@ -1021,7 +1021,7 @@ const listenAction = (sftpClient, socket) => { try { buffer = encodeString(content, encoding) } catch (encodeErr) { - consola.error(`文件编码失败(编码: ${ encoding }):`, encodeErr.message) + logger.error(`文件编码失败(编码: ${ encoding }):`, encodeErr.message) socket.emit('file_save_error', { error: `文件编码失败: ${ encodeErr.message }`, filePath @@ -1032,11 +1032,11 @@ const listenAction = (sftpClient, socket) => { // 保存文件内容 await sftpClient.put(buffer, filePath) - consola.info(`文件保存成功: ${ filePath }`) + logger.info(`文件保存成功: ${ filePath }`) socket.emit('file_saved', { filePath }) } catch (err) { - consola.error('保存文件失败:', err.message) + logger.error('保存文件失败:', err.message) socket.emit('file_save_error', { error: err.message, filePath @@ -1049,7 +1049,7 @@ const listenAction = (sftpClient, socket) => { // 开始上传 socket.on('upload_start', async ({ taskId, fileName, fileSize, targetPath }) => { try { - consola.info(`收到上传请求: ${ fileName }, 大小: ${ (fileSize / 1024 / 1024 / 1024).toFixed(2) }GB`) + logger.info(`收到上传请求: ${ fileName }, 大小: ${ (fileSize / 1024 / 1024 / 1024).toFixed(2) }GB`) if (!taskId || !fileName || !fileSize || !targetPath) { throw new Error('上传参数不完整') @@ -1075,11 +1075,11 @@ const listenAction = (sftpClient, socket) => { } uploadTasks.set(taskId, uploadTask) - consola.info(`开始上传任务: ${ taskId } - ${ fileName }`) + logger.info(`开始上传任务: ${ taskId } - ${ fileName }`) socket.emit('upload_started', { taskId, fileName }) } catch (err) { - consola.error('开始上传失败:', err.message) + logger.error('开始上传失败:', err.message) socket.emit('upload_fail', { taskId, error: err.message }) } }) @@ -1107,7 +1107,7 @@ const listenAction = (sftpClient, socket) => { // 处理写入流错误(将错误标记到任务中) task.writeStream.on('error', (err) => { - consola.error(`写入流错误: ${ taskId }`, err.message) + logger.error(`写入流错误: ${ taskId }`, err.message) task.writeStreamError = err // 销毁流,防止继续写入 if (!task.writeStream.destroyed) { @@ -1164,7 +1164,7 @@ const listenAction = (sftpClient, socket) => { task.lastProgressTime = now } - // consola.info(`上传分片: ${ taskId } - ${ chunkIndex + 1 }/${ totalChunks }`) // 太频繁,注释掉 + // logger.info(`上传分片: ${ taskId } - ${ chunkIndex + 1 }/${ totalChunks }`) // 太频繁,注释掉 socket.emit('upload_chunk_success', { taskId, chunkIndex }) // 如果是最后一个分片,完成文件写入并开始传输 @@ -1173,7 +1173,7 @@ const listenAction = (sftpClient, socket) => { } } catch (err) { - consola.error('上传分片失败:', err.message) + logger.error('上传分片失败:', err.message) socket.emit('upload_chunk_fail', { taskId, chunkIndex, error: err.message }) // 清理资源 @@ -1187,7 +1187,7 @@ const listenAction = (sftpClient, socket) => { // 完成上传的辅助函数 async function completeUpload(task) { try { - consola.info(`文件接收完成,准备传输: ${ task.fileName }`) + logger.info(`文件接收完成,准备传输: ${ task.fileName }`) // 关闭写入流 if (task.writeStream) { @@ -1221,7 +1221,7 @@ const listenAction = (sftpClient, socket) => { }) // 通过SFTP传输到远程服务器,使用fastPut带进度回调 - consola.info(`开始传输文件到远程服务器: ${ task.targetPath }`) + logger.info(`开始传输文件到远程服务器: ${ task.targetPath }`) let sftpStartTime = Date.now() let lastSftpUpdateTime = sftpStartTime @@ -1260,7 +1260,7 @@ const listenAction = (sftpClient, socket) => { }) // 传输完成 - consola.info(`文件上传成功: ${ task.fileName }`) + logger.info(`文件上传成功: ${ task.fileName }`) socket.emit('upload_complete', { taskId: task.taskId, fileName: task.fileName, @@ -1268,7 +1268,7 @@ const listenAction = (sftpClient, socket) => { }) } catch (err) { - consola.error('完成上传失败:', err.message) + logger.error('完成上传失败:', err.message) socket.emit('upload_fail', { taskId: task.taskId, error: err.message @@ -1278,9 +1278,9 @@ const listenAction = (sftpClient, socket) => { if (task.tempFilePath && fs.existsSync(task.tempFilePath)) { try { fs.unlinkSync(task.tempFilePath) - consola.info(`已清理临时文件: ${ task.tempFilePath }`) + logger.info(`已清理临时文件: ${ task.tempFilePath }`) } catch (cleanupErr) { - consola.warn('清理临时文件失败:', cleanupErr.message) + logger.warn('清理临时文件失败:', cleanupErr.message) } } @@ -1307,14 +1307,14 @@ const listenAction = (sftpClient, socket) => { if (task.tempFilePath && fs.existsSync(task.tempFilePath)) { try { fs.unlinkSync(task.tempFilePath) - consola.info(`取消上传,已清理临时文件: ${ task.tempFilePath }`) + logger.info(`取消上传,已清理临时文件: ${ task.tempFilePath }`) } catch (cleanupErr) { - consola.warn('清理临时文件失败:', cleanupErr.message) + logger.warn('清理临时文件失败:', cleanupErr.message) } } uploadTasks.delete(taskId) - consola.info(`取消上传任务: ${ taskId }`) + logger.info(`取消上传任务: ${ taskId }`) socket.emit('upload_cancelled', { taskId }) } }) @@ -1322,7 +1322,7 @@ const listenAction = (sftpClient, socket) => { // 监听连接断开,清理下载任务和缓存 socket.on('disconnect', async (reason) => { try { - consola.info('SFTP连接断开,开始清理资源...', reason) + logger.info('SFTP连接断开,开始清理资源...', reason) // 清理定时器 if (memoryCleanupInterval) { @@ -1343,7 +1343,7 @@ const listenAction = (sftpClient, socket) => { remoteCleanupPromises.push(cleanupRemoteTarFile(task.remoteTarPath)) } } catch (taskError) { - consola.warn(`清理下载任务 ${ taskId } 失败:`, taskError.message) + logger.warn(`清理下载任务 ${ taskId } 失败:`, taskError.message) } } @@ -1351,9 +1351,9 @@ const listenAction = (sftpClient, socket) => { if (remoteCleanupPromises.length > 0) { try { await Promise.all(remoteCleanupPromises) - consola.info(`连接断开时已清理 ${ remoteCleanupPromises.length } 个远程临时文件`) + logger.info(`连接断开时已清理 ${ remoteCleanupPromises.length } 个远程临时文件`) } catch (err) { - consola.warn('连接断开时清理远程临时文件部分失败:', err.message) + logger.warn('连接断开时清理远程临时文件部分失败:', err.message) } } @@ -1371,13 +1371,13 @@ const listenAction = (sftpClient, socket) => { if (task.tempFilePath && fs.existsSync(task.tempFilePath)) { try { fs.unlinkSync(task.tempFilePath) - consola.info(`连接断开,已清理临时文件: ${ task.tempFilePath }`) + logger.info(`连接断开,已清理临时文件: ${ task.tempFilePath }`) } catch (cleanupErr) { - consola.warn('清理临时文件失败:', cleanupErr.message) + logger.warn('清理临时文件失败:', cleanupErr.message) } } } catch (taskError) { - consola.warn(`清理上传任务 ${ taskId } 失败:`, taskError.message) + logger.warn(`清理上传任务 ${ taskId } 失败:`, taskError.message) } } @@ -1389,12 +1389,12 @@ const listenAction = (sftpClient, socket) => { try { cleanupCacheDir() } catch (cleanupError) { - consola.warn('清理本地缓存目录失败:', cleanupError.message) + logger.warn('清理本地缓存目录失败:', cleanupError.message) } - consola.info('SFTP资源清理完成') + logger.info('SFTP资源清理完成') } catch (disconnectError) { - consola.error('Socket断开连接清理过程中发生错误:', disconnectError.message) + logger.error('Socket断开连接清理过程中发生错误:', disconnectError.message) } }) @@ -1406,7 +1406,7 @@ const listenAction = (sftpClient, socket) => { for (const [taskId, task] of uploadTasks) { if (now - task.startTime > timeout) { - consola.warn(`清理超时上传任务: ${ taskId }`) + logger.warn(`清理超时上传任务: ${ taskId }`) if (task.abortController) { task.abortController.abort() } @@ -1418,9 +1418,9 @@ const listenAction = (sftpClient, socket) => { if (task.tempFilePath && fs.existsSync(task.tempFilePath)) { try { fs.unlinkSync(task.tempFilePath) - consola.info(`清理超时任务临时文件: ${ task.tempFilePath }`) + logger.info(`清理超时任务临时文件: ${ task.tempFilePath }`) } catch (cleanupErr) { - consola.warn('清理临时文件失败:', cleanupErr.message) + logger.warn('清理临时文件失败:', cleanupErr.message) } } @@ -1431,7 +1431,7 @@ const listenAction = (sftpClient, socket) => { // 检查并清理超时的下载任务 for (const [taskId, task] of downloadTasks) { if (now - task.startTime > timeout) { - consola.warn(`清理超时下载任务: ${ taskId }`) + logger.warn(`清理超时下载任务: ${ taskId }`) if (task.abortController) { task.abortController.abort() } @@ -1580,12 +1580,12 @@ module.exports = (httpServer) => { return } let sftpClient = new SFTPClient() - consola.success('sftp-v2 websocket 已连接') + logger.info('sftp-v2 websocket 已连接') let jumpSshClients = [] // 添加socket本身的错误处理 socket.on('error', (err) => { - consola.error('SFTP-v2 Socket连接错误:', err.message) + logger.error('SFTP-v2 Socket连接错误:', err.message) }) socket.on('ws_sftp', async ({ hostId }) => { @@ -1610,14 +1610,14 @@ module.exports = (httpServer) => { return } - consola.info('准备连接sftp-v2 面板:', host) - consola.log('连接信息', { username, port, authType }) + logger.info('准备连接sftp-v2 面板:', host) + logger.info('连接信息', { username, port, authType }) sftpClient.client = new SSHClient() // 添加错误处理器,防止程序崩溃 sftpClient.client.on('error', (err) => { - consola.error('SFTP SSH连接错误:', err.message) + logger.error('SFTP SSH连接错误:', err.message) try { // 发送SSH连接错误事件 socket.emit('shell_connection_error', { @@ -1625,40 +1625,40 @@ module.exports = (httpServer) => { code: err.code || 'UNKNOWN' }) } catch (emitError) { - consola.error('发送错误事件失败:', emitError.message) + logger.error('发送错误事件失败:', emitError.message) } }) sftpClient.client.on('end', () => { - consola.info('SSH连接正常结束') + logger.info('SSH连接正常结束') }) sftpClient.client.on('close', (hadError) => { if (hadError) { - consola.warn('SSH连接异常关闭') + logger.warn('SSH连接异常关闭') try { socket.emit('shell_connection_error', { message: 'SSH连接异常关闭', code: 'CONNECTION_CLOSED' }) } catch (emitError) { - consola.error('发送连接关闭事件失败:', emitError.message) + logger.error('发送连接关闭事件失败:', emitError.message) } } else { - consola.info('SSH连接已关闭') + logger.info('SSH连接已关闭') } }) // 添加未处理异常捕获 // sftpClient.client.on('timeout', () => { - // consola.warn('SSH连接超时') + // logger.warn('SSH连接超时') // try { // socket.emit('shell_connection_error', { // message: 'SSH连接超时', // code: 'CONNECTION_TIMEOUT' // }) // } catch (emitError) { - // consola.error('发送超时事件失败:', emitError.message) + // logger.error('发送超时事件失败:', emitError.message) // } // }) @@ -1678,23 +1678,23 @@ module.exports = (httpServer) => { try { rootList = await sftpClient.list('/') - consola.success('获取根目录成功') + logger.info('获取根目录成功') } catch (error) { - consola.error('获取根目录失败:', error.message) - consola.info('尝试获取当前目录') + logger.error('获取根目录失败:', error.message) + logger.info('尝试获取当前目录') isRootUser = false try { // 获取当前工作目录的绝对路径 currentWorkingDir = await sftpClient.cwd() - consola.info('当前工作目录:', currentWorkingDir) + logger.info('当前工作目录:', currentWorkingDir) rootList = await sftpClient.list(currentWorkingDir) - consola.success('获取当前目录成功') + logger.info('获取当前目录成功') } catch (cwdError) { - consola.warn('获取工作目录失败,使用相对路径:', cwdError.message) + logger.warn('获取工作目录失败,使用相对路径:', cwdError.message) currentWorkingDir = '~' rootList = await sftpClient.list('./') - consola.success('获取当前目录成功') + logger.info('获取当前目录成功') } } @@ -1707,10 +1707,10 @@ module.exports = (httpServer) => { isRootUser, currentPath: currentWorkingDir }) - consola.success('连接sftp-v2 成功:', host) + logger.info('连接sftp-v2 成功:', host) listenAction(sftpClient, socket) } catch (error) { - consola.error('连接sftp-v2 失败:', error.message) + logger.error('连接sftp-v2 失败:', error.message) // 发送详细的错误信息给前端 let errorMessage = error.message @@ -1729,7 +1729,7 @@ module.exports = (httpServer) => { await sftpClient.end() } } catch (cleanupError) { - consola.warn('清理SFTP客户端资源失败:', cleanupError.message) + logger.warn('清理SFTP客户端资源失败:', cleanupError.message) } // 清理跳板机连接 @@ -1737,9 +1737,9 @@ module.exports = (httpServer) => { jumpSshClients.forEach((client, index) => { try { client.end() - consola.info(`已清理跳板机连接 ${ index + 1 }`) + logger.info(`已清理跳板机连接 ${ index + 1 }`) } catch (cleanupError) { - consola.warn(`清理跳板机连接 ${ index + 1 } 失败:`, cleanupError.message) + logger.warn(`清理跳板机连接 ${ index + 1 } 失败:`, cleanupError.message) } }) } @@ -1747,12 +1747,12 @@ module.exports = (httpServer) => { socket.disconnect() } } catch (globalError) { - consola.error('SFTP连接处理过程中发生未预期错误:', globalError.message) + logger.error('SFTP连接处理过程中发生未预期错误:', globalError.message) try { socket.emit('connect_fail', `连接失败: ${ globalError.message }`) socket.disconnect() } catch (cleanupError) { - consola.error('清理失败连接时发生错误:', cleanupError.message) + logger.error('清理失败连接时发生错误:', cleanupError.message) } } }) @@ -1760,9 +1760,9 @@ module.exports = (httpServer) => { socket.on('disconnect', async () => { try { await sftpClient.end() - consola.info('sftp-v2 连接断开') + logger.info('sftp-v2 连接断开') } catch (error) { - consola.info('sftp断开连接失败:', error.message) + logger.info('sftp断开连接失败:', error.message) } finally { sftpClient = null // 这里不再清理缓存目录,因为在 listenAction 中的 disconnect 处理器会处理 diff --git a/server/app/socket/terminal.js b/server/app/socket/terminal.js index 8e898fc..c705002 100644 --- a/server/app/socket/terminal.js +++ b/server/app/socket/terminal.js @@ -39,7 +39,7 @@ function createInteractiveShell(socket, targetSSHClient) { // 检查SSH客户端连接状态 if (!targetSSHClient || !targetSSHClient._sock || !targetSSHClient._sock.writable) { const errorMsg = 'SSH客户端连接已断开,无法创建交互式终端' - consola.error(errorMsg) + logger.error(errorMsg) socket.emit('terminal_connect_fail', errorMsg) return reject(new Error(errorMsg)) } @@ -47,7 +47,7 @@ function createInteractiveShell(socket, targetSSHClient) { try { targetSSHClient.shell({ term: 'xterm-color' }, (err, stream) => { if (err) { - consola.error('创建交互式终端失败:', err.message) + logger.error('创建交互式终端失败:', err.message) socket.emit('terminal_connect_fail', err.message) return reject(err) } @@ -59,18 +59,18 @@ function createInteractiveShell(socket, targetSSHClient) { socket.emit('output', data.toString()) }) .on('close', () => { - consola.info('交互终端已关闭') + logger.info('交互终端已关闭') targetSSHClient.end() }) .on('error', (streamErr) => { - consola.error('终端流错误:', streamErr.message) + logger.error('终端流错误:', streamErr.message) socket.emit('terminal_connect_fail', streamErr.message) }) socket.emit('terminal_connect_shell_success') // 已连接终端,web端可以执行指令了 }) } catch (shellError) { - consola.error('调用shell方法失败:', shellError.message) + logger.error('调用shell方法失败:', shellError.message) socket.emit('terminal_connect_fail', shellError.message) reject(shellError) } @@ -96,7 +96,7 @@ async function getProxyConfig(proxyId) { password: proxyInfo.password || '' } } catch (error) { - consola.error('获取代理配置失败:', error.message) + logger.error('获取代理配置失败:', error.message) throw error } } @@ -119,7 +119,7 @@ async function handleProxyAndJumpHostConnection(options) { const proxyConfig = await getProxyConfig(proxyServer) if (proxyConfig) { const logMsg = `${ logPrefix }使用代理服务器: ${ proxyConfig.name } (${ proxyConfig.type.toUpperCase() }) - ${ proxyConfig.host }:${ proxyConfig.port }` - consola.info(logMsg) + logger.info(logMsg) // 向前端发送代理信息(如果socket存在且有对应方法) if (socket && socket.emit) { @@ -146,7 +146,7 @@ async function handleProxyAndJumpHostConnection(options) { } targetConnectionOptions.sock = proxySocket - consola.success(`${ logPrefix }代理连接建立成功: ${ host }`) + logger.info(`${ logPrefix }代理连接建立成功: ${ host }`) // 向前端发送成功信息 if (socket && socket.emit && typeof socket.emit === 'function') { @@ -166,7 +166,7 @@ async function handleProxyAndJumpHostConnection(options) { if (jumpHostResult) { targetConnectionOptions.sock = jumpHostResult.sock jumpSshClients = jumpHostResult.sshClients - consola.success(`${ logPrefix }跳板机连接成功`) + logger.info(`${ logPrefix }跳板机连接成功`) } } @@ -175,13 +175,13 @@ async function handleProxyAndJumpHostConnection(options) { jumpSshClients } } catch (error) { - consola.error(`${ logPrefix }连接失败:`, error.message) + logger.error(`${ logPrefix }连接失败:`, error.message) throw error } } async function createTerminal(hostId, socket, targetSSHClient, isInteractiveShell = true) { - consola.info(`准备创建${ isInteractiveShell ? '交互式' : '非交互式' }终端:${ hostId }`) + logger.info(`准备创建${ isInteractiveShell ? '交互式' : '非交互式' }终端:${ hostId }`) return new Promise(async (resolve) => { const targetHostInfo = await hostListDB.findOneAsync({ _id: hostId }) if (!targetHostInfo) return socket.emit('create_fail', `查找hostId【${ hostId }】凭证信息失败`) @@ -206,13 +206,13 @@ async function createTerminal(hostId, socket, targetSSHClient, isInteractiveShel socket.emit('terminal_print_info', `准备连接目标终端: ${ name } - ${ host }`) socket.emit('terminal_print_info', `连接信息: ssh ${ username }@${ host } -p ${ port } -> ${ authType }`) - consola.info('准备连接目标终端:', host) - consola.log('连接信息', { username, port, authType }) + logger.info('准备连接目标终端:', host) + logger.info('连接信息', { username, port, authType }) let closeNoticeFlag = false // 避免重复发送通知 targetSSHClient .on('ready', async () => { - consola.success('终端连接成功:', host) + logger.info('终端连接成功:', host) if (isInteractiveShell) { sendNoticeAsync('host_login', '终端登录', `别名: ${ name } \n IP:${ host } \n 端口:${ port } \n 状态: 登录成功`) socket.emit('terminal_print_info', `终端连接成功: ${ name } - ${ host }`) @@ -222,7 +222,7 @@ async function createTerminal(hostId, socket, targetSSHClient, isInteractiveShel let stream = await createInteractiveShell(socket, targetSSHClient) resolve({ stream, jumpSshClients }) } catch (shellError) { - consola.error('创建交互式终端失败:', host, shellError.message) + logger.error('创建交互式终端失败:', host, shellError.message) // 连接已经成功但创建shell失败,需要清理连接 targetSSHClient.end() jumpSshClients?.forEach(sshClient => sshClient && sshClient.end()) @@ -234,13 +234,13 @@ async function createTerminal(hostId, socket, targetSSHClient, isInteractiveShel .on('close', (err) => { if (closeNoticeFlag) return closeNoticeFlag = false const closeReason = err ? '发生错误导致连接断开' : '正常断开连接' - consola.info(`终端连接断开(${ closeReason }): ${ host }`) + logger.info(`终端连接断开(${ closeReason }): ${ host }`) socket.emit('terminal_connect_close', { reason: closeReason }) }) .on('error', (err) => { closeNoticeFlag = true sendNoticeAsync('host_login', '终端登录', `别名: ${ name } \n IP:${ host } \n 端口:${ port } \n 状态: 登录失败`) - consola.error('连接终端失败:', host, err.message) + logger.error('连接终端失败:', host, err.message) socket.emit('terminal_connect_fail', err.message) }) .on('keyboard-interactive', function (name, instructions, instructionsLang, prompts, finish) { @@ -252,7 +252,7 @@ async function createTerminal(hostId, socket, targetSSHClient, isInteractiveShel // debug: (info) => console.log(info) }) } catch (err) { - consola.error('创建终端失败: ', host, err.message) + logger.error('创建终端失败: ', host, err.message) socket.emit('terminal_create_fail', err.message) } }) @@ -278,7 +278,7 @@ function createServerIo(serverIo) { return } connectionCount++ - consola.success(`terminal websocket 已连接 - 当前连接数: ${ connectionCount }`) + logger.info(`terminal websocket 已连接 - 当前连接数: ${ connectionCount }`) let targetSSHClient = null let jumpSshClients = [] socket.on('ws_terminal', async ({ hostId }) => { @@ -288,7 +288,7 @@ function createServerIo(serverIo) { // 如果创建终端失败,result可能为undefined if (!result) { - consola.error('创建终端失败,未返回结果') + logger.error('创建终端失败,未返回结果') return } @@ -297,7 +297,7 @@ function createServerIo(serverIo) { const listenerInput = (key) => { if (!targetSSHClient || !targetSSHClient._sock || !targetSSHClient._sock.writable) { - consola.info('终端连接已关闭,禁止输入') + logger.info('终端连接已关闭,禁止输入') return } stream && stream.write(key) @@ -310,7 +310,7 @@ function createServerIo(serverIo) { socket.on('input', listenerInput) socket.on('resize', resizeShell) } catch (error) { - consola.error('ws_terminal事件处理失败:', error.message) + logger.error('ws_terminal事件处理失败:', error.message) socket.emit('terminal_connect_fail', `连接失败: ${ error.message }`) } }) @@ -329,7 +329,7 @@ function createServerIo(serverIo) { jumpSshClients?.forEach(sshClient => sshClient && sshClient.end()) targetSSHClient = null jumpSshClients = null - consola.info(`终端socket连接断开: ${ reason } - 当前连接数: ${ connectionCount }`) + logger.info(`终端socket连接断开: ${ reason } - 当前连接数: ${ connectionCount }`) }) }) } diff --git a/server/app/utils/decrypt-file.js b/server/app/utils/decrypt-file.js index cae3094..28c9e64 100644 --- a/server/app/utils/decrypt-file.js +++ b/server/app/utils/decrypt-file.js @@ -44,7 +44,7 @@ function decryptAndExecuteAsync(plusPath) { ) resolve(exports) } catch (error) { - consola.info('解锁plus功能失败: ', error.message) + logger.info('解锁plus功能失败: ', error.message) resolve(null) } }) diff --git a/server/app/utils/get-plus.js b/server/app/utils/get-plus.js index 4850e27..b64b9a8 100644 --- a/server/app/utils/get-plus.js +++ b/server/app/utils/get-plus.js @@ -11,15 +11,15 @@ async function getLicenseInfo(key = '') { let ip = '' if (global.serverIp && (Date.now() - global.getServerIpLastTime) / 1000 / 60 < 60) { ip = global.serverIp - consola.log('get server ip by cache: ', ip) + logger.info('通过缓存获取服务器IP: ', ip) } else { ip = await getLocalNetIP() global.serverIp = ip global.getServerIpLastTime = Date.now() - consola.log('get server ip by net: ', ip) + logger.info('通过接口获取服务器IP: ', ip) } if (!ip) { - consola.error('activate plus failed: get public ip failed') + logger.error('😒激活PLUS功能失败: get public ip failed') global.serverIp = '' return { success: false, msg: 'get public ip failed' } } @@ -33,7 +33,7 @@ async function getLicenseInfo(key = '') { const response = await requestWithFailover('/api/licenses/activate', requestOptions) if (!response.ok) { - consola.log('activate plus failed: ', response.status) + logger.info('😒激活PLUS功能失败: ', response.status) if (response.status === 403) { const errMsg = await response.json() throw { errMsg, clear: true } @@ -45,7 +45,7 @@ async function getLicenseInfo(key = '') { if (success) { let { decryptKey, expiryDate, usedIPCount, maxIPs, usedIPs } = data decryptKey = await AESEncryptAsync(decryptKey) - consola.success('activate plus success') + logger.info('🎉PLUS功能激活成功') const plusData = { key, decryptKey, expiryDate, usedIPCount, maxIPs, usedIPs } let count = await plusDB.countAsync({}) if (count === 0) { @@ -56,10 +56,10 @@ async function getLicenseInfo(key = '') { } return { success: true, msg: '激活成功' } } - consola.error('activate plus failed: ', data) + logger.error('😒激活PLUS功能失败: ', data) return { success: false, msg: '激活失败' } } catch (error) { - consola.error(`activate plus failed: ${ error.message || error.errMsg?.message }`) + logger.error(`😒激活PLUS功能失败: ${ error.message || error.errMsg?.message }`) if (error.clear) { await plusDB.removeAsync({}, { multi: true }) } diff --git a/server/app/utils/notify.js b/server/app/utils/notify.js index fdd0b61..6c1aeee 100644 --- a/server/app/utils/notify.js +++ b/server/app/utils/notify.js @@ -10,7 +10,7 @@ const notifyDB = new NotifyDB().getInstance() function sendServerChan(sendKey, title, content) { return new Promise((async (resolve, reject) => { try { - consola.info('server酱通知预发送: ', title) + logger.info('server酱通知预发送: ', title) const url = `https://sctapi.ftqq.com/${ sendKey }.send` const params = new URLSearchParams({ text: title, desp: content }) let { data } = await axios.post(url, params, { @@ -19,10 +19,10 @@ function sendServerChan(sendKey, title, content) { } }) resolve(data) - consola.info('server酱通知发送成功: ', title) + logger.info('server酱通知发送成功: ', title) } catch (error) { reject(error) - consola.error('server酱通知发送失败: ', error) + logger.error('server酱通知发送失败: ', error) } })) @@ -31,7 +31,7 @@ function sendServerChan(sendKey, title, content) { function sendEmail({ service, user, pass }, title, content) { return new Promise((async (resolve, reject) => { try { - consola.info('邮箱通知预发送: ', title) + logger.info('邮箱通知预发送: ', title) let transporter = nodemailer.createTransport({ service, auth: { @@ -46,11 +46,11 @@ function sendEmail({ service, user, pass }, title, content) { // text: '', // 纯文本版本内容,如果收件人的邮件客户端不支持HTML显示,就会显示这个文本 html: commonTemp(content) }) - consola.info('邮件通知发送成功: ', title) + logger.info('邮件通知发送成功: ', title) resolve() } catch (error) { reject(error) - consola.error('邮件通知发送失败: ', error) + logger.error('邮件通知发送失败: ', error) } })) } @@ -61,36 +61,36 @@ async function sendNoticeAsync(noticeAction, title, content) { let notifyList = await notifyDB.findAsync({}) let { sw } = notifyList.find((item) => item.type === noticeAction) // 获取对应动作的通知开关 // console.log('notify swtich: ', noticeAction, sw) - if (!sw) return consola.info('通知开关关闭, 不发送通知: ', noticeAction) + if (!sw) return logger.info('通知开关关闭, 不发送通知: ', noticeAction) let notifyConfig = await notifyConfigDB.findOneAsync({}) let { type } = notifyConfig - if (!type) return consola.error('通知类型不存在: ', type) + if (!type) return logger.error('通知类型不存在: ', type) title = `EasyNode-${ title }` content += `\n通知发送时间:${ new Date() }` switch (type) { case 'sct': let { sendKey } = notifyConfig['sct'] - if (!sendKey) return consola.info('未发送server酱通知, sendKey 为空') + if (!sendKey) return logger.info('未发送server酱通知, sendKey 为空') await sendServerChan(sendKey, title, content) break case 'email': let { service, user, pass } = notifyConfig['email'] - if (!service || !user || !pass) return consola.info('未发送邮件通知通知, 未配置邮箱: ', { service, user, pass }) + if (!service || !user || !pass) return logger.info('未发送邮件通知通知, 未配置邮箱: ', { service, user, pass }) await sendEmail({ service, user, pass }, title, content) break case 'tg': let { token, chatId } = notifyConfig['tg'] - if (!token || !chatId) return consola.info('未发送Telegram通知, 未配置token或chatId: ', { token, chatId }) + if (!token || !chatId) return logger.info('未发送Telegram通知, 未配置token或chatId: ', { token, chatId }) let { sendTg } = await decryptAndExecuteAsync(path.join(__dirname, 'plus.js')) - if (!sendTg) return consola.info('未发送Telegram通知, Plus功能解析失败') + if (!sendTg) return logger.info('未发送Telegram通知, Plus功能解析失败') await sendTg({ token, chatId }, title, content) break default: - consola.info('未配置通知类型: ', type) + logger.info('未配置通知类型: ', type) break } } catch (error) { - consola.error('通知发送失败: ', error) + logger.error('通知发送失败: ', error) } } diff --git a/server/app/utils/plus.js b/server/app/utils/plus.js index 8962434..f2aa854 100644 --- a/server/app/utils/plus.js +++ b/server/app/utils/plus.js @@ -1 +1 @@ -U2FsdGVkX193cbUwkwmNSHZRGKZ0AviTVx/Cp6OTfkZ958srbmgKihf5EeaIpKJtZDnqy9c9YiZVVOPfy5HTzYg30QVrOcDXnvTAIq1c1XSdeAQnINJsHFKDHoHbhI6iyixgey2hNbd6M8YvPAE78Hi3hrYRwz21t9DuRVU5G5qc387b3lWHTNb7OgHllNJ89QCP08n1IKfLB90qHVaGhRS457h3LTb6wPdaF9qt0CU8pSLUOE52FpFsgCb9iAedhBznij7dzL4wj2nohslS41PQ4U/lzKuxA2YPwJSQLOC3yBgqmN8s3nbEb6uN++K9udSnEuSCa0jJ6L4wFjGMokEY5/hii3iEzrTjwsXwIAAxZhe6fYieMOK4Uqc5c84X2jGTrrU0oScQbdylLePSWjX90eJtkyDUlemnp7AhHFYZjvtee+OLuQWQxdQlAyLb7nA34Zw3O6+f2Hs9FBEDbuxXvmT7wCPNWCa/iLo7YjmKRlrJ3dqYDrgGsMJtF1BRbx5PrSpUyyLveeeRZB0sNNmRyqEfhTyoiDtbykzpZ5oKvDjqdy1g6ANrhUFqiSK8d5feDI7rP0ELK1KEW1ZDViJ9DKzzgCg4XCcAA3Wvkjhs+Tns2GpUJG0nnsTJ6WjGk1l39lNYqQqw3QqtB099PGPgNedjsXYbe++B4eiBFCS2Kz384B51NmJ2bcskTpJTXLbMHS1h8paz2PGGqZoJMqqpMlPwkbRAdjpejzNJAuEiiZeUNf0RzIn/L8qT4SJAj7TSWs6F0csoXeYjKTMkJ5xjK0m3cUmDLqBwgIkUR2D+Yyqk7+nn0llL/fuIE2DVJUjzl8aOyYdConjW5Eg+TjH9eePOZZJ4CRRwLDmZ1IY= \ No newline at end of file +U2FsdGVkX18MF+tYSR1XUu4k5TYtD8puiurP+LyWIdTwRj6w6OWxSHLkHsTP2YLCiYL26JpviTPA0tSKHOZ7AjUs37SZ8/wNT8p0kJ0+kt+zK8Qqy7DufTRiFOhb4ARa5W160OON5013372657nxzRfJF8meKptqVtHFuKGHzq5r2G3kTM/XPvuaePOyKTW/yiFsiGfB1/3mvsCd59Ly18IeN261C735Yn3cMH+WxRkOaHuo3lH+XcoSwIIolvOHu/zdjlllgBfS/Z7NwBkdeO7l6iIr16TYMlqfeyuUcO27NZwJVArjxwp6kxMVwOWe0BRxryUzags7goHVEj91iUrxua+cyY4tJ98qwHBhPLAFUGXfTOoaWTGSp9hkjKBIF1TiY7Uf2uMw5kY8xY+11Epj972Fvx+cIRaXPwNw2U2UF2f3hml9YQvtQmaL9B7rpOQbvsTeEjE4Qbws8BSiODDghAMMMgpSP3xhXMCU6H/vVy+bJpKEkR4LeZtkioA+gFo4oRHqWzyfYeHbzs42UAbkrqJKNy9Gjr8+3TRaM9OEnLTpXxY6r7P5GPSDZm6qTxA/z/9OKuUFez0Ys8B7Z8ywDxa/JOz4p7qdwlT47nb+o2Q3t7dhrxt3k+o7z5f93B/zGhHN8DcI+jxiWzea5DSpKn8HBbSjoMcC+LugVcDZc4xAdyzgJHmil/pWOnXmbhix8P4MvFVmaghKix3gCOTkJWR+d7KI6InSm6//gyUk/t6V9eD5zBndorIhMKg3rih2ISOWSBuQPB5z8tH+tCKkvpOGZXQFQh0xWag5QZcWp8FCmbrQKmxtSd8kLacIakjk3HLBzlcB4u8GgRAA0tzWAL+hoHmVJ4O0GMHUrCc= \ No newline at end of file diff --git a/server/app/utils/tools.js b/server/app/utils/tools.js index fcb5138..7ebdc74 100644 --- a/server/app/utils/tools.js +++ b/server/app/utils/tools.js @@ -77,10 +77,8 @@ const getNetIPInfo = async (searchIp = '') => { } console.log(searchResult) let validInfo = searchResult.find(item => Boolean(item.country)) - consola.info('查询IP信息:', validInfo) return validInfo || { ip: '获取IP信息API出错,请排查或更新API', country: '未知', city: '未知', date } } catch (error) { - // consola.error('getIpInfo Error: ', error) return { ip: '未知', country: '未知', @@ -105,7 +103,6 @@ const getLocalNetIP = async () => { } if (ipCN.status === 'fulfilled') { let ip = ipCN.value?.data?.ip - consola.log('ipCN:', ip) if (ip) return ip } if (freeipapi.status === 'fulfilled') { @@ -279,7 +276,7 @@ const isAllowedIp = (requestIP) => { let allowedIPs = Array.isArray(global.ALLOWED_IPS) ? global.ALLOWED_IPS : [] if (allowedIPs.length === 0) return true let flag = allowedIPs.some(item => requestIP.includes(item)) - if (!flag) consola.warn(`requestIP:${ requestIP } 不在允许的IP列表中. 允许的IP列表:${ allowedIPs.join(',') }`) + if (!flag) logger.warn(`requestIP:${ requestIP } 不在允许的IP列表中. 允许的IP列表:${ allowedIPs.join(',') }`) return flag } @@ -328,7 +325,7 @@ async function requestWithFailover(path, options = {}, timeout = 5000) { for (let i = 0; i < plusServers.length; i++) { const server = plusServers[i] try { - consola.info(`Plus服务: ${ i + 1 }/${ plusServers.length }: ${ server }${ path }`) + logger.info(`Plus服务: ${ i + 1 }/${ plusServers.length }: ${ server }${ path }`) const response = await fetch(server + path, { method, @@ -339,13 +336,13 @@ async function requestWithFailover(path, options = {}, timeout = 5000) { // 如果状态码是200或403,不需要尝试下一个服务器 if (response.ok || response.status === 403) { - consola.info(`Plus服务: ${ i + 1 }/${ plusServers.length }: ${ server }${ path } 响应成功,状态码: ${ response.status }`) + logger.info(`Plus服务: ${ i + 1 }/${ plusServers.length }: ${ server }${ path } 响应成功,状态码: ${ response.status }`) return response } // 尝试下一个服务器 if (i < plusServers.length - 1) { - consola.info(`Plus服务: ${ i + 1 }/${ plusServers.length }: ${ server }${ path } 响应状态码 ${ response.status },尝试下一个服务器`) + logger.info(`Plus服务: ${ i + 1 }/${ plusServers.length }: ${ server }${ path } 响应状态码 ${ response.status },尝试下一个服务器`) continue } @@ -355,11 +352,11 @@ async function requestWithFailover(path, options = {}, timeout = 5000) { } catch (error) { // 如果不是最后一个服务,尝试下一个服务器[防止异常报错] if (i < plusServers.length - 1) { - consola.info(`Plus服务: ${ i + 1 }/${ plusServers.length }: ${ server }${ path } 请求失败: ${ error.message },尝试下一个服务器`) + logger.info(`Plus服务: ${ i + 1 }/${ plusServers.length }: ${ server }${ path } 请求失败: ${ error.message },尝试下一个服务器`) continue } // 如果是最后一个服务器,抛出错误 - consola.error(`Plus服务: 所有服务器请求失败: ${ error.message }`) + logger.error(`Plus服务: 所有服务器请求失败: ${ error.message }`) throw error } } diff --git a/server/app/utils/verify-auth.js b/server/app/utils/verify-auth.js index f9e282b..20207aa 100644 --- a/server/app/utils/verify-auth.js +++ b/server/app/utils/verify-auth.js @@ -23,7 +23,7 @@ const verifyAuthSync = async (token, userId) => { } return { code: enumLoginCode.SUCCESS, success: true } // 验证成功 } catch (err) { - consola.error('用户身份校验失败: ', err.message) + logger.error('用户身份校验失败: ', err.message) return { code: enumLoginCode.ERROR_TOKEN } } } diff --git a/server/index.js b/server/index.js index 33722be..0a2c2f4 100644 --- a/server/index.js +++ b/server/index.js @@ -1,5 +1,3 @@ -const consola = require('consola') -global.consola = consola global.rpdToken = Array.from({ length:32 },()=>Math.random().toString(36)[2]).join('') require('dotenv').config() require('./app/main.js') diff --git a/server/package.json b/server/package.json index 27af13a..12e9371 100644 --- a/server/package.json +++ b/server/package.json @@ -23,7 +23,6 @@ "@seald-io/nedb": "^4.0.4", "axios": "^1.12.0", "chardet": "^2.1.1", - "consola": "^3.2.3", "cross-env": "^7.0.3", "crypto-js": "^4.2.0", "dotenv": "^16.4.5", diff --git a/yarn.lock b/yarn.lock index 20203e9..afd3798 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2125,11 +2125,6 @@ confbox@^0.2.1: resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.2.1.tgz#ae39f2c99699afa451d00206479f15f9a1208a8b" integrity sha512-hkT3yDPFbs95mNCy1+7qNKC6Pro+/ibzYxtM2iqEigpf0sVw+bg4Zh9/snjsBcf990vfIsg5+1U7VyiyBb3etg== -consola@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" - integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== - content-disposition@~0.5.2: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"