
核心代码如下:
bash
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多数据库备份脚本生成工具</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #2c3e50;
--secondary: #4a6491;
--accent: #4fc3f7;
--success: #38a169;
--warning: #dd6b20;
--danger: #e53e3e;
--light: #f8f9fa;
--dark: #1a2a6c;
--postgres: #336791;
--sqlserver: #0078d7;
--converter: #9c27b0;
--modifier: #ff9800;
--scheduler: #2196f3;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #1a2a6c, #2c3e50);
color: #333;
min-height: 100vh;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
}
.container {
max-width: 1400px;
width: 100%;
background: rgba(255, 255, 255, 0.97);
border-radius: 15px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4);
overflow: hidden;
}
header {
background: linear-gradient(90deg, var(--primary), var(--secondary));
color: white;
padding: 25px 40px;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
overflow: hidden;
}
.logo {
display: flex;
align-items: center;
gap: 15px;
z-index: 2;
}
.logo i {
font-size: 2.8rem;
color: var(--accent);
text-shadow: 0 0 10px rgba(79, 195, 247, 0.5);
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.logo h1 {
font-size: 2.4rem;
font-weight: 800;
letter-spacing: 0.5px;
}
.subtitle {
font-size: 1.1rem;
opacity: 0.9;
margin-top: 5px;
}
.header-pattern {
position: absolute;
top: -50px;
right: -50px;
opacity: 0.1;
font-size: 10rem;
transform: rotate(15deg);
z-index: 1;
}
.main-content {
display: flex;
min-height: 700px;
}
.sidebar {
width: 300px;
background: var(--primary);
color: white;
padding: 25px 0;
position: relative;
z-index: 2;
}
.sidebar::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 5px;
background: linear-gradient(90deg, var(--accent), #1a9fff);
}
.sidebar-section {
margin-bottom: 25px;
}
.sidebar-title {
padding: 12px 25px;
font-size: 1.1rem;
font-weight: 600;
color: var(--accent);
border-bottom: 1px solid #3a506b;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.sidebar-option {
padding: 14px 35px;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 12px;
position: relative;
}
.sidebar-option:hover {
background: rgba(58, 80, 107, 0.7);
}
.sidebar-option.active {
background: rgba(74, 100, 145, 0.9);
border-left: 4px solid var(--accent);
}
.sidebar-option i {
width: 25px;
text-align: center;
font-size: 1.1rem;
}
.sidebar-option::after {
content: "";
position: absolute;
left: 25px;
right: 25px;
bottom: 0;
height: 1px;
background: rgba(255, 255, 255, 0.05);
}
.content-area {
flex: 1;
padding: 30px;
display: flex;
flex-direction: column;
background: #fafcff;
}
.tab-content {
display: none;
flex: 1;
}
.tab-content.active {
display: flex;
flex-direction: column;
animation: fadeIn 0.5s;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.section-title {
font-size: 1.8rem;
margin-bottom: 25px;
color: var(--primary);
padding-bottom: 15px;
border-bottom: 2px solid var(--secondary);
display: flex;
align-items: center;
gap: 15px;
}
.config-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 30px;
margin-bottom: 30px;
}
.config-card {
background: white;
border-radius: 12px;
box-shadow: 0 7px 20px rgba(0, 0, 0, 0.08);
padding: 28px;
border: 1px solid #e0e6ed;
transition: transform 0.3s, box-shadow 0.3s;
position: relative;
overflow: hidden;
}
.config-card:hover {
transform: translateY(-5px);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.12);
}
.card-title {
display: flex;
align-items: center;
gap: 12px;
font-size: 1.35rem;
margin-bottom: 22px;
color: var(--primary);
padding-bottom: 12px;
border-bottom: 1px solid #e2e8f0;
}
.card-title i {
color: var(--secondary);
font-size: 1.4rem;
}
.form-group {
margin-bottom: 22px;
}
.form-group label {
display: block;
margin-bottom: 10px;
font-weight: 600;
color: #4a5568;
display: flex;
align-items: center;
gap: 8px;
}
.form-group label i {
color: var(--secondary);
font-size: 0.9rem;
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 14px 16px;
border: 1px solid #cbd5e0;
border-radius: 10px;
font-size: 1.05rem;
transition: all 0.3s;
background: #f8fafc;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
border-color: var(--secondary);
outline: none;
box-shadow: 0 0 0 3px rgba(74, 100, 145, 0.2);
background: white;
}
.checkbox-group {
display: flex;
align-items: center;
gap: 12px;
margin: 18px 0;
}
.checkbox-group input {
width: auto;
transform: scale(1.2);
}
.btn {
padding: 14px 28px;
border: none;
border-radius: 10px;
font-size: 1.05rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
display: inline-flex;
align-items: center;
gap: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.btn-primary {
background: linear-gradient(90deg, var(--secondary), var(--primary));
color: white;
}
.btn-primary:hover {
background: linear-gradient(90deg, var(--primary), var(--secondary));
box-shadow: 0 7px 14px rgba(44, 62, 80, 0.4);
transform: translateY(-2px);
}
.btn-secondary {
background: #e0e6ed;
color: #4a5568;
}
.btn-secondary:hover {
background: #cbd5e0;
transform: translateY(-2px);
}
.btn-success {
background: linear-gradient(90deg, var(--success), #2f9e58);
color: white;
}
.btn-success:hover {
background: linear-gradient(90deg, #2f9e58, var(--success));
transform: translateY(-2px);
}
.btn-postgres {
background: linear-gradient(90deg, var(--postgres), #2a5b80);
color: white;
}
.btn-sqlserver {
background: linear-gradient(90deg, var(--sqlserver), #0066b4);
color: white;
}
.btn-converter {
background: linear-gradient(90deg, var(--converter), #7b1fa2);
color: white;
}
.btn-modifier {
background: linear-gradient(90deg, var(--modifier), #ef6c00);
color: white;
}
.btn-scheduler {
background: linear-gradient(90deg, var(--scheduler), #0d47a1);
color: white;
}
.action-buttons {
display: flex;
gap: 18px;
margin-top: 30px;
flex-wrap: wrap;
}
.report-section {
margin-top: 40px;
background: white;
border-radius: 12px;
box-shadow: 0 7px 20px rgba(0, 0, 0, 0.08);
padding: 30px;
border: 1px solid #e0e6ed;
flex: 1;
display: flex;
flex-direction: column;
}
.report-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 25px;
}
.report-content {
background: #f8f9fa;
border: 1px solid #e2e8f0;
border-radius: 10px;
padding: 25px;
font-family: 'Consolas', 'Courier New', monospace;
white-space: pre-wrap;
flex: 1;
overflow-y: auto;
line-height: 1.5;
font-size: 0.95rem;
color: #2d3748;
position: relative;
min-height: 250px;
}
.report-content::before {
content: "> 生成的备份脚本";
position: absolute;
top: -12px;
left: 15px;
background: #f8f9fa;
padding: 0 10px;
color: var(--secondary);
font-size: 0.85rem;
font-weight: 600;
}
.copy-btn {
position: absolute;
top: 15px;
right: 15px;
padding: 8px 16px;
background: rgba(255, 255, 255, 0.9);
border: 1px solid #cbd5e0;
border-radius: 6px;
font-size: 0.85rem;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 6px;
}
.copy-btn:hover {
background: var(--secondary);
color: white;
border-color: var(--secondary);
}
.tables-list {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.table-tag {
background: #e2e8f0;
padding: 5px 12px;
border-radius: 20px;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 5px;
}
.table-tag i {
cursor: pointer;
color: var(--danger);
font-size: 0.8rem;
}
footer {
text-align: center;
padding: 20px;
background: var(--primary);
color: #a0aec0;
font-size: 0.95rem;
}
.database-icon {
width: 45px;
height: 45px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
color: white;
font-size: 1.3rem;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.oracle-icon {
background: #c74634;
}
.mysql-icon {
background: #f29111;
}
.postgres-icon {
background: var(--postgres);
}
.sqlserver-icon {
background: var(--sqlserver);
}
.status-indicator {
display: flex;
align-items: center;
gap: 12px;
margin-top: 15px;
font-weight: 600;
padding: 12px;
border-radius: 8px;
background: #f0f7ff;
}
.success {
color: var(--success);
}
.warning {
color: var(--warning);
}
.error {
color: var(--danger);
}
.backup-type {
display: flex;
gap: 15px;
margin-bottom: 20px;
background: #f0f7ff;
padding: 15px;
border-radius: 10px;
}
.backup-type-btn {
flex: 1;
padding: 15px;
text-align: center;
border-radius: 8px;
background: #e2e8f0;
cursor: pointer;
transition: all 0.3s;
font-weight: 600;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.backup-type-btn.active {
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
}
.backup-type-btn i {
font-size: 1.8rem;
}
.backup-type-btn.physical.active {
background: var(--secondary);
color: white;
}
.backup-type-btn.logical.active {
background: var(--success);
color: white;
}
.tool-content {
padding: 20px;
background: white;
border-radius: 12px;
box-shadow: 0 7px 20px rgba(0, 0, 0, 0.08);
flex: 1;
display: flex;
flex-direction: column;
}
.tool-title {
font-size: 1.8rem;
margin-bottom: 20px;
color: var(--primary);
display: flex;
align-items: center;
gap: 15px;
}
.tool-description {
margin-bottom: 30px;
line-height: 1.6;
color: #4a5568;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
border-left: 4px solid var(--accent);
}
.tool-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 25px;
margin-bottom: 30px;
}
.tool-card {
background: white;
border-radius: 12px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
padding: 25px;
border: 1px solid #e2e8f0;
transition: all 0.3s;
}
.tool-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
}
.tool-card h3 {
display: flex;
align-items: center;
gap: 12px;
font-size: 1.4rem;
margin-bottom: 20px;
color: var(--primary);
padding-bottom: 12px;
border-bottom: 1px solid #e2e8f0;
}
.tool-card p {
color: #4a5568;
line-height: 1.6;
margin-bottom: 20px;
}
.tool-feature {
background: white;
border-radius: 12px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
padding: 25px;
margin-bottom: 25px;
border: 1px solid #e2e8f0;
transition: all 0.3s;
}
.tool-feature:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
}
.tool-feature h3 {
display: flex;
align-items: center;
gap: 12px;
font-size: 1.4rem;
margin-bottom: 20px;
color: var(--primary);
padding-bottom: 12px;
border-bottom: 1px solid #e2e8f0;
}
.converter-feature h3 {
color: var(--converter);
}
.modifier-feature h3 {
color: var(--modifier);
}
.scheduler-feature h3 {
color: var(--scheduler);
}
.notification {
position: fixed;
top: 20px;
right: 20px;
padding: 15px 25px;
border-radius: 8px;
background: var(--success);
color: white;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
z-index: 1000;
display: flex;
align-items: center;
gap: 10px;
transform: translateX(150%);
transition: transform 0.3s ease-out;
}
.notification.show {
transform: translateX(0);
}
.notification i {
font-size: 1.2rem;
}
.database-selector {
display: flex;
flex-direction: column;
gap: 15px;
margin-bottom: 20px;
}
.database-item {
display: flex;
align-items: center;
padding: 12px;
border: 1px solid #e2e8f0;
border-radius: 8px;
background: #f8f9fa;
cursor: pointer;
transition: all 0.3s;
}
.database-item:hover {
background: #edf2f7;
}
.database-item.selected {
background: #ebf8ff;
border-color: var(--accent);
}
.database-item input {
margin-right: 12px;
}
.database-item label {
flex: 1;
cursor: pointer;
}
.database-item .tables-list {
flex: 1;
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.table-item {
background: #e2e8f0;
padding: 5px 12px;
border-radius: 20px;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 5px;
}
.table-item.selected {
background: var(--accent);
color: white;
}
.custom-db-input {
margin-top: 15px;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
border: 1px solid #e2e8f0;
}
.input-hint {
font-size: 0.9rem;
color: #718096;
margin-top: 8px;
margin-bottom: 15px;
}
.input-example {
background: #edf2f7;
padding: 8px 12px;
border-radius: 6px;
font-size: 0.85rem;
margin-top: 8px;
}
@media (max-width: 900px) {
.main-content {
flex-direction: column;
}
.sidebar {
width: 100%;
}
.config-grid {
grid-template-columns: 1fr;
}
.backup-type {
flex-direction: column;
}
.action-buttons {
flex-direction: column;
}
.database-icons {
display: none;
}
header {
flex-direction: column;
gap: 20px;
text-align: center;
}
.notification {
top: 10px;
right: 10px;
left: 10px;
text-align: center;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<div class="logo">
<i class="fas fa-database"></i>
<div>
<h1>多数据库备份脚本生成工具</h1>
<div class="subtitle">支持Oracle, MySQL, PostgreSQL, SQL Server | 物理与逻辑备份 | 按库/表备份</div>
</div>
</div>
<div class="database-icons">
<div style="display: flex; gap: 15px;">
<div class="database-icon oracle-icon"><i class="fab fa-oracle"></i></div>
<div class="database-icon mysql-icon"><i class="fas fa-database"></i></div>
<div class="database-icon postgres-icon"><i class="fas fa-server"></i></div>
<div class="database-icon sqlserver-icon"><i class="fab fa-microsoft"></i></div>
</div>
</div>
<div class="header-pattern">
<i class="fas fa-code"></i>
</div>
</header>
<div class="main-content">
<div class="sidebar">
<div class="sidebar-section">
<div class="sidebar-title">
<i class="fas fa-database"></i>
数据库类型
</div>
<div class="sidebar-option active" data-tab="oracle">
<i class="fab fa-oracle"></i>
Oracle
</div>
<div class="sidebar-option" data-tab="mysql">
<i class="fas fa-database"></i>
MySQL
</div>
<div class="sidebar-option" data-tab="postgres">
<i class="fas fa-server"></i>
PostgreSQL
</div>
<div class="sidebar-option" data-tab="sqlserver">
<i class="fab fa-microsoft"></i>
SQL Server
</div>
</div>
<div class="sidebar-section">
<div class="sidebar-title">
<i class="fas fa-tools"></i>
工具功能
</div>
<!-- 已移除脚本转换器 -->
<div class="sidebar-option" data-tab="modifier">
<i class="fas fa-edit"></i>
脚本修改器
</div>
<div class="sidebar-option" data-tab="scheduler">
<i class="fas fa-calendar-alt"></i>
计划任务生成
</div>
</div>
<div class="sidebar-section">
<div class="sidebar-title">
<i class="fas fa-history"></i>
最近脚本
</div>
<div class="sidebar-option">
<i class="fas fa-file-code"></i>
oracle_full_backup.sh
</div>
<div class="sidebar-option">
<i class="fas fa-file-code"></i>
mysql_tables_backup.sql
</div>
<div class="sidebar-option">
<i class="fas fa-file-code"></i>
pg_daily_backup.sh
</div>
</div>
</div>
<div class="content-area">
<!-- Oracle 配置 -->
<div class="tab-content active" id="oracle">
<h2 class="section-title"><i class="fab fa-oracle"></i> Oracle 备份配置</h2>
<div class="backup-type">
<div class="backup-type-btn physical active" data-type="physical">
<i class="fas fa-hard-drive"></i>
物理备份
</div>
<div class="backup-type-btn logical" data-type="logical">
<i class="fas fa-file-code"></i>
逻辑备份
</div>
</div>
<div class="config-grid">
<div class="config-card">
<h3 class="card-title"><i class="fas fa-plug"></i> 连接设置</h3>
<div class="form-group">
<label for="oracle-host"><i class="fas fa-server"></i> 主机地址</label>
<input type="text" id="oracle-host" placeholder="例如: 192.168.1.100" value="dbserver01">
</div>
<div class="form-group">
<label for="oracle-port"><i class="fas fa-network-wired"></i> 端口</label>
<input type="text" id="oracle-port" value="1521">
</div>
<div class="form-group">
<label for="oracle-service"><i class="fas fa-cog"></i> 服务名/SID</label>
<input type="text" id="oracle-service" placeholder="例如: ORCL" value="ORCL">
</div>
<div class="form-group">
<label for="oracle-user"><i class="fas fa-user"></i> 用户名</label>
<input type="text" id="oracle-user" placeholder="例如: sys" value="sys as sysdba">
</div>
<div class="form-group">
<label for="oracle-password"><i class="fas fa-key"></i> 密码</label>
<input type="password" id="oracle-password" placeholder="输入密码" value="********">
</div>
</div>
<div class="config-card">
<h3 class="card-title"><i class="fas fa-cog"></i> 备份设置</h3>
<div class="form-group">
<label for="oracle-backup-path"><i class="fas fa-folder-open"></i> 备份路径</label>
<input type="text" id="oracle-backup-path" value="/backup/oracle/">
</div>
<!-- 物理备份特定设置 -->
<div class="backup-options physical active">
<div class="form-group">
<label for="oracle-parallel"><i class="fas fa-microchip"></i> 并行度</label>
<input type="number" id="oracle-parallel" min="1" max="16" value="4">
</div>
<div class="form-group">
<label for="oracle-compression"><i class="fas fa-compress"></i> 压缩级别</label>
<select id="oracle-compression">
<option value="low">低</option>
<option value="medium" selected>中</option>
<option value="high">高</option>
</select>
</div>
</div>
<!-- 逻辑备份特定设置 - 自定义输入 -->
<div class="backup-options logical">
<div class="form-group">
<label><i class="fas fa-database"></i> 数据库和表配置</label>
<div class="custom-db-input">
<div class="input-hint">
输入格式:数据库名:表1,表2,表3(每行一个数据库)
</div>
<textarea id="oracle-db-config" rows="4" placeholder="例如:
APP_DB:USERS,ORDERS,PRODUCTS
REPORT_DB:SALES,INVENTORY">APP_DB:USERS,ORDERS</textarea>
<div class="input-example">
示例:<br>
HR_DB:EMPLOYEES,DEPARTMENTS<br>
FINANCE_DB:ACCOUNTS,TRANSACTIONS
</div>
</div>
</div>
</div>
<div class="form-group">
<label>高级选项</label>
<div class="checkbox-group">
<input type="checkbox" id="oracle-encryption">
<label for="oracle-encryption">启用加密</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="oracle-validate" checked>
<label for="oracle-validate">备份后验证</label>
</div>
</div>
</div>
</div>
<div class="action-buttons">
<button class="btn btn-primary" id="generate-oracle">
<i class="fas fa-code"></i> 生成备份脚本
</button>
<button class="btn btn-secondary">
<i class="fas fa-save"></i> 保存配置
</button>
</div>
<div class="report-section">
<div class="report-header">
<h3 class="section-title"><i class="fas fa-file-code"></i> 生成的备份脚本</h3>
</div>
<div class="report-content" id="oracle-script">
<!-- 生成的脚本将显示在这里 -->
</div>
</div>
</div>
<!-- MySQL 配置 -->
<div class="tab-content" id="mysql">
<h2 class="section-title"><i class="fas fa-database"></i> MySQL 备份配置</h2>
<div class="backup-type">
<div class="backup-type-btn physical active" data-type="physical">
<i class="fas fa-hard-drive"></i>
物理备份
</div>
<div class="backup-type-btn logical" data-type="logical">
<i class="fas fa-file-code"></i>
逻辑备份
</div>
</div>
<div class="config-grid">
<div class="config-card">
<h3 class="card-title"><i class="fas fa-plug"></i> 连接设置</h3>
<div class="form-group">
<label for="mysql-host"><i class="fas fa-server"></i> 主机地址</label>
<input type="text" id="mysql-host" placeholder="例如: 192.168.1.100" value="db-mysql-01">
</div>
<div class="form-group">
<label for="mysql-port"><i class="fas fa-network-wired"></i> 端口</label>
<input type="text" id="mysql-port" value="3306">
</div>
<div class="form-group">
<label for="mysql-db"><i class="fas fa-database"></i> 数据库名</label>
<input type="text" id="mysql-db" placeholder="例如: app_db" value="app_db">
</div>
<div class="form-group">
<label for="mysql-user"><i class="fas fa-user"></i> 用户名</label>
<input type="text" id="mysql-user" placeholder="例如: root" value="admin">
</div>
<div class="form-group">
<label for="mysql-password"><i class="fas fa-key"></i> 密码</label>
<input type="password" id="mysql-password" placeholder="输入密码" value="********">
</div>
</div>
<div class="config-card">
<h3 class="card-title"><i class="fas fa-cog"></i> 备份设置</h3>
<div class="form-group">
<label for="mysql-backup-path"><i class="fas fa-folder-open"></i> 备份路径</label>
<input type="text" id="mysql-backup-path" value="/backup/mysql/">
</div>
<!-- 物理备份特定设置 -->
<div class="backup-options physical active">
<div class="form-group">
<label for="mysql-threads"><i class="fas fa-microchip"></i> 线程数</label>
<input type="number" id="mysql-threads" min="1" max="16" value="4">
</div>
<div class="form-group">
<label for="mysql-compression"><i class="fas fa-compress"></i> 压缩级别</label>
<select id="mysql-compression">
<option value="1">快速</option>
<option value="2" selected>平衡</option>
<option value="9">最佳</option>
</select>
</div>
</div>
<!-- 逻辑备份特定设置 - 自定义输入 -->
<div class="backup-options logical">
<div class="form-group">
<label><i class="fas fa-database"></i> 数据库和表配置</label>
<div class="custom-db-input">
<div class="input-hint">
输入格式:数据库名:表1,表2,表3(每行一个数据库)
</div>
<textarea id="mysql-db-config" rows="4" placeholder="例如:
app_db:users,orders,products
report_db:sales,inventory">app_db:users,orders</textarea>
<div class="input-example">
示例:<br>
wordpress:wp_posts,wp_users<br>
inventory:products,categories
</div>
</div>
</div>
</div>
<div class="form-group">
<label>高级选项</label>
<div class="checkbox-group">
<input type="checkbox" id="mysql-encryption">
<label for="mysql-encryption">启用加密</label>
</div>
</div>
</div>
</div>
<div class="action-buttons">
<button class="btn btn-primary" id="generate-mysql">
<i class="fas fa-code"></i> 生成备份脚本
</button>
<button class="btn btn-secondary">
<i class="fas fa-save"></i> 保存配置
</button>
</div>
<div class="report-section">
<div class="report-header">
<h3 class="section-title"><i class="fas fa-file-code"></i> 生成的备份脚本</h3>
</div>
<div class="report-content" id="mysql-script">
<!-- 生成的脚本将显示在这里 -->
</div>
</div>
</div>
<!-- PostgreSQL 配置 -->
<div class="tab-content" id="postgres">
<h2 class="section-title"><i class="fas fa-server"></i> PostgreSQL 备份配置</h2>
<div class="backup-type">
<div class="backup-type-btn physical active" data-type="physical">
<i class="fas fa-hard-drive"></i>
物理备份
</div>
<div class="backup-type-btn logical" data-type="logical">
<i class="fas fa-file-code"></i>
逻辑备份
</div>
</div>
<div class="config-grid">
<div class="config-card">
<h3 class="card-title"><i class="fas fa-plug"></i> 连接设置</h3>
<div class="form-group">
<label for="postgres-host"><i class="fas fa-server"></i> 主机地址</label>
<input type="text" id="postgres-host" placeholder="例如: 192.168.1.100" value="pg-server">
</div>
<div class="form-group">
<label for="postgres-port"><i class="fas fa-network-wired"></i> 端口</label>
<input type="text" id="postgres-port" value="5432">
</div>
<div class="form-group">
<label for="postgres-db"><i class="fas fa-database"></i> 数据库名</label>
<input type="text" id="postgres-db" placeholder="例如: app_db" value="app_db">
</div>
<div class="form-group">
<label for="postgres-user"><i class="fas fa-user"></i> 用户名</label>
<input type="text" id="postgres-user" placeholder="例如: postgres" value="admin">
</div>
<div class="form-group">
<label for="postgres-password"><i class="fas fa-key"></i> 密码</label>
<input type="password" id="postgres-password" placeholder="输入密码" value="********">
</div>
</div>
<div class="config-card">
<h3 class="card-title"><i class="fas fa-cog"></i> 备份设置</h3>
<div class="form-group">
<label for="postgres-backup-path"><i class="fas fa-folder-open"></i> 备份路径</label>
<input type="text" id="postgres-backup-path" value="/backup/postgres/">
</div>
<!-- 物理备份特定设置 -->
<div class="backup-options physical active">
<div class="form-group">
<label for="postgres-compress"><i class="fas fa-compress"></i> 压缩级别</label>
<select id="postgres-compress">
<option value="0">无压缩</option>
<option value="1">快速</option>
<option value="6" selected>平衡</option>
<option value="9">最佳</option>
</select>
</div>
<div class="form-group">
<label for="postgres-checkpoint"><i class="fas fa-check-circle"></i> 检查点模式</label>
<select id="postgres-checkpoint">
<option value="fast">快速</option>
<option value="spread" selected>分散</option>
<option value="full">完整</option>
</select>
</div>
</div>
<!-- 逻辑备份特定设置 - 自定义输入 -->
<div class="backup-options logical">
<div class="form-group">
<label><i class="fas fa-database"></i> 数据库和表配置</label>
<div class="custom-db-input">
<div class="input-hint">
输入格式:数据库名:表1,表2,表3(每行一个数据库)
</div>
<textarea id="postgres-db-config" rows="4" placeholder="例如:
app_db:users,orders,products
report_db:sales,inventory">app_db:users,orders</textarea>
<div class="input-example">
示例:<br>
public_data:customers,transactions<br>
logs:access_logs,error_logs
</div>
</div>
</div>
</div>
<div class="form-group">
<label>高级选项</label>
<div class="checkbox-group">
<input type="checkbox" id="postgres-verify" checked>
<label for="postgres-verify">备份后验证</label>
</div>
</div>
</div>
</div>
<div class="action-buttons">
<button class="btn btn-postgres" id="generate-postgres">
<i class="fas fa-code"></i> 生成备份脚本
</button>
<button class="btn btn-secondary">
<i class="fas fa-save"></i> 保存配置
</button>
</div>
<div class="report-section">
<div class="report-header">
<h3 class="section-title"><i class="fas fa-file-code"></i> 生成的备份脚本</h3>
</div>
<div class="report-content" id="postgres-script">
<!-- 生成的脚本将显示在这里 -->
</div>
</div>
</div>
<!-- SQL Server 配置 -->
<div class="tab-content" id="sqlserver">
<h2 class="section-title"><i class="fab fa-microsoft"></i> SQL Server 备份配置</h2>
<div class="backup-type">
<div class="backup-type-btn physical active" data-type="physical">
<i class="fas fa-hard-drive"></i>
物理备份
</div>
<div class="backup-type-btn logical" data-type="logical">
<i class="fas fa-file-code"></i>
逻辑备份
</div>
</div>
<div class="config-grid">
<div class="config-card">
<h3 class="card-title"><i class="fas fa-plug"></i> 连接设置</h3>
<div class="form-group">
<label for="sqlserver-host"><i class="fas fa-server"></i> 主机地址</label>
<input type="text" id="sqlserver-host" placeholder="例如: 192.168.1.100" value="sql-server">
</div>
<div class="form-group">
<label for="sqlserver-port"><i class="fas fa-network-wired"></i> 端口</label>
<input type="text" id="sqlserver-port" value="1433">
</div>
<div class="form-group">
<label for="sqlserver-db"><i class="fas fa-database"></i> 数据库名</label>
<input type="text" id="sqlserver-db" placeholder="例如: app_db" value="app_db">
</div>
<div class="form-group">
<label for="sqlserver-user"><i class="fas fa-user"></i> 用户名</label>
<input type="text" id="sqlserver-user" placeholder="例如: sa" value="admin">
</div>
<div class="form-group">
<label for="sqlserver-password"><i class="fas fa-key"></i> 密码</label>
<input type="password" id="sqlserver-password" placeholder="输入密码" value="********">
</div>
</div>
<div class="config-card">
<h3 class="card-title"><i class="fas fa-cog"></i> 备份设置</h3>
<div class="form-group">
<label for="sqlserver-backup-path"><i class="fas fa-folder-open"></i> 备份路径</label>
<input type="text" id="sqlserver-backup-path" value="C:\\Backup\\">
</div>
<!-- 物理备份特定设置 -->
<div class="backup-options physical active">
<div class="form-group">
<label for="sqlserver-compress"><i class="fas fa-compress"></i> 压缩级别</label>
<select id="sqlserver-compress">
<option value="low">低</option>
<option value="medium" selected>中</option>
<option value="high">高</option>
</select>
</div>
<div class="form-group">
<label for="sqlserver-blocksize"><i class="fas fa-cube"></i> 块大小</label>
<select id="sqlserver-blocksize">
<option value="64">64 KB</option>
<option value="128" selected>128 KB</option>
<option value="256">256 KB</option>
</select>
</div>
</div>
<!-- 逻辑备份特定设置 - 自定义输入 -->
<div class="backup-options logical">
<div class="form-group">
<label><i class="fas fa-database"></i> 数据库和表配置</label>
<div class="custom-db-input">
<div class="input-hint">
输入格式:数据库名:表1,表2,表3(每行一个数据库)
</div>
<textarea id="sqlserver-db-config" rows="4" placeholder="例如:
AppDB:Users,Orders,Products
ReportDB:Sales,Inventory">AppDB:Users,Orders</textarea>
<div class="input-example">
示例:<br>
Northwind:Customers,Orders<br>
AdventureWorks:Product,ProductCategory
</div>
</div>
</div>
</div>
<div class="form-group">
<label>高级选项</label>
<div class="checkbox-group">
<input type="checkbox" id="sqlserver-verify" checked>
<label for="sqlserver-verify">备份后验证</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="sqlserver-checksum">
<label for="sqlserver-checksum">使用校验和</label>
</div>
</div>
</div>
</div>
<div class="action-buttons">
<button class="btn btn-sqlserver" id="generate-sqlserver">
<i class="fas fa-code"></i> 生成备份脚本
</button>
<button class="btn btn-secondary">
<i class="fas fa-save"></i> 保存配置
</button>
</div>
<div class="report-section">
<div class="report-header">
<h3 class="section-title"><i class="fas fa-file-code"></i> 生成的备份脚本</h3>
</div>
<div class="report-content" id="sqlserver-script">
<!-- 生成的脚本将显示在这里 -->
</div>
</div>
</div>
<!-- 脚本修改器 -->
<div class="tab-content" id="modifier">
<div class="tool-content">
<h2 class="tool-title"><i class="fas fa-edit"></i> 脚本修改器</h2>
<div class="tool-description">
使用此工具修改和优化现有的备份脚本。支持语法高亮、参数替换和错误检测功能。
</div>
<div class="tool-grid">
<div class="tool-card">
<h3><i class="fas fa-bolt"></i> 快速优化</h3>
<p>一键优化现有脚本,提高执行效率并减少资源占用。</p>
<button class="btn btn-modifier">
<i class="fas fa-magic"></i> 优化脚本
</button>
</div>
<div class="tool-card">
<h3><i class="fas fa-code"></i> 语法检查</h3>
<p>检查脚本语法错误,确保脚本在目标环境中能正确执行。</p>
<button class="btn btn-modifier">
<i class="fas fa-check-circle"></i> 检查语法
</button>
</div>
<div class="tool-card">
<h3><i class="fas fa-exchange-alt"></i> 变量替换</h3>
<p>批量替换脚本中的占位符变量为实际值。</p>
<button class="btn btn-modifier">
<i class="fas fa-sync-alt"></i> 替换变量
</button>
</div>
</div>
<div class="tool-feature modifier-feature">
<h3><i class="fas fa-file-code"></i> 脚本编辑器</h3>
<div class="form-group">
<label for="script-content">输入要修改的备份脚本:</label>
<textarea id="script-content" rows="12" placeholder="在此粘贴您的备份脚本..."></textarea>
</div>
<button class="btn btn-modifier">
<i class="fas fa-play"></i> 执行修改
</button>
</div>
</div>
</div>
<!-- 计划任务生成 -->
<div class="tab-content" id="scheduler">
<div class="tool-content">
<h2 class="tool-title"><i class="fas fa-calendar-alt"></i> 计划任务生成器</h2>
<div class="tool-description">
为您的备份脚本创建计划任务配置,支持Windows任务计划程序和Linux Cron配置生成。
</div>
<div class="tool-grid">
<div class="tool-card">
<h3><i class="fab fa-windows"></i> Windows任务计划</h3>
<p>生成Windows任务计划程序配置文件(.xml)或命令行。</p>
<button class="btn btn-scheduler">
<i class="fas fa-download"></i> 生成配置
</button>
</div>
<div class="tool-card">
<h3><i class="fab fa-linux"></i> Linux Cron配置</h3>
<p>生成Linux Cron配置文件或命令行。</p>
<button class="btn btn-scheduler">
<i class="fas fa-download"></i> 生成配置
</button>
</div>
<div class="tool-card">
<h3><i class="fas fa-history"></i> 执行历史</h3>
<p>查看和管理之前生成的计划任务配置。</p>
<button class="btn btn-scheduler">
<i class="fas fa-clock"></i> 查看历史
</button>
</div>
</div>
<div class="tool-feature scheduler-feature">
<h3><i class="fas fa-cogs"></i> 任务配置</h3>
<div class="config-grid">
<div class="config-card">
<h3 class="card-title"><i class="fas fa-clock"></i> 计划时间</h3>
<div class="form-group">
<label for="schedule-frequency">执行频率</label>
<select id="schedule-frequency">
<option value="daily">每天</option>
<option value="weekly" selected>每周</option>
<option value="monthly">每月</option>
<option value="hourly">每小时</option>
</select>
</div>
<div class="form-group">
<label for="schedule-time">执行时间</label>
<input type="time" id="schedule-time" value="02:00">
</div>
<div class="form-group">
<label for="schedule-days">选择星期(如果适用)</label>
<div class="checkbox-group">
<input type="checkbox" id="monday" checked>
<label for="monday">周一</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="tuesday" checked>
<label for="tuesday">周二</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="wednesday" checked>
<label for="wednesday">周三</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="thursday" checked>
<label for="thursday">周四</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="friday" checked>
<label for="friday">周五</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="saturday">
<label for="saturday">周六</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="sunday">
<label for="sunday">周日</label>
</div>
</div>
</div>
<div class="config-card">
<h3 class="card-title"><i class="fas fa-file-alt"></i> 脚本设置</h3>
<div class="form-group">
<label for="script-path">脚本路径</label>
<input type="text" id="script-path" placeholder="例如: /backup/scripts/mysql_backup.sh">
</div>
<div class="form-group">
<label for="output-log">输出日志路径</label>
<input type="text" id="output-log" placeholder="例如: /var/log/backup.log">
</div>
<div class="form-group">
<label>高级选项</label>
<div class="checkbox-group">
<input type="checkbox" id="email-notify">
<label for="email-notify">完成后发送邮件通知</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="error-only">
<label for="error-only">仅在错误时通知</label>
</div>
</div>
</div>
</div>
<button class="btn btn-scheduler">
<i class="fas fa-cogs"></i> 生成计划任务配置
</button>
</div>
</div>
</div>
</div>
</div>
<footer>
<p>多数据库备份脚本生成工具 v3.2 | © 2023 数据库管理解决方案 | 支持 Oracle, MySQL, PostgreSQL, SQL Server</p>
</footer>
</div>
<div class="notification" id="notification">
<i class="fas fa-check-circle"></i>
<span id="notification-text">脚本已复制到剪贴板!</span>
</div>
<script>
// 显示通知
function showNotification(message) {
const notification = document.getElementById('notification');
const notificationText = document.getElementById('notification-text');
notificationText.textContent = message;
notification.classList.add('show');
setTimeout(() => {
notification.classList.remove('show');
}, 3000);
}
// 可靠的复制到剪贴板函数
function copyToClipboard(text) {
// 创建临时textarea元素
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.setAttribute('readonly', '');
textarea.style.position = 'absolute';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
// 选择文本
textarea.select();
try {
// 尝试使用新的Clipboard API
if (navigator.clipboard) {
navigator.clipboard.writeText(text).then(() => {
showNotification('脚本已复制到剪贴板!');
}).catch(err => {
// 如果Clipboard API失败,使用传统方法
document.execCommand('copy');
showNotification('脚本已复制到剪贴板!');
});
} else {
// 使用传统方法
document.execCommand('copy');
showNotification('脚本已复制到剪贴板!');
}
} catch (err) {
showNotification('复制失败: ' + err);
} finally {
// 移除临时元素
document.body.removeChild(textarea);
}
}
// 数据库切换功能
document.querySelectorAll('.sidebar-option[data-tab]').forEach(option => {
option.addEventListener('click', () => {
// 移除所有活动标签
document.querySelectorAll('.sidebar-option').forEach(el => {
el.classList.remove('active');
});
// 设置当前选项为活动状态
option.classList.add('active');
// 隐藏所有内容区域
document.querySelectorAll('.tab-content').forEach(el => {
el.classList.remove('active');
});
// 显示选中的内容区域
const tabId = option.getAttribute('data-tab');
document.getElementById(tabId).classList.add('active');
});
});
// 备份类型切换
document.querySelectorAll('.backup-type-btn').forEach(btn => {
btn.addEventListener('click', () => {
const parent = btn.parentElement;
const backupType = btn.dataset.type;
// 更新按钮状态
parent.querySelectorAll('.backup-type-btn').forEach(b => {
b.classList.remove('active');
});
btn.classList.add('active');
// 更新备份选项显示
const container = parent.closest('.tab-content');
container.querySelectorAll('.backup-options').forEach(opt => {
opt.classList.remove('active');
});
container.querySelectorAll(`.backup-options.${backupType}`).forEach(opt => {
opt.classList.add('active');
});
});
});
// 表选择功能
document.querySelectorAll('.table-item').forEach(item => {
item.addEventListener('click', function() {
this.classList.toggle('selected');
});
});
// 数据库选择功能
document.querySelectorAll('.database-item input').forEach(input => {
input.addEventListener('change', function() {
const parent = this.closest('.database-item');
parent.classList.toggle('selected', this.checked);
});
});
// 生成Oracle备份脚本
document.getElementById('generate-oracle').addEventListener('click', () => {
const host = document.getElementById('oracle-host').value || 'dbserver01';
const port = document.getElementById('oracle-port').value || '1521';
const service = document.getElementById('oracle-service').value || 'ORCL';
const user = document.getElementById('oracle-user').value || 'sys as sysdba';
const path = document.getElementById('oracle-backup-path').value || '/backup/oracle/';
const isPhysical = document.querySelector('#oracle .backup-type-btn.physical').classList.contains('active');
let script = '';
if (isPhysical) {
// 物理备份脚本
const parallel = document.getElementById('oracle-parallel').value || 4;
const compression = document.getElementById('oracle-compression').value || 'medium';
const encryption = document.getElementById('oracle-encryption').checked;
const validate = document.getElementById('oracle-validate').checked;
script = `#!/bin/bash
# Oracle 物理备份脚本 (RMAN)
# 生成时间: ${new Date().toLocaleString()}
# 配置参数
HOST="${host}"
PORT="${port}"
SERVICE="${service}"
USER="${user}"
BACKUP_DIR="${path}"
PARALLEL=${parallel}
COMPRESSION="${compression}"
echo "开始Oracle物理备份..."
echo "目标主机: $HOST:$PORT/$SERVICE"
echo "备份目录: $BACKUP_DIR"
echo "并行度: $PARALLEL"
echo "压缩级别: $COMPRESSION"
${encryption ? 'echo "加密: 启用"' : ''}
${validate ? 'echo "验证: 启用"' : ''}
# 创建备份目录
mkdir -p $BACKUP_DIR
# 运行RMAN备份
rman target $USER/$SERVICE << EOF
run {
allocate channel ch1 type disk;
allocate channel ch2 type disk;
${parallel > 2 ? `allocate channel ch3 type disk;\n allocate channel ch4 type disk;` : ''}
set compression on for backup;
${encryption ? 'set encryption on;' : ''}
backup as compressed backupset database
format '${path}full_%d_%T_%U.bkp'
tag 'FULL_DB_BACKUP';
backup current controlfile
format '${path}control_%d_%T_%U.bkp';
backup archivelog all delete input;
release channel ch1;
release channel ch2;
${parallel > 2 ? 'release channel ch3;\n release channel ch4;' : ''}
}
EOF
${validate ? `
echo "验证备份文件..."
rman target $USER/$SERVICE << EOF
validate backupset all;
EOF
` : ''}
echo "备份完成! 备份文件保存在 $BACKUP_DIR";
`;
} else {
// 逻辑备份脚本
const encryption = document.getElementById('oracle-encryption').checked;
const validate = document.getElementById('oracle-validate').checked;
const dbConfig = document.getElementById('oracle-db-config').value;
// 解析自定义数据库配置
const dbEntries = dbConfig.split('\n').filter(line => line.trim() !== '');
let backupCommands = '';
let validateCommands = '';
const dateStr = "$(date +%Y%m%d_%H%M%S)";
dbEntries.forEach((entry, index) => {
const [dbName, tables] = entry.split(':').map(item => item.trim());
if (dbName && tables) {
const tableList = tables.split(',').map(t => t.trim()).filter(t => t !== '').join(',');
const dumpFile = `${path}${dbName.toLowerCase()}_tables_${dateStr}.dmp`;
const logFile = `${path}${dbName.toLowerCase()}_tables_${dateStr}.log`;
backupCommands += `
echo "备份数据库 ${dbName} 中的表: ${tableList}"
expdp $USER/$SERVICE@$HOST:$PORT/$SERVICE \\
tables=${tableList} \\
directory=DATA_PUMP_DIR \\
dumpfile=${dumpFile} \\
logfile=${logFile} \\
compression=all \\
${encryption ? 'encryption_password=backup_pass' : ''}
`;
if (validate) {
validateCommands += `
echo "验证备份文件: ${dumpFile}"
impdp $USER/$SERVICE@$HOST:$PORT/$SERVICE \\
sqlfile=${dumpFile.replace('.dmp', '.sql')} \\
directory=DATA_PUMP_DIR \\
dumpfile=${dumpFile} \\
validate_only=y
`;
}
}
});
script = `#!/bin/bash
# Oracle 逻辑备份脚本 (expdp)
# 生成时间: ${new Date().toLocaleString()}
# 配置参数
HOST="${host}"
PORT="${port}"
SERVICE="${service}"
USER="${user}"
BACKUP_DIR="${path}"
echo "开始Oracle逻辑备份..."
echo "目标主机: $HOST:$PORT/$SERVICE"
echo "备份目录: $BACKUP_DIR"
${encryption ? 'echo "加密: 启用"' : ''}
${validate ? 'echo "验证: 启用"' : ''}
# 创建备份目录
mkdir -p $BACKUP_DIR
${backupCommands}
${validate ? validateCommands : ''}
echo "备份完成! 备份文件保存在 $BACKUP_DIR";
`;
}
const reportContent = document.getElementById('oracle-script');
reportContent.innerHTML = `<pre class="script-content">${script}</pre>
<button class="copy-btn" onclick="copyToClipboard(\`${script}\`)"><i class="fas fa-copy"></i> 复制脚本</button>`;
});
// 生成MySQL备份脚本
document.getElementById('generate-mysql').addEventListener('click', () => {
const host = document.getElementById('mysql-host').value || 'db-mysql-01';
const port = document.getElementById('mysql-port').value || '3306';
const user = document.getElementById('mysql-user').value || 'admin';
const path = document.getElementById('mysql-backup-path').value || '/backup/mysql/';
const isPhysical = document.querySelector('#mysql .backup-type-btn.physical').classList.contains('active');
let script = '';
if (isPhysical) {
// 物理备份脚本
const threads = document.getElementById('mysql-threads').value || 4;
const compression = document.getElementById('mysql-compression').value || 2;
const encryption = document.getElementById('mysql-encryption').checked;
script = `#!/bin/bash
# MySQL 物理备份脚本 (Percona XtraBackup)
# 生成时间: ${new Date().toLocaleString()}
# 配置参数
HOST="${host}"
PORT="${port}"
USER="${user}"
BACKUP_DIR="${path}"
THREADS=${threads}
COMPRESSION=${compression}
echo "开始MySQL物理备份..."
echo "目标主机: $HOST:$PORT"
echo "备份目录: $BACKUP_DIR"
echo "线程数: $THREADS"
echo "压缩级别: $COMPRESSION"
${encryption ? 'echo "加密: 启用"' : ''}
# 创建备份目录
mkdir -p $BACKUP_DIR
# 运行XtraBackup
xtrabackup \\
--host=$HOST \\
--port=$PORT \\
--user=$USER \\
--password=your_password_here \\
--backup \\
--target-dir=$BACKUP_DIR \\
--compress \\
--compress-threads=$THREADS \\
--parallel=$THREADS \\
${encryption ? '--encrypt=AES256 --encrypt-key="your_encryption_key"' : ''}
echo "准备备份文件..."
xtrabackup --prepare --target-dir=$BACKUP_DIR
echo "备份完成! 备份文件保存在 $BACKUP_DIR";
`;
} else {
// 逻辑备份脚本
const encryption = document.getElementById('mysql-encryption').checked;
const dbConfig = document.getElementById('mysql-db-config').value;
// 解析自定义数据库配置
const dbEntries = dbConfig.split('\n').filter(line => line.trim() !== '');
let backupCommands = '';
const dateStr = "$(date +%Y%m%d_%H%M%S)";
dbEntries.forEach((entry, index) => {
const [dbName, tables] = entry.split(':').map(item => item.trim());
if (dbName && tables) {
const tableList = tables.split(',').map(t => t.trim()).filter(t => t !== '').join(' ');
const dumpFile = `${path}${dbName}_tables_${dateStr}.sql`;
backupCommands += `
echo "备份数据库 ${dbName} 中的表: ${tableList}"
mysqldump \\
-h $HOST \\
-P $PORT \\
-u $USER \\
-p \\
${dbName} \\
${tableList} \\
${encryption ? '--encrypt=AES256 --encrypt-key="your_encryption_key"' : ''} \\
> ${dumpFile}
`;
}
});
script = `#!/bin/bash
# MySQL 逻辑备份脚本 (mysqldump)
# 生成时间: ${new Date().toLocaleString()}
# 配置参数
HOST="${host}"
PORT="${port}"
USER="${user}"
BACKUP_DIR="${path}"
echo "开始MySQL逻辑备份..."
echo "目标主机: $HOST:$PORT"
echo "备份目录: $BACKUP_DIR"
${encryption ? 'echo "加密: 启用"' : ''}
# 创建备份目录
mkdir -p $BACKUP_DIR
${backupCommands}
echo "备份完成! 备份文件保存在 $BACKUP_DIR";
`;
}
const reportContent = document.getElementById('mysql-script');
reportContent.innerHTML = `<pre class="script-content">${script}</pre>
<button class="copy-btn" onclick="copyToClipboard(\`${script}\`)"><i class="fas fa-copy"></i> 复制脚本</button>`;
});
// 生成PostgreSQL备份脚本
document.getElementById('generate-postgres').addEventListener('click', () => {
const host = document.getElementById('postgres-host').value || 'pg-server';
const port = document.getElementById('postgres-port').value || '5432';
const user = document.getElementById('postgres-user').value || 'admin';
const path = document.getElementById('postgres-backup-path').value || '/backup/postgres/';
const isPhysical = document.querySelector('#postgres .backup-type-btn.physical').classList.contains('active');
let script = '';
if (isPhysical) {
// 物理备份脚本
const compress = document.getElementById('postgres-compress').value || 6;
const checkpoint = document.getElementById('postgres-checkpoint').value || 'spread';
const verify = document.getElementById('postgres-verify').checked;
script = `#!/bin/bash
# PostgreSQL 物理备份脚本 (pg_basebackup)
# 生成时间: ${new Date().toLocaleString()}
# 配置参数
HOST="${host}"
PORT="${port}"
USER="${user}"
BACKUP_DIR="${path}"
COMPRESSION=${compress}
CHECKPOINT="${checkpoint}"
echo "开始PostgreSQL物理备份..."
echo "目标主机: $HOST:$PORT"
echo "备份目录: $BACKUP_DIR"
echo "压缩级别: $COMPRESSION"
echo "检查点模式: $CHECKPOINT"
${verify ? 'echo "验证: 启用"' : ''}
# 创建备份目录
mkdir -p $BACKUP_DIR
# 运行物理备份
pg_basebackup \\
-h $HOST \\
-p $PORT \\
-U $USER \\
-D $BACKUP_DIR/postgres_basebackup_$(date +%Y%m%d) \\
-Ft \\
-z -Z $COMPRESSION \\
-c $CHECKPOINT \\
-P
${verify ? `
echo "验证备份文件..."
pg_verifybackup $BACKUP_DIR/postgres_basebackup_$(date +%Y%m%d)
` : ''}
echo "备份完成! 备份文件保存在 $BACKUP_DIR";
`;
} else {
// 逻辑备份脚本
const verify = document.getElementById('postgres-verify').checked;
const dbConfig = document.getElementById('postgres-db-config').value;
// 解析自定义数据库配置
const dbEntries = dbConfig.split('\n').filter(line => line.trim() !== '');
let backupCommands = '';
let verifyCommands = '';
const dateStr = "$(date +%Y%m%d_%H%M%S)";
dbEntries.forEach((entry, index) => {
const [dbName, tables] = entry.split(':').map(item => item.trim());
if (dbName && tables) {
const tableList = tables.split(',').map(t => t.trim()).filter(t => t !== '');
let tableOptions = '';
tableList.forEach(table => {
tableOptions += ` -t ${table}`;
});
const dumpFile = `${path}${dbName}_tables_${dateStr}.dump`;
backupCommands += `
echo "备份数据库 ${dbName} 中的表: ${tableList.join(', ')}"
pg_dump \\
-h $HOST \\
-p $PORT \\
-U $USER \\
-d ${dbName} \\
${tableOptions} \\
-Fc \\
-f ${dumpFile}
`;
if (verify) {
verifyCommands += `
echo "验证备份文件: ${dumpFile}"
pg_restore -l ${dumpFile} > /dev/null
if [ $? -eq 0 ]; then
echo "备份验证成功!"
else
echo "备份验证失败!"
fi
`;
}
}
});
script = `#!/bin/bash
# PostgreSQL 逻辑备份脚本 (pg_dump)
# 生成时间: ${new Date().toLocaleString()}
# 配置参数
HOST="${host}"
PORT="${port}"
USER="${user}"
BACKUP_DIR="${path}"
echo "开始PostgreSQL逻辑备份..."
echo "目标主机: $HOST:$PORT"
echo "备份目录: $BACKUP_DIR"
${verify ? 'echo "验证: 启用"' : ''}
# 创建备份目录
mkdir -p $BACKUP_DIR
${backupCommands}
${verify ? verifyCommands : ''}
echo "备份完成! 备份文件保存在 $BACKUP_DIR";
`;
}
const reportContent = document.getElementById('postgres-script');
reportContent.innerHTML = `<pre class="script-content">${script}</pre>
<button class="copy-btn" onclick="copyToClipboard(\`${script}\`)"><i class="fas fa-copy"></i> 复制脚本</button>`;
});
// 生成SQL Server备份脚本
document.getElementById('generate-sqlserver').addEventListener('click', () => {
const host = document.getElementById('sqlserver-host').value || 'sql-server';
const port = document.getElementById('sqlserver-port').value || '1433';
const user = document.getElementById('sqlserver-user').value || 'admin';
const path = document.getElementById('sqlserver-backup-path').value || 'C:\\Backup\\';
const isPhysical = document.querySelector('#sqlserver .backup-type-btn.physical').classList.contains('active');
let script = '';
if (isPhysical) {
// 物理备份脚本
const compress = document.getElementById('sqlserver-compress').value || 'medium';
const blocksize = document.getElementById('sqlserver-blocksize').value || 128;
const verify = document.getElementById('sqlserver-verify').checked;
const checksum = document.getElementById('sqlserver-checksum').checked;
script = `-- SQL Server 物理备份脚本
-- 生成时间: ${new Date().toLocaleString()}
-- 配置参数
DECLARE @backupPath NVARCHAR(255) = '${path.replace(/\\/g, '\\\\')}sqlserver_backup_${new Date().getTime()}.bak'
DECLARE @compression NVARCHAR(20) = '${compress}'
DECLARE @blocksize INT = ${blocksize} * 1024
DECLARE @verify BIT = ${verify ? 1 : 0}
DECLARE @checksum BIT = ${checksum ? 1 : 0}
-- 开始备份
BACKUP DATABASE [APP_DB]
TO DISK = @backupPath
WITH
FORMAT,
COMPRESSION,
BLOCKSIZE = @blocksize,
${checksum ? 'CHECKSUM,' : ''}
STATS = 5;
${verify ? `
-- 验证备份
RESTORE VERIFYONLY
FROM DISK = @backupPath
WITH CHECKSUM;
` : ''}
PRINT '备份完成! 备份文件保存在: ' + @backupPath;
`;
} else {
// 逻辑备份脚本
const verify = document.getElementById('sqlserver-verify').checked;
const dbConfig = document.getElementById('sqlserver-db-config').value;
// 解析自定义数据库配置
const dbEntries = dbConfig.split('\n').filter(line => line.trim() !== '');
let backupCommands = '';
let verifyCommands = '';
const dateStr = "CONVERT(NVARCHAR, GETDATE(), 112) + '_' + REPLACE(CONVERT(NVARCHAR, GETDATE(), 108), ':', '')";
dbEntries.forEach((entry, index) => {
const [dbName, tables] = entry.split(':').map(item => item.trim());
if (dbName && tables) {
const tableList = tables.split(',').map(t => t.trim()).filter(t => t !== '');
tableList.forEach(table => {
const dataFile = `@backupPath + '${dbName}_${table}_' + ${dateStr} + '.dat'`;
backupCommands += `
PRINT '正在备份表: ${dbName}.dbo.${table}'
EXEC xp_cmdshell 'bcp "${dbName}.dbo.${table}" out "' + ${dataFile} + '" -T -c -t,'
`;
if (verify) {
verifyCommands += `
PRINT '验证表: ${dbName}.dbo.${table}'
DECLARE @${table.replace(/\s/g, '')}Count INT
SELECT @${table.replace(/\s/g, '')}Count = COUNT(*) FROM [${dbName}].dbo.[${table}]
PRINT '源表行数: ' + CAST(@${table.replace(/\s/g, '')}Count AS NVARCHAR)
DECLARE @${table.replace(/\s/g, '')}BackupCount INT
EXEC xp_cmdshell 'find /c /v "" "' + ${dataFile} + '"', no_output
SELECT @${table.replace(/\s/g, '')}BackupCount = CAST(REPLACE(@@ROWCOUNT, '行数', '') AS INT) - 1
PRINT '备份行数: ' + CAST(@${table.replace(/\s/g, '')}BackupCount AS NVARCHAR)
IF @${table.replace(/\s/g, '')}Count <> @${table.replace(/\s/g, '')}BackupCount
PRINT '警告: ${table}表备份行数与源表不一致!'
`;
}
});
}
});
script = `-- SQL Server 逻辑备份脚本
-- 生成时间: ${new Date().toLocaleString()}
-- 配置参数
DECLARE @backupPath NVARCHAR(255) = '${path.replace(/\\/g, '\\\\')}'
DECLARE @dateStr NVARCHAR(20) = ${dateStr}
DECLARE @verify BIT = ${verify ? 1 : 0}
PRINT '开始SQL Server逻辑备份...'
PRINT '目标主机: ${host}:${port}'
PRINT '备份目录: ' + @backupPath
${backupCommands}
${verify ? verifyCommands : ''}
PRINT '备份完成! 备份文件保存在: ' + @backupPath;
`;
}
const reportContent = document.getElementById('sqlserver-script');
reportContent.innerHTML = `<pre class="script-content">${script}</pre>
<button class="copy-btn" onclick="copyToClipboard(\`${script}\`)"><i class="fas fa-copy"></i> 复制脚本</button>`;
});
// 初始化页面
document.addEventListener('DOMContentLoaded', () => {
// 生成初始Oracle脚本
document.getElementById('generate-oracle').click();
// 初始化备份选项显示
document.querySelectorAll('.backup-options').forEach(opt => {
opt.classList.remove('active');
});
document.querySelectorAll('.backup-options.physical').forEach(opt => {
opt.classList.add('active');
});
});
</script>
</body>
</html>