- 提取 Nginx 检测为独立函数 isNginxInstalled - 为 select 函数添加 defaultIndex 参数支持默认选项 - 数据库配置保留用户上次输入值作为默认值 - 运行环境和部署方式选择支持记忆上次配置
264 lines
9.7 KiB
JavaScript
264 lines
9.7 KiB
JavaScript
const fs = require('fs');
|
||
const { execSync } = require('child_process');
|
||
const { colors, log } = require('./logger');
|
||
const { ask, askPassword, select } = require('./ui');
|
||
const { config } = require('./config');
|
||
const { detectLinuxDistro } = require('./env-check');
|
||
|
||
async function configureDatabase(cmdArgs) {
|
||
log.step('数据库配置');
|
||
|
||
if (cmdArgs?.nonInteractive && cmdArgs?.dbType) {
|
||
config.dbType = cmdArgs.dbType;
|
||
log.info(`使用命令行参数: 数据库类型 = ${config.dbType}`);
|
||
} else if (cmdArgs?.nonInteractive) {
|
||
config.dbType = 'sqlite';
|
||
log.info('使用默认配置: 数据库类型 = sqlite');
|
||
} else {
|
||
const defaultDbType = config.dbType || 'sqlite';
|
||
const defaultIndex = defaultDbType === 'mysql' ? 2 : 1;
|
||
config.dbType = await select('选择数据库类型:', [
|
||
{ label: 'SQLite(零配置,适合开发/小规模)', value: 'sqlite' },
|
||
{ label: 'MySQL(生产环境推荐)', value: 'mysql' }
|
||
], defaultIndex);
|
||
}
|
||
|
||
if (config.dbType === 'mysql') {
|
||
if (cmdArgs?.nonInteractive) {
|
||
config.dbConfig.host = process.env.MYSQL_HOST || 'localhost';
|
||
config.dbConfig.port = process.env.MYSQL_PORT || '3306';
|
||
config.dbConfig.username = process.env.MYSQL_USER || 'root';
|
||
config.dbConfig.password = process.env.MYSQL_PASSWORD || '';
|
||
config.dbConfig.database = process.env.MYSQL_DATABASE || 'idc_management';
|
||
log.info(`MySQL 配置: ${config.dbConfig.host}:${config.dbConfig.port}/${config.dbConfig.database}`);
|
||
} else {
|
||
const mysqlOption = await select('MySQL 配置方式:', [
|
||
{ label: '已有数据库(填写现有 MySQL 连接信息)', value: 'existing' },
|
||
{ label: '自动安装 MySQL(Linux 系统支持自动安装配置)', value: 'install' }
|
||
]);
|
||
|
||
if (mysqlOption === 'install') {
|
||
const installResult = await installMySQL();
|
||
if (installResult.success) {
|
||
config.dbConfig = { ...installResult.config };
|
||
} else {
|
||
log.error('MySQL 自动安装失败');
|
||
const fallback = await ask('是否改为手动配置现有 MySQL? (Y/n)', 'Y');
|
||
if (fallback.toLowerCase() === 'y') {
|
||
await configureExistingMySQL();
|
||
} else {
|
||
log.info('已取消 MySQL 配置,将使用 SQLite');
|
||
config.dbType = 'sqlite';
|
||
}
|
||
}
|
||
} else {
|
||
await configureExistingMySQL();
|
||
}
|
||
}
|
||
|
||
if (config.dbType === 'mysql') {
|
||
const testResult = await testMySQLConnection();
|
||
if (!testResult.success) {
|
||
log.error(`MySQL 连接测试失败: ${testResult.error}`);
|
||
const retry = cmdArgs?.nonInteractive ? false : await ask('是否重新配置? (Y/n)', 'Y');
|
||
if (retry.toLowerCase() === 'y') {
|
||
return await configureDatabase(cmdArgs);
|
||
}
|
||
log.warning('将继续部署,但数据库可能无法正常工作');
|
||
}
|
||
}
|
||
}
|
||
|
||
log.divider();
|
||
}
|
||
|
||
async function configureExistingMySQL() {
|
||
console.log('\n' + colors.yellow + '请确保 MySQL 服务已启动并创建了数据库' + colors.reset);
|
||
console.log(colors.gray + '创建数据库命令: CREATE DATABASE idc_management CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;' + colors.reset + '\n');
|
||
|
||
config.dbConfig.host = await ask('MySQL 主机地址', config.dbConfig.host || 'localhost');
|
||
config.dbConfig.port = await ask('MySQL 端口', config.dbConfig.port || '3306');
|
||
config.dbConfig.username = await ask('MySQL 用户名', config.dbConfig.username || 'root');
|
||
config.dbConfig.password = await askPassword('MySQL 密码');
|
||
config.dbConfig.database = await ask('数据库名称', config.dbConfig.database || 'idc_management');
|
||
}
|
||
|
||
async function installMySQL() {
|
||
log.subStep('检测系统环境...');
|
||
|
||
const platform = process.platform;
|
||
|
||
if (platform === 'win32') {
|
||
log.warning('Windows 系统暂不支持自动安装 MySQL');
|
||
console.log('\n' + colors.cyan + '请手动安装 MySQL:' + colors.reset);
|
||
console.log(' 1. 下载 MySQL: https://dev.mysql.com/downloads/mysql/');
|
||
console.log(' 2. 或使用 XAMPP/WAMP 等集成环境');
|
||
console.log(' 3. 安装后创建数据库:');
|
||
console.log(colors.gray + ' CREATE DATABASE idc_management CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;' + colors.reset);
|
||
return { success: false };
|
||
}
|
||
|
||
if (platform !== 'linux') {
|
||
log.warning('当前系统暂不支持自动安装 MySQL');
|
||
return { success: false };
|
||
}
|
||
|
||
const distro = detectLinuxDistro();
|
||
log.info(`检测到 Linux 发行版: ${distro}`);
|
||
|
||
const mysqlRootPassword = await askPassword('设置 MySQL root 密码(用于新安装的 MySQL)');
|
||
if (!mysqlRootPassword) {
|
||
log.error('密码不能为空');
|
||
return { success: false };
|
||
}
|
||
|
||
log.subStep('开始安装 MySQL...');
|
||
|
||
try {
|
||
switch (distro) {
|
||
case 'ubuntu':
|
||
case 'debian':
|
||
await installMySQLDebian(mysqlRootPassword);
|
||
break;
|
||
case 'centos':
|
||
case 'rhel':
|
||
case 'rocky':
|
||
case 'almalinux':
|
||
await installMySQLRHEL(mysqlRootPassword);
|
||
break;
|
||
default:
|
||
log.warning(`暂不支持 ${distro} 自动安装 MySQL`);
|
||
return { success: false };
|
||
}
|
||
|
||
config.dbConfig.host = 'localhost';
|
||
config.dbConfig.port = '3306';
|
||
config.dbConfig.username = 'root';
|
||
config.dbConfig.password = mysqlRootPassword;
|
||
config.dbConfig.database = 'idc_management';
|
||
|
||
log.subStep('创建数据库...');
|
||
await createMySQLDatabase(mysqlRootPassword);
|
||
|
||
log.success('MySQL 安装配置完成');
|
||
return {
|
||
success: true,
|
||
config: {
|
||
host: 'localhost',
|
||
port: '3306',
|
||
username: 'root',
|
||
password: mysqlRootPassword,
|
||
database: 'idc_management'
|
||
}
|
||
};
|
||
} catch (error) {
|
||
log.error(`MySQL 安装失败: ${error.message}`);
|
||
return { success: false, error: error.message };
|
||
}
|
||
}
|
||
|
||
async function installMySQLDebian(rootPassword) {
|
||
log.info('安装 MySQL (Ubuntu/Debian)...');
|
||
|
||
execSync('export DEBIAN_FRONTEND=noninteractive', { shell: '/bin/bash' });
|
||
execSync('apt-get update -qq', { shell: '/bin/bash', stdio: 'inherit' });
|
||
execSync(`debconf-set-selections <<< "mysql-server mysql-server/root_password password ${rootPassword}"`, { shell: '/bin/bash' });
|
||
execSync(`debconf-set-selections <<< "mysql-server mysql-server/root_password_again password ${rootPassword}"`, { shell: '/bin/bash' });
|
||
execSync('apt-get install -y -qq mysql-server', { shell: '/bin/bash', stdio: 'inherit' });
|
||
execSync('systemctl start mysql', { shell: '/bin/bash' });
|
||
execSync('systemctl enable mysql', { shell: '/bin/bash' });
|
||
|
||
log.success('MySQL 安装完成');
|
||
}
|
||
|
||
async function installMySQLRHEL(rootPassword) {
|
||
log.info('安装 MySQL (CentOS/RHEL)...');
|
||
|
||
execSync('yum install -y -q epel-release', { shell: '/bin/bash', stdio: 'inherit' });
|
||
execSync('yum install -y -q mysql-server', { shell: '/bin/bash', stdio: 'inherit' });
|
||
execSync('systemctl start mysqld', { shell: '/bin/bash' });
|
||
execSync('systemctl enable mysqld', { shell: '/bin/bash' });
|
||
|
||
try {
|
||
execSync(`mysqladmin -u root password "${rootPassword}"`, { shell: '/bin/bash' });
|
||
} catch {
|
||
log.info('root 密码可能已设置,跳过');
|
||
}
|
||
|
||
log.success('MySQL 安装完成');
|
||
}
|
||
|
||
async function createMySQLDatabase(rootPassword) {
|
||
log.subStep('创建数据库...');
|
||
|
||
const createDbSql = 'CREATE DATABASE IF NOT EXISTS idc_management CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;';
|
||
|
||
try {
|
||
execSync(`mysql -u root -p'${rootPassword}' -e "${createDbSql}"`, {
|
||
shell: '/bin/bash',
|
||
stdio: ['pipe', 'pipe', 'pipe']
|
||
});
|
||
log.success('数据库 idc_management 创建成功');
|
||
return;
|
||
} catch (error) {
|
||
const errorMsg = error.stderr ? error.stderr.toString() : error.message;
|
||
|
||
if (errorMsg.includes('Access denied') || errorMsg.includes('ERROR 1045')) {
|
||
log.warning('MySQL root 密码验证失败,尝试无密码连接...');
|
||
try {
|
||
execSync(`mysql -u root -e "${createDbSql}"`, {
|
||
shell: '/bin/bash',
|
||
stdio: ['pipe', 'pipe', 'pipe']
|
||
});
|
||
log.success('数据库 idc_management 创建成功');
|
||
return;
|
||
} catch (e2) {
|
||
log.warning(`无密码连接也失败: ${e2.message}`);
|
||
}
|
||
}
|
||
|
||
log.warning(`数据库自动创建失败: ${errorMsg.trim()}`);
|
||
log.info('请手动创建数据库:');
|
||
console.log(colors.cyan + ' mysql -u root -p' + colors.reset);
|
||
console.log(colors.cyan + ' CREATE DATABASE idc_management CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;' + colors.reset);
|
||
}
|
||
}
|
||
|
||
async function testMySQLConnection() {
|
||
log.subStep('测试 MySQL 连接...');
|
||
|
||
try {
|
||
execSync(`mysql -h ${config.dbConfig.host} -P ${config.dbConfig.port} -u ${config.dbConfig.username} -p'${config.dbConfig.password}' -e "SELECT 1" ${config.dbConfig.database}`, {
|
||
shell: '/bin/bash',
|
||
stdio: ['pipe', 'pipe', 'pipe'],
|
||
timeout: 5000
|
||
});
|
||
log.success('MySQL 连接测试成功');
|
||
return { success: true };
|
||
} catch (error) {
|
||
const errorMsg = error.stderr ? error.stderr.toString() : error.message;
|
||
|
||
if (errorMsg.includes('Access denied') || errorMsg.includes('ERROR 1045')) {
|
||
return { success: false, error: '用户名或密码错误' };
|
||
}
|
||
if (errorMsg.includes('Unknown database')) {
|
||
return { success: false, error: `数据库 ${config.dbConfig.database} 不存在` };
|
||
}
|
||
if (errorMsg.includes('Connection refused') || errorMsg.includes("Can't connect")) {
|
||
return { success: false, error: `无法连接到 ${config.dbConfig.host}:${config.dbConfig.port}` };
|
||
}
|
||
|
||
return { success: false, error: errorMsg.trim() || '连接失败' };
|
||
}
|
||
}
|
||
|
||
module.exports = {
|
||
configureDatabase,
|
||
configureExistingMySQL,
|
||
installMySQL,
|
||
installMySQLDebian,
|
||
installMySQLRHEL,
|
||
createMySQLDatabase,
|
||
testMySQLConnection,
|
||
};
|