habppyar commited on
Commit
e094011
·
verified ·
1 Parent(s): 542da58

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +59 -48
server.js CHANGED
@@ -3,26 +3,24 @@ const http = require('http');
3
  const os = require('os');
4
  const fs = require('fs');
5
  const { exec } = require('child_process');
6
- const path = require('path');
7
 
8
  // --- Hugging Face Spaces 核心配置 ---
9
- // 必须监听所有接口,以响应外部请求
10
  const HOST = '0.0.0.0';
11
- // 必须使用 Hugging Face 指定的端口
12
  const PORT = process.env.PORT || 7860;
13
 
14
- // --- 辅助函数:获取磁盘使用情况 ---
15
  function getDiskUsage() {
16
  try {
17
- const stats = fs.statfsSync('/'); // 获取目录的磁盘信息
 
18
  const total = stats.bsize * stats.blocks;
19
  const free = stats.bsize * stats.bfree;
20
  const used = total - free;
21
  const usagePercent = ((used / total) * 100).toFixed(2);
22
  return {
23
- total: (total / (1024 ** 3)).toFixed(2), // GB
24
- used: (used / (1024 ** 3)).toFixed(2), // GB
25
- free: (free / (1024 ** 3)).toFixed(2), // GB
26
  usagePercent: `${usagePercent}%`
27
  };
28
  } catch (error) {
@@ -30,21 +28,17 @@ function getDiskUsage() {
30
  }
31
  }
32
 
33
- // --- 辅助函数:获取出口公网IP(cURL方式)---
34
  function getPublicIP() {
35
  return new Promise(resolve => {
36
- // Hugging Face Spaces 容器内通常可以访问外部网络
37
  exec('curl -s --max-time 5 ifconfig.me', (err, stdout) => {
38
- if (err) {
39
- resolve('无法获取公网IP (可能为NAT环境)');
40
- } else {
41
- resolve(stdout.trim());
42
- }
43
  });
44
  });
45
  }
46
 
47
- // --- 辅助函数:获取所有环境变量(过滤掉敏感信息)---
48
  function getSafeEnvVars() {
49
  const safeVars = {};
50
  const sensitiveKeys = ['PASSWORD', 'SECRET', 'TOKEN', 'KEY'];
@@ -58,29 +52,47 @@ function getSafeEnvVars() {
58
  return safeVars;
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  // --- 创建 HTTP 服务器 ---
62
  const server = http.createServer(async (req, res) => {
63
- // 1. 获取动态信息
64
  const publicIP = await getPublicIP();
65
  const diskInfo = getDiskUsage();
 
66
 
67
- // 2. 系统与硬件信息 (通过 os 模块)
68
  const cpuInfo = os.cpus()[0];
69
- const totalMem = (os.totalmem() / (1024 ** 3)).toFixed(2); // GB
70
- const freeMem = (os.freemem() / (1024 ** 3)).toFixed(2); // GB
71
- const usedMem = (totalMem - freeMem).toFixed(2); // GB
72
  const systemUptime = Math.floor(os.uptime() / 60) + ' 分钟';
73
 
74
- // 3. 关键环境检查
75
- const isNodePathSet = !!process.env.NODE_PATH;
76
- const isDataDirWritable = fs.accessSync('/data', fs.constants.W_OK) === undefined; // 检查 /data 是否可写
77
- const isHfHomeSet = !!process.env.HF_HOME;
 
 
78
 
79
- // 4. 构建用于展示的数据模型
80
  const envReport = {
81
- // ========== 1. 访问信息 ==========
82
  access: {
83
- spaceUrl: `https://${process.env.SPACE_ID?.replace('/', '-')}.hf.space` || '未知 (请通过公网域名访问)',
84
  publicIP: publicIP,
85
  internalIP: (() => {
86
  const interfaces = os.networkInterfaces();
@@ -92,10 +104,10 @@ const server = http.createServer(async (req, res) => {
92
  return '127.0.0.1';
93
  })(),
94
  hostname: os.hostname(),
95
- spaceId: process.env.SPACE_ID || '未',
96
- spaceRepoName: process.env.SPACE_REPO_NAME || '未',
97
  },
98
- // ========== 2. 硬件资源 (免费层标准) ==========
99
  hardware: {
100
  cpuModel: cpuInfo?.model || '未知',
101
  cpuCores: os.cpus().length,
@@ -106,38 +118,37 @@ const server = http.createServer(async (req, res) => {
106
  uptime: systemUptime,
107
  expectedFreeTier: '2 vCPU / 16GB RAM / 50GB 临时磁盘'
108
  },
109
- // ========== 3. Node.js 环境 ==========
110
  nodeEnv: {
111
  version: process.version,
112
  platform: process.platform,
113
  arch: process.arch,
114
  execPath: process.execPath,
115
  cwd: process.cwd(),
116
- nodePath: isNodePathSet ? process.env.NODE_PATH : '未设置'
117
  },
118
- // ========== 4. 容器与权限 ==========
119
  container: {
120
- userId: process.getuid?.(),
121
- groupId: process.getgid?.(),
122
- expectedUserId: '1000 (Hugging Face 默认用户ID)',
123
- isDataDirWritable: isDataDirWritable,
124
- hfHome: process.env.HF_HOME || '未设置 (可设置为 /data/.huggingface 加速重启)',
125
- // 检测是否使用了 Persistent Storage
126
- persistentStorageMounted: fs.existsSync('/data'),
 
127
  },
128
- // ========== 5. 关键环境变量 (安全过滤) ==========
129
  envVars: getSafeEnvVars(),
130
- // ========== 6. 部署建议 ==========
131
  suggestions: [
132
  '✅ 必须监听 0.0.0.0,并在 README.md 中设置 app_port: 7860',
133
- '✅ 强烈建议为敏感信息(如 OPENCODE_PASSWORD)使用 HF Secrets,勿硬编码',
134
- '✅ 如需数据持久化,请考虑升级 Persistent Storage 或将数据备份到 HF Dataset',
135
- '✅ 容器默认以用户 ID 1000 运行,Dockerfile 中需创建此用户避免权限问题',
136
- '✅ 可设置 HF_HOME=/data/.huggingface 以加速 Hugging Face 库的重复启动',
137
  ]
138
  };
139
 
140
- // 5. 输出美观的 JSON 报告
141
  res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
142
  res.end(JSON.stringify(envReport, null, 2));
143
  });
 
3
  const os = require('os');
4
  const fs = require('fs');
5
  const { exec } = require('child_process');
 
6
 
7
  // --- Hugging Face Spaces 核心配置 ---
 
8
  const HOST = '0.0.0.0';
 
9
  const PORT = process.env.PORT || 7860;
10
 
11
+ // --- 辅助函数:获取磁盘使用情况(需要处理 /data 可能不存在)---
12
  function getDiskUsage() {
13
  try {
14
+ // 获取当前工作目录所在文件系统(通常是容器根目录)
15
+ const stats = fs.statfsSync('/');
16
  const total = stats.bsize * stats.blocks;
17
  const free = stats.bsize * stats.bfree;
18
  const used = total - free;
19
  const usagePercent = ((used / total) * 100).toFixed(2);
20
  return {
21
+ total: (total / (1024 ** 3)).toFixed(2),
22
+ used: (used / (1024 ** 3)).toFixed(2),
23
+ free: (free / (1024 ** 3)).toFixed(2),
24
  usagePercent: `${usagePercent}%`
25
  };
26
  } catch (error) {
 
28
  }
29
  }
30
 
31
+ // --- 辅助函数:获取出口公网IP---
32
  function getPublicIP() {
33
  return new Promise(resolve => {
 
34
  exec('curl -s --max-time 5 ifconfig.me', (err, stdout) => {
35
+ if (err) resolve('无法获取公网IP (可能为NAT环境)');
36
+ else resolve(stdout.trim());
 
 
 
37
  });
38
  });
39
  }
40
 
41
+ // --- 辅助函数:安全获取环境变量---
42
  function getSafeEnvVars() {
43
  const safeVars = {};
44
  const sensitiveKeys = ['PASSWORD', 'SECRET', 'TOKEN', 'KEY'];
 
52
  return safeVars;
53
  }
54
 
55
+ // --- 辅助函数:检查 /data 目录状态(兼容不存在的情况)---
56
+ function checkDataDir() {
57
+ try {
58
+ if (fs.existsSync('/data')) {
59
+ // 目录存在,检查是否可写
60
+ fs.accessSync('/data', fs.constants.W_OK);
61
+ return { exists: true, writable: true };
62
+ } else {
63
+ return { exists: false, writable: false, reason: '目录不存在(免费层未挂载持久存储)' };
64
+ }
65
+ } catch (err) {
66
+ return { exists: true, writable: false, reason: err.message };
67
+ }
68
+ }
69
+
70
  // --- 创建 HTTP 服务器 ---
71
  const server = http.createServer(async (req, res) => {
72
+ // 1. 动态信息
73
  const publicIP = await getPublicIP();
74
  const diskInfo = getDiskUsage();
75
+ const dataDirStatus = checkDataDir();
76
 
77
+ // 2. 系统与硬件信息
78
  const cpuInfo = os.cpus()[0];
79
+ const totalMem = (os.totalmem() / (1024 ** 3)).toFixed(2);
80
+ const freeMem = (os.freemem() / (1024 ** 3)).toFixed(2);
81
+ const usedMem = (totalMem - freeMem).toFixed(2);
82
  const systemUptime = Math.floor(os.uptime() / 60) + ' 分钟';
83
 
84
+ // 3. 用户ID和权限
85
+ let userId = null, groupId = null;
86
+ try {
87
+ userId = process.getuid();
88
+ groupId = process.getgid();
89
+ } catch(e) { /* Windows 可能不支持 */ }
90
 
91
+ // 4. 构建环境报告
92
  const envReport = {
93
+ // 访问信息
94
  access: {
95
+ spaceUrl: `https://${process.env.SPACE_ID?.replace('/', '-') || 'unknown'}.hf.space`,
96
  publicIP: publicIP,
97
  internalIP: (() => {
98
  const interfaces = os.networkInterfaces();
 
104
  return '127.0.0.1';
105
  })(),
106
  hostname: os.hostname(),
107
+ spaceId: process.env.SPACE_ID || '未设置',
108
+ spaceRepoName: process.env.SPACE_REPO_NAME || '未设置',
109
  },
110
+ // 硬件资源
111
  hardware: {
112
  cpuModel: cpuInfo?.model || '未知',
113
  cpuCores: os.cpus().length,
 
118
  uptime: systemUptime,
119
  expectedFreeTier: '2 vCPU / 16GB RAM / 50GB 临时磁盘'
120
  },
121
+ // Node.js 环境
122
  nodeEnv: {
123
  version: process.version,
124
  platform: process.platform,
125
  arch: process.arch,
126
  execPath: process.execPath,
127
  cwd: process.cwd(),
 
128
  },
129
+ // 容器与权限
130
  container: {
131
+ userId: userId,
132
+ groupId: groupId,
133
+ expectedUserId: '通常为 1000 (node 用户)',
134
+ isDataDirPresent: dataDirStatus.exists,
135
+ isDataDirWritable: dataDirStatus.writable,
136
+ dataDirDetail: dataDirStatus.reason || (dataDirStatus.writable ? '可写' : '不可写'),
137
+ hfHome: process.env.HF_HOME || '未设置',
138
+ persistentStorageAvailable: dataDirStatus.exists && dataDirStatus.writable,
139
  },
140
+ // 关键环境变量安全过滤
141
  envVars: getSafeEnvVars(),
142
+ // 部署建议
143
  suggestions: [
144
  '✅ 必须监听 0.0.0.0,并在 README.md 中设置 app_port: 7860',
145
+ '✅ 强烈建议为敏感信息使用 HF Secrets,勿硬编码',
146
+ '✅ 免费层磁盘非持久化,重启会丢失数据',
147
+ '✅ 如需持久化,考虑升级 Persistent Storage 或将数据备份到 HF Dataset',
148
+ '✅ 容器默认用户 UID 可能为 1000,Dockerfile 中建议使用现有 node 用户',
149
  ]
150
  };
151
 
 
152
  res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
153
  res.end(JSON.stringify(envReport, null, 2));
154
  });