183 lines
5.7 KiB
JavaScript
183 lines
5.7 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Pixiv 后端服务器启动脚本
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
|
|
// 只在 Windows 环境下设置终端标题
|
|
if (os.platform() === 'win32') {
|
|
process.title = 'Pixiv Manager';
|
|
}
|
|
|
|
// 加载配置文件
|
|
function loadConfig() {
|
|
// 检测是否在pkg打包环境中运行
|
|
const isPackaged = process.pkg !== undefined;
|
|
|
|
// 在打包环境中,配置文件在当前工作目录;在开发环境中,配置文件在上级目录
|
|
const configPath = isPackaged
|
|
? path.join(process.cwd(), 'config.json') // 打包环境:当前工作目录
|
|
: path.join(__dirname, '..', 'config.json'); // 开发环境:上级目录
|
|
let config = {
|
|
server: {
|
|
port: 3000,
|
|
autoOpenBrowser: true
|
|
},
|
|
proxy: {
|
|
port: null,
|
|
enabled: false
|
|
},
|
|
logging: {
|
|
level: "INFO"
|
|
},
|
|
system: {
|
|
threadPoolSize: 16
|
|
}
|
|
};
|
|
|
|
try {
|
|
console.log(`检测环境: ${isPackaged ? '打包环境' : '开发环境'}`);
|
|
console.log(`配置文件路径: ${configPath}`);
|
|
|
|
if (fs.existsSync(configPath)) {
|
|
const configData = fs.readFileSync(configPath, 'utf8');
|
|
const userConfig = JSON.parse(configData);
|
|
|
|
// 合并配置,用户配置覆盖默认配置
|
|
config = {
|
|
...config,
|
|
server: { ...config.server, ...userConfig.server },
|
|
proxy: { ...config.proxy, ...userConfig.proxy },
|
|
logging: { ...config.logging, ...userConfig.logging },
|
|
system: { ...config.system, ...userConfig.system }
|
|
};
|
|
console.log('已加载配置文件');
|
|
} else {
|
|
// 如果配置文件不存在,创建默认配置文件
|
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
console.log('已创建默认配置文件:', configPath);
|
|
}
|
|
} catch (error) {
|
|
console.error('读取配置文件失败,使用默认配置:', error.message);
|
|
}
|
|
|
|
return config;
|
|
}
|
|
// 加载配置
|
|
const config = loadConfig();
|
|
|
|
// 重要:必须在任何其他模块导入之前设置线程池大小
|
|
// 解决多个下载任务时的SSH连接阻塞问题
|
|
if (!process.env.UV_THREADPOOL_SIZE) {
|
|
process.env.UV_THREADPOOL_SIZE = config.system.threadPoolSize.toString();
|
|
}
|
|
|
|
// 设置环境变量
|
|
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
|
|
|
// 设置日志级别环境变量
|
|
if (config.logging.level) {
|
|
process.env.LOG_LEVEL = config.logging.level.toLowerCase();
|
|
}
|
|
|
|
// 在设置环境变量后导入logger和服务器
|
|
const { defaultLogger } = require('./utils/logger');
|
|
const logger = defaultLogger.child('Start');
|
|
const PixivServer = require('./server');
|
|
|
|
// 如果配置了代理,设置环境变量
|
|
if (config.proxy.enabled === true || (config.proxy.enabled === "auto" && config.proxy.port)) {
|
|
// 显式配置代理端口
|
|
if (config.proxy.port) {
|
|
process.env.PROXY_PORT = config.proxy.port.toString();
|
|
logger.info(`代理端口已设置为: ${config.proxy.port}`);
|
|
}
|
|
} else if (config.proxy.enabled === "auto") {
|
|
// 自动检测系统代理
|
|
const systemProxy = process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy;
|
|
if (systemProxy) {
|
|
logger.info(`检测到系统代理: ${systemProxy}`);
|
|
// 从系统代理URL中提取端口
|
|
const match = systemProxy.match(/http:\/\/127\.0\.0\.1:(\d+)/);
|
|
if (match) {
|
|
process.env.PROXY_PORT = match[1];
|
|
logger.info(`自动设置代理端口为: ${match[1]}`);
|
|
}
|
|
} else {
|
|
logger.info('未检测到系统代理,将尝试使用系统代理环境变量');
|
|
}
|
|
}
|
|
|
|
// 设置服务器端口
|
|
if (config.server.port) {
|
|
process.env.PORT = config.server.port.toString();
|
|
logger.info(`服务器端口已设置为: ${config.server.port}`);
|
|
}
|
|
|
|
// 输出日志级别信息
|
|
logger.info(`日志级别: ${config.logging.level}`);
|
|
|
|
// 设置自动打开浏览器选项
|
|
if (config.server.autoOpenBrowser !== undefined) {
|
|
process.env.AUTO_OPEN_BROWSER = config.server.autoOpenBrowser.toString();
|
|
logger.info(`自动打开浏览器: ${config.server.autoOpenBrowser ? '启用' : '禁用'}`);
|
|
}
|
|
|
|
logger.info('启动 Pixiv 后端服务器...');
|
|
// logger.info('配置信息:', {
|
|
// serverPort: config.server.port,
|
|
// proxyMode: config.proxy.enabled,
|
|
// proxyPort: config.proxy.enabled === true && config.proxy.port ? config.proxy.port :
|
|
// (config.proxy.enabled === "auto" ? '自动检测' : '未启用'),
|
|
// logLevel: config.logging.level,
|
|
// autoOpenBrowser: config.server.autoOpenBrowser,
|
|
// threadPoolSize: config.system.threadPoolSize
|
|
// });
|
|
|
|
// 创建服务器实例
|
|
const server = new PixivServer();
|
|
|
|
// 处理进程信号
|
|
process.on('SIGINT', async () => {
|
|
logger.info('收到 SIGINT 信号,正在关闭服务器...');
|
|
await server.shutdown();
|
|
});
|
|
|
|
process.on('SIGTERM', async () => {
|
|
logger.info('收到 SIGTERM 信号,正在关闭服务器...');
|
|
await server.shutdown();
|
|
});
|
|
|
|
// 处理未捕获的异常
|
|
process.on('uncaughtException', error => {
|
|
logger.error('未捕获的异常', error);
|
|
logger.error('异常堆栈:', error.stack);
|
|
process.exit(1);
|
|
});
|
|
|
|
process.on('unhandledRejection', (reason, promise) => {
|
|
logger.error('未处理的 Promise 拒绝');
|
|
logger.error('拒绝原因:', reason);
|
|
if (reason instanceof Error) {
|
|
logger.error('错误堆栈:', reason.stack);
|
|
}
|
|
logger.error('Promise:', promise);
|
|
|
|
// 不要立即退出进程,而是记录错误并继续运行
|
|
// 这样可以避免因为自动恢复任务的小错误而停止整个服务
|
|
logger.warn('继续运行服务器,但建议检查上述错误');
|
|
});
|
|
|
|
// 启动服务器
|
|
server
|
|
.init()
|
|
.then(() => server.start())
|
|
.catch(error => {
|
|
logger.error('服务器启动失败', error);
|
|
process.exit(1);
|
|
});
|