1、index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
const { execSync, spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const https = require('https');

const BASE_DIR = '/home/container';
const DASHBOARD_DIR = path.join(BASE_DIR, 'dashboard');
const BINARY_NAME = 'dashboard-linux-amd64';

const DOWNLOAD_URL = 'https://github.com/naiba/nezha/releases/download/v0.20.13/dashboard-linux-amd64.zip';

console.log('🚀 哪吒 Dashboard 一键启动脚本(最终修复版)');

function runCommand(cmd, options = {}) {
console.log(`执行: ${cmd}`);
try {
execSync(cmd, { stdio: 'inherit', ...options });
return true;
} catch (e) {
console.error(`❌ 执行失败: ${cmd}`);
return false;
}
}

async function downloadFile(url, dest) {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(dest);
https.get(url, (res) => {
if (res.statusCode === 301 || res.statusCode === 302) {
return downloadFile(res.headers.location, dest).then(resolve).catch(reject);
}
res.pipe(file);
file.on('finish', () => { file.close(); resolve(); });
}).on('error', (err) => { fs.unlinkSync(dest); reject(err); });
});
}

async function ensureResources() {
const dirs = [
'resource/template/theme-custom',
'resource/static/custom',
'data'
];

dirs.forEach(dir => {
fs.mkdirSync(path.join(DASHBOARD_DIR, dir), { recursive: true });
});

// 创建最小占位模板文件,防止 ParseGlob 报错
const placeholder = path.join(DASHBOARD_DIR, 'resource/template/theme-custom/index.html');
if (!fs.existsSync(placeholder)) {
fs.writeFileSync(placeholder, '<!DOCTYPE html><html><head><title>Nezha Dashboard</title></head><body><h1>哪吒面板启动成功</h1></body></html>');
}

console.log('✅ 资源目录与模板文件已准备完成');
}

async function main() {
fs.mkdirSync(DASHBOARD_DIR, { recursive: true });
process.chdir(DASHBOARD_DIR);

if (!fs.existsSync(path.join(DASHBOARD_DIR, BINARY_NAME))) {
console.log('📥 下载哪吒 Dashboard...');
await downloadFile(DOWNLOAD_URL, 'dashboard.zip');
runCommand('unzip -o dashboard.zip');
if (fs.existsSync('dashboard.zip')) fs.unlinkSync('dashboard.zip');
} else {
console.log('✅ 二进制已存在');
}

await ensureResources();
runCommand(`chmod +x ${BINARY_NAME}`);

console.log('\n🌟 正在启动哪吒 Dashboard (端口 20234)...');
console.log('访问地址 → http://你的IP:20234\n');

const dashboard = spawn(`./${BINARY_NAME}`, [], {
stdio: 'inherit',
cwd: DASHBOARD_DIR
});

dashboard.on('error', err => console.error('启动错误:', err));
}

main().catch(err => console.error('脚本异常:', err));

2、package.json

1
2
3
4
5
6
7
8
9
{
"name": "nezha-dashboard",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {}
}