@oxiaom/adoremix 1.0.35 → 1.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli.js +40 -0
- package/src/doctor.js +19 -8
- package/src/nginx.js +132 -0
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -425,6 +425,46 @@ function buildProgram() {
|
|
|
425
425
|
}
|
|
426
426
|
});
|
|
427
427
|
|
|
428
|
+
const nginx = program
|
|
429
|
+
.command('nginx')
|
|
430
|
+
.description('NGINX 静态加速:媒体文件走 nginx(端口 9876)减轻设备服务压力,开机自启');
|
|
431
|
+
|
|
432
|
+
nginx
|
|
433
|
+
.command('install')
|
|
434
|
+
.description('安装并配置 nginx(端口 9876 挂 etc/docroot,preurl 自动改为 IP:9876)')
|
|
435
|
+
.option('--workdir <path>')
|
|
436
|
+
.action((opts) => {
|
|
437
|
+
const mod = require('./nginx');
|
|
438
|
+
try {
|
|
439
|
+
process.exitCode = mod.install(resolveWorkdir(opts.workdir));
|
|
440
|
+
} catch (e) {
|
|
441
|
+
logger.error(e.message);
|
|
442
|
+
process.exitCode = 1;
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
nginx
|
|
447
|
+
.command('uninstall')
|
|
448
|
+
.description('卸载 nginx 加速(还原 preurl 到原端口)')
|
|
449
|
+
.option('--workdir <path>')
|
|
450
|
+
.action((opts) => {
|
|
451
|
+
const mod = require('./nginx');
|
|
452
|
+
try {
|
|
453
|
+
process.exitCode = mod.uninstall(resolveWorkdir(opts.workdir));
|
|
454
|
+
} catch (e) {
|
|
455
|
+
logger.error(e.message);
|
|
456
|
+
process.exitCode = 1;
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
nginx
|
|
461
|
+
.command('status')
|
|
462
|
+
.description('查看 nginx 运行状态')
|
|
463
|
+
.action(() => {
|
|
464
|
+
const mod = require('./nginx');
|
|
465
|
+
try { process.exitCode = mod.status(); } catch (e) { logger.error(e.message); process.exitCode = 1; }
|
|
466
|
+
});
|
|
467
|
+
|
|
428
468
|
program
|
|
429
469
|
.command('uninstall')
|
|
430
470
|
.description('完全卸载:停服务 + 卸载 systemd 服务;加 --purge 删除工作目录(含配置/数据库,不可恢复)')
|
package/src/doctor.js
CHANGED
|
@@ -335,24 +335,35 @@ function runDoctor(workdir, opts) {
|
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
337
|
|
|
338
|
-
// C. Qt
|
|
339
|
-
|
|
338
|
+
// C. 捆绑库一致性:自包含包中,Qt/ICU/pcre/z/glib/krb5/sqlite/ssl 等应全部从捆绑 lib/ 解析。
|
|
339
|
+
// 若某个库从系统路径加载,说明捆绑不完整或 RPATH 未生效,版本可能不匹配(如系统 ICU72 vs 捆绑 ICU67)。
|
|
340
|
+
const BUNDLED_PREFIXES = [
|
|
341
|
+
'libQt5', 'libicu', 'libpcre', 'libz', 'libglib-2.0',
|
|
342
|
+
'libgssapi_krb5', 'libkrb5', 'libk5crypto', 'libkrb5support',
|
|
343
|
+
'libcom_err', 'libkeyutils', 'libdouble-conversion', 'libsqlite3',
|
|
344
|
+
'libssl', 'libcrypto', 'libhiredis', 'libmariadb', 'libopus', 'libmp3lame'
|
|
345
|
+
];
|
|
340
346
|
const libDirNorm = path.normalize(libDir);
|
|
341
|
-
|
|
347
|
+
let bundledChecked = 0;
|
|
348
|
+
let bundledFromSystem = 0;
|
|
349
|
+
for (const so of Object.keys(resolved)) {
|
|
350
|
+
if (!BUNDLED_PREFIXES.some(p => so.startsWith(p))) continue;
|
|
351
|
+
bundledChecked++;
|
|
342
352
|
const rp = resolved[so];
|
|
343
353
|
if (!rp) {
|
|
344
|
-
issues.push({ type: '
|
|
345
|
-
logger.error(`❌ ${so}
|
|
354
|
+
issues.push({ type: 'bundled-lib-missing', severity: 'error', msg: `${so} 未能解析(应捆绑在 lib/)` });
|
|
355
|
+
logger.error(`❌ ${so} 未解析(捆绑库加载失败)`);
|
|
346
356
|
} else if (!path.normalize(rp).startsWith(libDirNorm + path.sep)) {
|
|
347
|
-
|
|
348
|
-
|
|
357
|
+
bundledFromSystem++;
|
|
358
|
+
issues.push({ type: 'bundled-lib-system', severity: 'error', msg: `${so} 从系统加载:${rp}(应捆绑 ${libDir}),版本可能不匹配` });
|
|
359
|
+
logger.error(`❌ ${so} => ${rp}(非捆绑,可能版本不匹配)`);
|
|
349
360
|
} else {
|
|
350
361
|
logger.ok(`✓ ${so} => 捆绑 ${path.basename(rp)}`);
|
|
351
362
|
}
|
|
352
363
|
}
|
|
353
364
|
|
|
354
365
|
// D. 依赖解析统计(信息性)
|
|
355
|
-
logger.log(` 已解析依赖 ${Object.keys(resolved).length} 项,缺库 ${missing.length}
|
|
366
|
+
logger.log(` 已解析依赖 ${Object.keys(resolved).length} 项,缺库 ${missing.length} 项,捆绑库 ${bundledChecked} 项(其中从系统加载 ${bundledFromSystem} 项)`);
|
|
356
367
|
} catch (e) {
|
|
357
368
|
logger.warn(`⚠ ldd 检查失败(非 Linux 或权限问题):${e.message.split('\n')[0]}`);
|
|
358
369
|
}
|
package/src/nginx.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
const logger = require('./logger');
|
|
7
|
+
const config = require('./config');
|
|
8
|
+
|
|
9
|
+
const NGINX_PORT = 9876;
|
|
10
|
+
const NGINX_CONF = '/etc/nginx/conf.d/adoremix.conf';
|
|
11
|
+
|
|
12
|
+
function whichNginx() {
|
|
13
|
+
try { return execSync('which nginx', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim(); }
|
|
14
|
+
catch (e) { return null; }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function buildConfig(workdir) {
|
|
18
|
+
const docroot = path.join(workdir, 'etc', 'docroot');
|
|
19
|
+
return `# AdoreMix 静态加速(由 adoremix nginx install 生成)
|
|
20
|
+
# 用途:媒体文件(mp3 等)走 nginx 直接出,减轻 AdoreMix 设备服务压力。
|
|
21
|
+
server {
|
|
22
|
+
listen ${NGINX_PORT};
|
|
23
|
+
server_name _;
|
|
24
|
+
|
|
25
|
+
root ${docroot};
|
|
26
|
+
index index.html;
|
|
27
|
+
|
|
28
|
+
client_max_body_size 100m;
|
|
29
|
+
access_log off;
|
|
30
|
+
|
|
31
|
+
# 媒体文件:mp3 等大文件长缓存
|
|
32
|
+
location ~* \\.(mp3|wav|m4a|aac|ogg|opus|flac)$ {
|
|
33
|
+
expires 30d;
|
|
34
|
+
add_header Cache-Control "public, immutable";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# 静态资源缓存
|
|
38
|
+
location ~* \\.(js|css|png|jpg|jpeg|gif|svg|woff2?|ttf|ico)$ {
|
|
39
|
+
expires 7d;
|
|
40
|
+
add_header Cache-Control "public";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
location / {
|
|
44
|
+
try_files $uri $uri/ =404;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function install(workdir) {
|
|
51
|
+
if (process.platform !== 'linux') {
|
|
52
|
+
logger.error('NGINX 静态加速仅支持 Linux');
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 1. 检测/安装 nginx
|
|
57
|
+
if (!whichNginx()) {
|
|
58
|
+
logger.info('未检测到 nginx,尝试 apt 安装...');
|
|
59
|
+
try {
|
|
60
|
+
execSync('apt-get update && apt-get install -y nginx', { stdio: 'inherit' });
|
|
61
|
+
} catch (e) {
|
|
62
|
+
logger.error(`nginx 安装失败:${(e.message || '').split('\n')[0]}`);
|
|
63
|
+
logger.warn(' 请手动安装:sudo apt-get install -y nginx');
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
logger.ok('nginx 已就绪');
|
|
68
|
+
|
|
69
|
+
// 2. 写配置
|
|
70
|
+
try {
|
|
71
|
+
fs.mkdirSync('/etc/nginx/conf.d', { recursive: true });
|
|
72
|
+
fs.writeFileSync(NGINX_CONF, buildConfig(workdir), 'utf8');
|
|
73
|
+
logger.ok(`写入 ${NGINX_CONF}`);
|
|
74
|
+
} catch (e) {
|
|
75
|
+
logger.error(`写 nginx 配置失败:${(e.message || '').split('\n')[0]}(可能需要 root)`);
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 3. 测试配置
|
|
80
|
+
try {
|
|
81
|
+
execSync('nginx -t', { stdio: 'inherit' });
|
|
82
|
+
} catch (e) {
|
|
83
|
+
logger.error('nginx 配置校验失败,请检查');
|
|
84
|
+
return 1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 4. 开机自启 + 启动
|
|
88
|
+
try {
|
|
89
|
+
execSync('systemctl enable nginx', { stdio: 'inherit' });
|
|
90
|
+
execSync('systemctl restart nginx', { stdio: 'inherit' });
|
|
91
|
+
logger.ok('nginx 已启动并设为开机自启');
|
|
92
|
+
} catch (e) {
|
|
93
|
+
logger.warn(`systemctl 操作失败:${(e.message || '').split('\n')[0]}(可能非 systemd 环境,请手动启动)`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 5. preurl 自动改为 IP:9876
|
|
97
|
+
const ip = config.getConfigValue(workdir, 'Settings.LocalIP') || '127.0.0.1';
|
|
98
|
+
const preurl = `http://${ip}:${NGINX_PORT}/`;
|
|
99
|
+
config.setConfigValue(workdir, 'Settings.preurl', preurl);
|
|
100
|
+
logger.ok(`preurl 已更新为 ${preurl}(媒体文件走 nginx)`);
|
|
101
|
+
logger.log('改完后记得:adoremix restart');
|
|
102
|
+
return 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function uninstall(workdir) {
|
|
106
|
+
if (process.platform !== 'linux') return 0;
|
|
107
|
+
try { execSync('systemctl disable nginx', { stdio: 'ignore' }); } catch (e) {}
|
|
108
|
+
try { execSync('systemctl stop nginx', { stdio: 'ignore' }); } catch (e) {}
|
|
109
|
+
try { fs.unlinkSync(NGINX_CONF); logger.ok('已删除 nginx 配置'); } catch (e) {}
|
|
110
|
+
|
|
111
|
+
// 还原 preurl 到原 HTTP 端口
|
|
112
|
+
const ip = config.getConfigValue(workdir, 'Settings.LocalIP') || '127.0.0.1';
|
|
113
|
+
const port = config.getConfigValue(workdir, 'listener.port') || 12080;
|
|
114
|
+
config.setConfigValue(workdir, 'Settings.preurl', `http://${ip}:${port}/`);
|
|
115
|
+
logger.ok(`preurl 已还原为 http://${ip}:${port}/`);
|
|
116
|
+
logger.log('改完后记得:adoremix restart');
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function status() {
|
|
121
|
+
if (process.platform !== 'linux') { logger.warn('仅 Linux 支持'); return 1; }
|
|
122
|
+
try {
|
|
123
|
+
const out = execSync('systemctl is-active nginx', { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
124
|
+
if (out === 'active') { logger.ok('nginx 运行中'); return 0; }
|
|
125
|
+
logger.warn(`nginx 状态:${out}`); return 1;
|
|
126
|
+
} catch (e) {
|
|
127
|
+
logger.warn('nginx 未运行');
|
|
128
|
+
return 1;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = { install, uninstall, status, NGINX_PORT };
|