diagnostics.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /**
  2. * 系统诊断工具 - 帮助找出可能存在的问题
  3. */
  4. const fs = require('fs').promises;
  5. const path = require('path');
  6. const { execSync } = require('child_process');
  7. const logger = require('../logger');
  8. // 检查所有必要的文件和目录是否存在
  9. async function checkFilesAndDirectories() {
  10. logger.info('开始检查必要的文件和目录...');
  11. // 检查必要的目录
  12. const requiredDirs = [
  13. { path: 'logs', critical: true },
  14. { path: 'documentation', critical: true },
  15. { path: 'web/images', critical: true },
  16. { path: 'routes', critical: true },
  17. { path: 'services', critical: true },
  18. { path: 'middleware', critical: true },
  19. { path: 'scripts', critical: false }
  20. ];
  21. const dirsStatus = {};
  22. for (const dir of requiredDirs) {
  23. const fullPath = path.join(__dirname, '..', dir.path);
  24. try {
  25. await fs.access(fullPath);
  26. dirsStatus[dir.path] = { exists: true, critical: dir.critical };
  27. logger.info(`目录存在: ${dir.path}`);
  28. } catch (error) {
  29. dirsStatus[dir.path] = { exists: false, critical: dir.critical };
  30. logger.error(`目录不存在: ${dir.path} (${dir.critical ? '关键' : '非关键'})`);
  31. }
  32. }
  33. // 检查必要的文件
  34. const requiredFiles = [
  35. { path: 'server.js', critical: true },
  36. { path: 'app.js', critical: false },
  37. { path: 'config.js', critical: true },
  38. { path: 'logger.js', critical: true },
  39. { path: 'init-dirs.js', critical: true },
  40. { path: 'download-images.js', critical: true },
  41. { path: 'cleanup.js', critical: true },
  42. { path: 'package.json', critical: true },
  43. { path: 'web/index.html', critical: true },
  44. { path: 'web/admin.html', critical: true }
  45. ];
  46. const filesStatus = {};
  47. for (const file of requiredFiles) {
  48. const fullPath = path.join(__dirname, '..', file.path);
  49. try {
  50. await fs.access(fullPath);
  51. filesStatus[file.path] = { exists: true, critical: file.critical };
  52. logger.info(`文件存在: ${file.path}`);
  53. } catch (error) {
  54. filesStatus[file.path] = { exists: false, critical: file.critical };
  55. logger.error(`文件不存在: ${file.path} (${file.critical ? '关键' : '非关键'})`);
  56. }
  57. }
  58. return { directories: dirsStatus, files: filesStatus };
  59. }
  60. // 检查Node.js模块依赖
  61. function checkNodeDependencies() {
  62. logger.info('开始检查Node.js依赖...');
  63. try {
  64. // 执行npm list --depth=0来检查已安装的依赖
  65. const npmListOutput = execSync('npm list --depth=0', { encoding: 'utf8' });
  66. logger.info('已安装的依赖:\n' + npmListOutput);
  67. return { success: true, output: npmListOutput };
  68. } catch (error) {
  69. logger.error('检查依赖时出错:', error.message);
  70. return { success: false, error: error.message };
  71. }
  72. }
  73. // 检查系统环境
  74. async function checkSystemEnvironment() {
  75. logger.info('开始检查系统环境...');
  76. const checks = {
  77. node: process.version,
  78. platform: process.platform,
  79. arch: process.arch,
  80. docker: null
  81. };
  82. try {
  83. // 检查Docker是否可用
  84. const dockerVersion = execSync('docker --version', { encoding: 'utf8' });
  85. checks.docker = dockerVersion.trim();
  86. logger.info(`Docker版本: ${dockerVersion.trim()}`);
  87. } catch (error) {
  88. checks.docker = false;
  89. logger.warn('Docker未安装或不可用');
  90. }
  91. return checks;
  92. }
  93. // 运行诊断
  94. async function runDiagnostics() {
  95. logger.info('======= 开始系统诊断 =======');
  96. const results = {
  97. filesAndDirs: await checkFilesAndDirectories(),
  98. dependencies: checkNodeDependencies(),
  99. environment: await checkSystemEnvironment()
  100. };
  101. // 检查关键错误
  102. const criticalErrors = [];
  103. // 检查关键目录
  104. Object.entries(results.filesAndDirs.directories).forEach(([dir, status]) => {
  105. if (status.critical && !status.exists) {
  106. criticalErrors.push(`关键目录丢失: ${dir}`);
  107. }
  108. });
  109. // 检查关键文件
  110. Object.entries(results.filesAndDirs.files).forEach(([file, status]) => {
  111. if (status.critical && !status.exists) {
  112. criticalErrors.push(`关键文件丢失: ${file}`);
  113. }
  114. });
  115. // 检查依赖
  116. if (!results.dependencies.success) {
  117. criticalErrors.push('依赖检查失败');
  118. }
  119. // 总结
  120. logger.info('======= 诊断完成 =======');
  121. if (criticalErrors.length > 0) {
  122. logger.error('发现关键错误:');
  123. criticalErrors.forEach(err => logger.error(`- ${err}`));
  124. logger.error('请解决以上问题后重试');
  125. } else {
  126. logger.success('未发现关键错误,系统应该可以正常运行');
  127. }
  128. return { results, criticalErrors };
  129. }
  130. // 直接运行脚本时启动诊断
  131. if (require.main === module) {
  132. runDiagnostics()
  133. .then(() => {
  134. logger.info('诊断完成');
  135. })
  136. .catch(error => {
  137. logger.fatal('诊断过程中发生错误:', error);
  138. });
  139. }
  140. module.exports = { runDiagnostics };