提交 ed572ca0 authored 作者: 陈泽健's avatar 陈泽健

feat(skills,deploy): 新增 DM8-PROCESS 技能、达梦数据库导入脚本升级、统一平台集群部署文档

主要变更:

1. 新增 .claude/skills/DM8-PROCESS/ 技能目录,整理 80 个达梦数据库运维脚本
2. 升级 import_dm8_databases.sh(arm/x86),新增字段名大写转换、重复列清理、自增序列批量创建、默认值修复等功能
3. 新增 import_dm_dmp.sh 和 import_dm_nacos_data.sh 导入脚本及 README 说明
4. 新增 Docs/PRD/新统一平台集群部署/ 需求文档、计划执行文档、方案目录
5. 新增 Docs/PRD/达梦数据库/ 问题追踪、对比记录、修复记录等文档
6. 更新 Troubleshoot SKILL.md 关联文件路径(迁移至 troubleshoot-ai-assistant 子项目)
7. 修正 CreateCMD 启动脚本工作目录路径
8. 新增 PowerShell 权限白名单配置
9. 更新 .gitignore 忽略日志、dmp文件、临时文件等
10. 删除已迁移的问题知识库旧文档(20个文件)
Co-Authored-By: 's avatarClaude <noreply@anthropic.com>
上级 6a43d4b2
......@@ -159,7 +159,9 @@
"Bash(cd \"E:\\\\\\\\GithubData\\\\\\\\ubains-module-test\\\\\\\\AuxiliaryTool\\\\\\\\ScriptTool\\\\\\\\新服务自检\")",
"Bash(sed -i '1914,1985d' check_server_health.ps1)",
"Bash(awk '/^ # EMQX增强检测 - 综合指标统计/,/^ catch {/' \"C:\\\\Users\\\\UBAINS\\\\Desktop\\\\Test\\\\check_server_health.ps1\")",
"Bash(awk 'NR>=2750 && NR<=2800' \"E:\\\\GithubData\\\\ubains-module-test\\\\AuxiliaryTool\\\\ScriptTool\\\\新服务自检\\\\check_server_health.ps1\")"
"Bash(awk 'NR>=2750 && NR<=2800' \"E:\\\\GithubData\\\\ubains-module-test\\\\AuxiliaryTool\\\\ScriptTool\\\\新服务自检\\\\check_server_health.ps1\")",
"PowerShell(Get-ChildItem *)",
"PowerShell(Get-Content *)"
]
}
}
@echo off
cd /d E:\GithubData\ubains-module-test\develop
cd /d E:\github\ubains-module-test\develop
E:\nodejs\claude.cmd --permission-mode bypassPermissions
# DM8-PROCESS - 达梦V8数据库处理技能
## 技能说明
本技能用于达梦V8数据库的日常运维、数据迁移、结构修复等操作。
## 环境信息
| 项目 | 信息 |
|------|------|
| 达梦服务器 | 192.168.5.40:5236 |
| 达梦容器 | dm8-server |
| SYSDBA密码 | Dameng2026Pwd |
| MySQL服务器 | 192.168.5.41:8306 |
| MySQL用户 | root / dNrprU&2S |
## 数据库用户密码
| 用户 | 密码 | 说明 |
|------|------|------|
| SYSDBA | Dameng2026Pwd | 系统管理员 |
| DM_UBAINS | dNrprU&2S! | 预定系统库 |
| DM_NACOS | Nacos@2026Pwd | Nacos配置库 |
| DM_HUAZHAO2 | Huazhao@2026 | 华招库 |
| DM_DEVOPS_VOICE | Devops@2026Pwd | 语音库 |
| DM_DEVOPS | Devops@2026Pwd | 运维库 |
## code目录脚本(共80个)
### 1. 自动化部署脚本(5个)
| 脚本 | 说明 |
|------|------|
| `import_dm8_databases.sh` | 主数据库导入脚本 |
| `import_dm_dmp.sh` | DMP文件导入脚本 |
| `import_dm_nacos_data.sh` | Nacos数据导入脚本 |
| `auto_deploy_dm8.sh` | 自动部署达梦 |
| `migrate_nacos_data.sh` | Nacos数据迁移 |
### 2. Docker容器部署与管理(11个)
| 脚本 | 说明 |
|------|------|
| `deploy_dm8_docker.py` | Docker方式部署达梦 |
| `deploy_dm8_mount.py` | 挂载方式部署达梦 |
| `dm8_container_deploy.sh` | 容器部署脚本 |
| `init_dm8_instance.py` | 初始化达梦实例 |
| `reset_dm8_container.py` | 重置达梦容器 |
| `check_dm8_status.py` | 检查达梦状态 |
| `check_server_env.py` | 检查服务器环境 |
| `build_image.sh` | 构建镜像 |
| `deploy_5236.sh` | 部署5236端口 |
| `start_dm8.sh` / `start_dm8_5236.sh` | 启动达梦 |
| `init_instance.sh` | 初始化实例 |
### 3. 数据迁移(MySQL → 达梦)(7个)
| 脚本 | 说明 |
|------|------|
| `mysql_to_dm8_converter.py` | MySQL到达梦转换器 |
| `bridge_migrate_v2.py` | 桥接迁移V2 |
| `migrate_on_server.py` | 服务器端迁移 |
| `import_sql_to_dm8.py` | 导入SQL到达梦 |
| `upload_sql_to_server.py` | 上传SQL到服务器 |
| `final_deploy.sh` | 最终部署 |
| `entrypoint.sh` / `container_entrypoint.sh` | 容器入口 |
### 4. Nacos数据迁移(5个)
| 脚本 | 说明 |
|------|------|
| `migrate_dm_nacos_v10.py` | Nacos迁移V10(最终版) |
| `import_dm_nacos_dmpython.py` | dmPython导入Nacos |
| `import_dm_nacos_final.py` | Nacos导入最终版 |
| `fix_duplicate_ids.py` | 修复重复ID |
| `fix_config_info.py` / `fix_config_mysqldump.py` | 修复CONFIG_INFO |
| `update_nacos_config_to_dm.py` | 更新Nacos配置 |
| `optimize_dm_nacos.py` | 优化Nacos |
### 5. DEVOPS数据迁移(5个)
| 脚本 | 说明 |
|------|------|
| `migrate_devops_final.py` | DEVOPS迁移最终版 |
| `migrate_devops_all.py` | 迁移所有DEVOPS数据 |
| `migrate_devops_docker_cp.py` | docker cp方式迁移 |
| `migrate_devops_core_data.py` | 迁移核心数据 |
| `fix_devops_stage1.py` / `fix_devops_stage2.py` | DEVOPS修复 |
### 6. 字段名大小写修复(5个)
| 脚本 | 说明 |
|------|------|
| `check_column_case.py` | 检查字段名大小写 |
| `fix_column_case.py` | 生成字段名大写转换SQL |
| `compare_all_columns.py` | 对比MySQL和达梦所有字段 |
| `fix_column_case_remote.sh` | 远程修复字段名大小写 |
| `check_dm_case.py` | 检查大小写 |
### 7. 结构修复(序列、默认值、表、列)(11个)
| 脚本 | 说明 |
|------|------|
| `batch_add_sequences.py` | 批量创建自增序列 |
| `batch_add_defaults.py` | 批量添加默认值 |
| `fix_dm_defaults_final.py` | 默认值修复最终版 |
| `fix_dm_defaults_full.py` | 完整默认值修复 |
| `create_missing_tables.py` | 创建缺失的表 |
| `add_columns_upper.py` | 添加缺失的列 |
| `add_missing_columns.py` | 添加缺失的列 |
| `add_final_defaults.py` | 添加最终默认值 |
| `fix_dm_reserved_words.py` | 修复保留字 |
| `fix_user_table.py` | 修复user表 |
| `drop_dup_cols.py` | 删除重复列 |
### 8. HUAZHAO2和DEVOPS_VOICE修复(3个)
| 脚本 | 说明 |
|------|------|
| `check_dm_huazhao_voice_v2.py` | 核对HUAZHAO2和DEVOPS_VOICE |
| `fix_dm_huazhao2_final.py` | HUAZHAO2修复最终版 |
| `fix_dm_huazhao_voice_final.py` | DEVOPS_VOICE修复最终版 |
### 9. 库对比检查(13个)
| 脚本 | 说明 |
|------|------|
| `check_devops_full_v2.py` | 完整对比DEVOPS库 |
| `check_devops_structure.py` | 检查DEVOPS结构 |
| `check_devops_data.py` | 检查DEVOPS数据 |
| `check_dm_defaults_v3.py` | 检查默认值V3 |
| `check_table_usage.py` | 检查表使用情况 |
| `check_large_tables.py` | 检查大表 |
| `check_mysql_actual_data.py` | 检查MySQL实际数据 |
| `check_mysql_devops_data.py` | 检查MySQL DEVOPS数据 |
| `check_pk.py` | 检查主键 |
| `check_token.py` | 检查token |
| `check_user_table.py` | 检查user表 |
| `count_tables.py` | 统计表数量 |
| `list_dm_devops_tables.py` | 列出DEVOPS表 |
### 10. 数据修复与迁移(6个)
| 脚本 | 说明 |
|------|------|
| `fix_dm8_data_migration.py` | 数据迁移修复 |
| `fix_dm8_final.py` | 最终修复 |
| `fix_dm8_remote_v3.py` | 远程修复V3 |
| `verify_table_data.py` | 验证表数据 |
| `verify_dm8_import.py` | 验证达梦导入 |
| `verify_migration.py` | 验证迁移 |
### 11. 其他辅助脚本(7个)
| 脚本 | 说明 |
|------|------|
| `analyze_table_usage.py` | 分析表使用 |
| `find_dm_pwd.py` | 查找密码 |
| `quick_verify.py` | 快速验证 |
## 使用方法
```bash
# 在Claude Code中调用
/DM8-PROCESS [参数]
```
## 注意事项
1. **密码特殊字符**`dNrprU&2S!` 包含 `&``!`,在bash中需用单引号包裹
2. **disql 2499字符限制**:长SQL需使用dmPython直连
3. **表名大小写**:达梦建议统一使用大写表名和字段名
4. **CURRENT_TIMESTAMP**:达梦中使用 `SYSDATE` 替代
5. **保留字处理**:保留字作为表名或列名需用双引号包裹
## 相关文档
- `Docs/PRD/达梦数据库/_PRD_字段名大小写修复需求文档.md`
- `Docs/PRD/达梦数据库/_ISSUE_DM_NACOS_数据迁移问题.md`
- `Docs/PRD/达梦数据库/_ISSUE_DM_HUAZHAO2_DEVOPS_VOICE_修复记录.md`
- `Docs/PRD/达梦数据库/_ISSUE_DM_DEVOPS_完整对比记录.md`
- `Docs/PRD/达梦数据库/_ISSUE_192.168.5.40_问题追踪.md`
- `自动化部署脚本/x86架构/达梦数据库/README.md`
- `自动化部署脚本/arm架构/达梦数据库/README.md`
## 变更记录
| 版本 | 日期 | 变更内容 |
|------|------|----------|
| 1.0 | 2026-07-12 | 创建skill目录结构,整理153个脚本 |
| 1.1 | 2026-07-12 | 清理73个无用脚本,保留80个核心脚本 |
\ No newline at end of file
#!/usr/bin/env python3
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='192.168.5.40', port=22, username='root', password='Ubains@123', timeout=10)
def exe_sql(sql):
cmd = 'docker exec -i dm8-server bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql SYSDBA/Dameng2026Pwd@localhost:5236"'
s, o, e = ssh.exec_command(cmd, timeout=60)
s.write(sql)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore')
# 用大写表名添加列
COLUMNS = [
('UVOICE_ROOMMASTER', 'MEETINGFUNCTION', 'VARCHAR(200)'),
('UVOICE_ROOMMASTER', 'CAPACITY', 'INT DEFAULT 0'),
('UVOICE_ROOMMEETING', 'TXT_WAVEFORM_DATA', 'TEXT'),
('UVOICE_ROOMUSER', 'TOKEN_CREATED_AT', 'TIMESTAMP'),
('UVOICE_ROOMUSER', 'TOKEN_EXPIRES_AT', 'TIMESTAMP'),
('UVOICE_ROOMUSER', 'HAS_VOICEPRINT', 'VARCHAR(10)'),
('UVOICE_ROOMUSER', 'OA_USER_ID', 'VARCHAR(100)'),
('UVOICE_ROOMUSER', 'OA_PROVIDER', 'VARCHAR(50)'),
('UVOICE_ROOMUSER', 'OA_DEPT_ID', 'VARCHAR(100)'),
('UVOICE_ROOMUSER', 'LAST_SYNCED_AT', 'TIMESTAMP'),
]
success = 0
for table, column, col_def in COLUMNS:
sql = f'ALTER TABLE DM_DEVOPS_VOICE.{table} ADD {column} {col_def};\n'
output = exe_sql(sql)
if 'executed successfully' in output or ('error' not in output.lower() and '错误' not in output):
print(f'{table}.{column} OK')
success += 1
else:
print(f'{table}.{column} 失败: {output[:100]}')
print(f'\n成功: {success}/{len(COLUMNS)}')
ssh.close()
\ No newline at end of file
#!/usr/bin/env python3
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='192.168.5.40', port=22, username='root', password='Ubains@123', timeout=10)
def exe_sql(sql):
cmd = 'docker exec -i dm8-server bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql SYSDBA/Dameng2026Pwd@localhost:5236"'
s, o, e = ssh.exec_command(cmd, timeout=60)
s.write(sql)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore')
# 添加剩余的默认值
sql1 = "ALTER TABLE DM_DEVOPS_VOICE.UVOICE_ROOMMEETING MODIFY TXT_WAVEFORM_DATA TEXT DEFAULT NULL;\n"
sql2 = "ALTER TABLE DM_DEVOPS_VOICE.UVOICE_ROOMUSER MODIFY TOKEN VARCHAR(8188) DEFAULT NULL;\n"
sql3 = "ALTER TABLE DM_DEVOPS_VOICE.UVOICE_ROOMUSER MODIFY HAS_VOICEPRINT VARCHAR(10) DEFAULT '0';\n"
print("UVOICE_ROOMMEETING.TXT_WAVEFORM_DATA")
print(exe_sql(sql1)[:100])
print("\nUVOICE_ROOMUSER.TOKEN")
print(exe_sql(sql2)[:100])
print("\nUVOICE_ROOMUSER.HAS_VOICEPRINT")
print(exe_sql(sql3)[:100])
ssh.close()
\ No newline at end of file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
添加缺失的列
"""
import paramiko
SSH_HOST = '192.168.5.40'
SSH_USER = 'root'
SSH_PWD = 'Ubains@123'
CONTAINER = 'dm8-server'
DM_PORT = 5236
DM_SYSDBA_PWD = 'Dameng2026Pwd'
# 需要添加的列
# (表名, 列名, 列定义)
COLUMNS_TO_ADD = [
('uvoice_roommaster', 'IMAGEURL', 'VARCHAR(500)'),
('uvoice_roommaster', 'MEETINGFUNCTION', 'VARCHAR(200)'),
('uvoice_roommaster', 'CAPACITY', 'INT DEFAULT 0'),
('uvoice_roommeeting', 'TXT_WAVEFORM_DATA', 'TEXT'),
('uvoice_roomuser', 'TOKEN_CREATED_AT', 'TIMESTAMP'),
('uvoice_roomuser', 'TOKEN_EXPIRES_AT', 'TIMESTAMP'),
('uvoice_roomuser', 'HAS_VOICEPRINT', 'VARCHAR(10)'),
('uvoice_roomuser', 'OA_USER_ID', 'VARCHAR(100)'),
('uvoice_roomuser', 'OA_PROVIDER', 'VARCHAR(50)'),
('uvoice_roomuser', 'OA_DEPT_ID', 'VARCHAR(100)'),
('uvoice_roomuser', 'LAST_SYNCED_AT', 'TIMESTAMP'),
]
def create_ssh():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=SSH_HOST, port=22, username=SSH_USER, password=SSH_PWD, timeout=10)
return ssh
def exe_sql(ssh, sql):
cmd = f'docker exec -i {CONTAINER} bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql SYSDBA/{DM_SYSDBA_PWD}@localhost:{DM_PORT}"'
s, o, e = ssh.exec_command(cmd, timeout=60)
s.write(sql)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore')
def main():
print("=" * 60)
print("添加缺失的列")
print("=" * 60)
ssh = create_ssh()
print("\nSSH 连接成功")
success = 0
failed = 0
for table, column, col_def in COLUMNS_TO_ADD:
print(f"\n{table}.{column}")
# 生成 ALTER TABLE 语句
sql = f'ALTER TABLE DM_DEVOPS_VOICE."{table}" ADD "{column}" {col_def};\n'
output = exe_sql(ssh, sql)
if 'executed successfully' in output or ('error' not in output.lower() and '错误' not in output):
print(" 成功")
success += 1
elif 'already exists' in output.lower() or '已存在' in output:
print(" 列已存在")
success += 1
else:
print(f" 失败: {output[:150]}")
failed += 1
ssh.close()
print("\n" + "=" * 60)
print(f"完成: 成功 {success}, 失败 {failed}")
print("=" * 60)
if __name__ == '__main__':
main()
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
查看关键表的结构和用途(使用小写表名)
"""
import paramiko
import sys
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.5.41', port=22, username='root', password='Ubains@123', timeout=10)
tables = [
('cmdb_servermonitor_date', '服务器监控日期数据', 28161),
('cmdb_datemonitor', '日期监控数据', 9871),
('cmdb_servermonitor', '服务器监控配置', 302),
('uvoice_recordtime', '录音时间记录', 615),
('auth_permission', 'Django权限表', 344),
('uvoice_roommeeting', '会议室会议记录', 317),
]
for table, desc, rows in tables:
print("\n" + "=" * 100)
print(f"表名: {table} ({desc}) - {rows} 行")
print("=" * 100)
# 查看表结构
cmd = f'''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' --batch devops -e "DESCRIBE {table};" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
output = stdout.read().decode('utf-8', errors='ignore')
print("\n表结构:")
print(output)
# 查看前3行数据
cmd = f'''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' --batch devops -e "SELECT * FROM {table} LIMIT 3;" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
output = stdout.read().decode('utf-8', errors='ignore')
print("\n示例数据(前3行):")
print(output)
ssh.close()
\ No newline at end of file
此差异已折叠。
import paramiko
import re
# --- MySQL: 获取所有NOT NULL带默认值的列 ---
mysql_ssh = paramiko.SSHClient()
mysql_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
mysql_ssh.connect(hostname='192.168.5.41', port=22, username='root', password='Ubains@123', timeout=10)
def mysql_exe(sql):
cmd = 'docker exec -i umysql mysql --defaults-extra-file=/tmp/mysql.cnf ubains --batch --skip-column-names'
s, o, e = mysql_ssh.exec_command(cmd, timeout=30)
s.write(sql)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore')
sql = """SELECT TABLE_NAME, COLUMN_NAME, COLUMN_DEFAULT, DATA_TYPE, COLUMN_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA='ubains'
AND IS_NULLABLE='NO'
AND COLUMN_DEFAULT IS NOT NULL
AND COLUMN_DEFAULT NOT IN ('NULL')
AND EXTRA NOT LIKE '%auto_increment%'
AND DATA_TYPE NOT IN ('tinytext', 'text', 'mediumtext', 'longtext', 'clob')
ORDER BY TABLE_NAME;
"""
o = mysql_exe(sql)
mysql_defaults = []
for line in o.strip().split('\n'):
if line.strip():
parts = line.split('\t')
if len(parts) >= 5:
mysql_defaults.append({
'table': parts[0],
'col': parts[1],
'default': parts[2],
'data_type': parts[3],
'col_type': parts[4],
})
print(f'MySQL NOT NULL defaults: {len(mysql_defaults)} columns')
mysql_ssh.close()
# --- DM: 检查对应列的默认值 ---
dm_ssh = paramiko.SSHClient()
dm_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
dm_ssh.connect(hostname='192.168.5.40', port=22, username='root', password='Ubains@123', timeout=10)
def dm_sql(sql):
cmd = "docker exec -i dm8-server sh -c \"export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql DM_UBAINS/'dNrprU&2S!'@localhost:5236\""
s, o, e = dm_ssh.exec_command(cmd, timeout=30)
s.write(sql)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore')
# 获取DM所有列的默认值
o = dm_sql("SELECT TABLE_NAME, COLUMN_NAME, DATA_DEFAULT FROM USER_TAB_COLUMNS WHERE NULLABLE='N' ORDER BY TABLE_NAME;\n")
dm_has_default = set()
for line in o.split('\n'):
m = re.search(r'^\d+\s+(\w+)\s+(\w+)\s+(.+)', line.strip())
if m and m.group(3).strip() and m.group(3).strip() != 'NULL':
dm_has_default.add((m.group(1), m.group(2)))
missing = []
for m in mysql_defaults:
dm_table = m['table'].upper()
dm_col = m['col'].upper()
key = (dm_table, dm_col)
if key not in dm_has_default and 'CURRENT_TIMESTAMP' not in m['default']:
default_val = m['default']
# 跳过自增列(已有序列处理)
missing.append({
'table': dm_table,
'col': dm_col,
'default': default_val,
'col_type': m['col_type'],
})
print(f' MISSING: {dm_table}.{dm_col} DEFAULT={default_val}')
print(f'\nTotal missing defaults: {len(missing)}')
# --- 批量修复 ---
if missing:
sql_batch = ''
for item in missing:
table = item['table']
col = item['col']
default = item['default']
# 构建达梦兼容的列定义
if default == 'CURRENT_TIMESTAMP':
continue # 不需要处理
# 转为达梦兼容类型
col_type = item['col_type']
# MySQL类型转达梦类型
if 'int' in col_type.lower():
dm_type = 'INT'
elif 'tinyint' in col_type.lower():
dm_type = 'INT'
elif 'bigint' in col_type.lower():
dm_type = 'BIGINT'
elif 'double' in col_type.lower():
dm_type = 'DOUBLE'
elif 'varchar' in col_type.lower():
size = re.search(r'\((\d+)\)', col_type)
size_str = size.group(1) if size else '255'
dm_type = f'VARCHAR({size_str})'
elif 'char' in col_type.lower():
size = re.search(r'\((\d+)\)', col_type)
size_str = size.group(1) if size else '1'
dm_type = f'VARCHAR({size_str})'
else:
dm_type = 'VARCHAR(255)'
# 默认值
if default == '' or default == "'" + "'":
default_val = "''"
elif default.startswith("'") and default.endswith("'"):
default_val = default
else:
default_val = f"'{default}'"
sql_batch += f"ALTER TABLE {table} MODIFY {col} {dm_type} DEFAULT {default_val};\n"
print(f'\nExecuting {len(sql_batch.splitlines())} ALTER statements...')
o = dm_sql(sql_batch)
success = o.count('executed successfully')
fail = o.count('Error')
print(f'Success: {success}, Fail: {fail}')
if fail > 0:
# 显示失败的行
for line in o.split('\n'):
if 'Error' in line or '[-' in line:
print(f' {line.strip()[:120]}')
dm_ssh.close()
print('\nDone!')
\ No newline at end of file
import paramiko
import re
# --- MySQL: 获取所有有自增的表 ---
mysql_ssh = paramiko.SSHClient()
mysql_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
mysql_ssh.connect(hostname='192.168.5.41', port=22, username='root', password='Ubains@123', timeout=10)
def mysql_exe(sql):
cmd = 'docker exec -i umysql mysql --defaults-extra-file=/tmp/mysql.cnf ubains --batch --skip-column-names'
s, o, e = mysql_ssh.exec_command(cmd, timeout=30)
s.write(sql)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore')
sql = """SELECT TABLE_NAME, COLUMN_NAME, IFNULL(EXTRA, '') as EXTRA
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'ubains'
AND EXTRA LIKE '%auto_increment%'
ORDER BY TABLE_NAME;
"""
o = mysql_exe(sql)
print('=== MySQL AUTO_INCREMENT 列 ===')
auto_cols = []
for line in o.strip().split('\n'):
if line.strip():
parts = line.split('\t')
if len(parts) >= 2:
table = parts[0].upper()
col = parts[1].upper()
auto_cols.append((table, col))
print(f' {table}.{col}')
mysql_ssh.close()
# --- 达梦: 批量创建序列 ---
dm_ssh = paramiko.SSHClient()
dm_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
dm_ssh.connect(hostname='192.168.5.40', port=22, username='root', password='Ubains@123', timeout=10)
def dm_sql(sql):
cmd = "docker exec -i dm8-server sh -c \"export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql DM_UBAINS/'dNrprU&2S!'@localhost:5236\""
s, o, e = dm_ssh.exec_command(cmd, timeout=60)
s.write(sql)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore')
# 获取已有序列
o = dm_sql('SELECT SEQUENCE_NAME FROM USER_SEQUENCES;\n')
existing = set()
for line in o.split('\n'):
m = re.search(r'^\d+\s+(\w+)', line.strip())
if m:
existing.add(m.group(1))
print()
print('=== 批量创建序列 ===')
created = 0
skipped = 0
failed = 0
for table, col in auto_cols:
seq_name = f'SEQ_{table}_{col}'
if seq_name in existing:
skipped += 1
continue
# 获取当前最大ID作为序列起始值
start_val = 1000 # 默认
o = dm_sql(f"SELECT NVL(MAX({col}), 0) + 1 FROM {table};\n")
for line in o.split('\n'):
m = re.search(r'^\s*\d+\s+(\d+)\s*$', line.strip())
if m:
start_val = max(int(m.group(1)), 1000)
break
sql = f"""CREATE SEQUENCE {seq_name} START WITH {start_val} INCREMENT BY 1;
ALTER TABLE {table} MODIFY {col} BIGINT DEFAULT {seq_name}.NEXTVAL;
"""
o = dm_sql(sql)
if 'executed successfully' in o:
print(f' [OK] {table}.{col} -> {seq_name} (start={start_val})')
created += 1
else:
print(f' [FAIL] {table}.{col}: {o[:150]}')
failed += 1
print(f'\nCreated: {created}, Skipped: {skipped}, Failed: {failed}')
# 验证
o = dm_sql('SELECT SEQUENCE_NAME FROM USER_SEQUENCES ORDER BY 1;\n')
seqs = []
for line in o.split('\n'):
m = re.search(r'^\d+\s+(\w+)', line.strip())
if m:
seqs.append(m.group(1))
print(f'\nTotal sequences: {len(seqs)}')
dm_ssh.close()
\ No newline at end of file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
MySQL → 达梦 DM8 桥接迁移脚本 v2
- SSH keepalive
- 小批次 INSERT
- 逐表迁移,容错
"""
import paramiko, sys, io, re, base64, time
if sys.platform == 'win32':
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
SERVER_IP = "192.168.5.46"
SERVER_USER = "root"
SERVER_PASS = "Ubains@123"
MYSQL_CONTAINER = "umysql"
MYSQL_USER = "root"
MYSQL_PASS = "dNrprU&2S"
DM8_CONTAINER = "dm8-server"
DM8_USER = "SYSDBA"
DM8_PASS = "Dameng2026Pwd"
DM8_PORT = 5236
def get_ssh_client():
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(SERVER_IP, 22, SERVER_USER, SERVER_PASS, timeout=30)
transport = client.get_transport()
transport.set_keepalive(15)
return client
def reconnect_on_failure(client_holder):
"""重连 SSH"""
try:
client_holder['client'].close()
except:
pass
client_holder['client'] = get_ssh_client()
return client_holder['client']
def safe_dm8_exec(client_holder, sql, retries=2):
"""带重连的 SQL 执行"""
for attempt in range(retries + 1):
try:
return dm8_exec_b64(client_holder['client'], sql)
except Exception as e:
if attempt < retries:
print(f'\n [重连 {attempt+1}...]', end='', flush=True)
reconnect_on_failure(client_holder)
else:
raise
def mysql_query(client, db, query):
cmd = f"docker exec {MYSQL_CONTAINER} mysql -u{MYSQL_USER} -p'{MYSQL_PASS}' -D {db} --batch --skip-column-names -e \"{query}\""
stdin, stdout, stderr = client.exec_command(cmd, timeout=120)
return stdout.read().decode('utf-8', errors='replace')
def dm8_exec_b64(client, sql):
"""使用 base64 编码执行 SQL"""
encoded = base64.b64encode(sql.encode('utf-8')).decode('ascii')
cmd = f"docker exec {DM8_CONTAINER} bash -c 'echo {encoded} | base64 -d | /opt/dmdbms/bin/disql {DM8_USER}/{DM8_PASS}@localhost:{DM8_PORT} 2>&1 | grep -v \"login used\\|disql V8\\|SQL>\\|Server\\[\"'"
stdin, stdout, stderr = client.exec_command(cmd, timeout=120)
return stdout.read().decode('utf-8', errors='replace')
def convert_create(sql, schema):
"""转换 CREATE TABLE"""
sql = sql.replace('`', '"')
sql = re.sub(r'\s+ENGINE\s*=\s*\w+', '', sql, flags=re.IGNORECASE)
sql = re.sub(r'\s+DEFAULT\s+CHARSET\s*=\s*\w+', '', sql, flags=re.IGNORECASE)
sql = re.sub(r'\s+CHARSET\s*=\s*\w+', '', sql, flags=re.IGNORECASE)
sql = re.sub(r'\s+COLLATE\s*=?\s*\w+', '', sql, flags=re.IGNORECASE)
sql = re.sub(r'\s+ROW_FORMAT\s*=\s*\w+', '', sql, flags=re.IGNORECASE)
sql = re.sub(r'\s+USING\s+BTREE', '', sql, flags=re.IGNORECASE)
sql = re.sub(r'\s+USING\s+HASH', '', sql, flags=re.IGNORECASE)
sql = re.sub(r'\s+AUTO_INCREMENT\s*=\s*\d+', '', sql, flags=re.IGNORECASE)
sql = re.sub(r"\s+COMMENT\s+'[^']*'", '', sql, flags=re.IGNORECASE)
sql = re.sub(r"\s*COMMENT\s*=\s*'[^']*'", '', sql, flags=re.IGNORECASE)
sql = re.sub(r'\s+CHARACTER\s+SET\s+\w+', '', sql, flags=re.IGNORECASE)
# 类型转换
for p1, p2 in [('int\(\d+\)', 'INTEGER'), ('tinyint\(\d+\)', 'TINYINT'),
('smallint\(\d+\)', 'SMALLINT'), ('bigint\(\d+\)', 'BIGINT'),
('datetime\(\d+\)', 'DATETIME'), ('timestamp\(\d+\)', 'TIMESTAMP'),
('longtext', 'CLOB'), ('longblob', 'BLOB')]:
sql = re.sub(p1, p2, sql, flags=re.IGNORECASE)
# 删除外键
sql = re.sub(r',?\s*CONSTRAINT\s+"[^"]*"\s+FOREIGN\s+KEY\s*\([^)]*\)\s*REFERENCES\s+"[^"]*"\s*\([^)]*\)\s*(ON\s+DELETE\s+\w+)?(\s*ON\s+UPDATE\s+\w+)?', '', sql, flags=re.IGNORECASE)
# Schema 前缀
m = re.search(r'CREATE\s+TABLE\s+"(\w+)"', sql, re.IGNORECASE)
if m:
t = m.group(1)
sql = sql.replace(f'CREATE TABLE "{t}"', f'CREATE TABLE {schema}."{t}"')
return sql
def escape_val(v):
if v == 'NULL' or v is None: return 'NULL'
return "'" + v.replace("'", "''").replace('\\', '\\\\') + "'"
def main():
client_holder = {'client': get_ssh_client()}
print("✅ SSH 连接成功")
# Schema 创建
dbs = ['offline', 'huazhao2', 'nacos_mysql', 'ubains', 'devops_voice', 'devops']
for db in dbs:
safe_dm8_exec(client_holder, f"CREATE SCHEMA IF NOT EXISTS {db};")
for db in dbs:
print(f"\n{'='*50}")
print(f"📄 {db}")
print(f"{'='*50}")
# 获取表列表
tables_raw = mysql_query(client_holder['client'], db, "SHOW TABLES;")
tables = [t.strip() for t in tables_raw.split('\n') if t.strip()]
print(f" 表: {len(tables)}")
ok = err = 0
for i, table in enumerate(tables):
print(f" [{i+1}/{len(tables)}] {table}", end=' ', flush=True)
# 获取 CREATE
out = mysql_query(client_holder['client'], db, f"SHOW CREATE TABLE {table};")
create_sql = None
for line in out.split('\n'):
if '\t' in line and 'CREATE TABLE' in line:
create_sql = line.split('\t', 1)[1].replace('\\n', '\n')
break
if not create_sql:
print('❌(no DDL)')
err += 1
continue
dm8_ddl = convert_create(create_sql, db)
safe_dm8_exec(client_holder, f'DROP TABLE IF EXISTS {db}."{table}";')
result = safe_dm8_exec(client_holder, dm8_ddl)
if 'error' in result.lower() or 'Error' in result:
print(f'❌(DDL)')
err += 1
continue
# 获取数据
data = mysql_query(client_holder['client'], db, f"SELECT * FROM {table};")
if not data.strip():
print('✅(空)')
ok += 1
continue
rows = data.strip().split('\n')
# 限制每批100行,大表更小批次
batch_size = 100 if len(rows) > 1000 else 500
total_inserted = 0
failed_rows = 0
insert_ok = True
for batch_start in range(0, len(rows), batch_size):
batch = rows[batch_start:batch_start + batch_size]
vals = []
for row in batch:
cols = row.split('\t')
vals.append('(' + ','.join(escape_val(c) for c in cols) + ')')
ins = f"INSERT INTO {db}.\"{table}\" VALUES {','.join(vals)};"
try:
r = safe_dm8_exec(client_holder, ins)
if 'error' in r.lower() or 'Error' in r:
# 批次失败,逐行重试
for row in batch:
cols = row.split('\t')
single_ins = f"INSERT INTO {db}.\"{table}\" VALUES ({','.join(escape_val(c) for c in cols)});"
try:
sr = safe_dm8_exec(client_holder, single_ins)
if 'error' in sr.lower() or 'Error' in sr:
failed_rows += 1
else:
total_inserted += 1
except:
failed_rows += 1
else:
total_inserted += len(batch)
except Exception as e:
print(f'\n [跳过批次]', end='', flush=True)
failed_rows += len(batch)
if failed_rows == 0:
print(f'✅({total_inserted})')
ok += 1
elif total_inserted > 0:
print(f'⚠️({total_inserted}/{len(rows)}, 丢{failed_rows})')
ok += 1
else:
print(f'❌(DDL ok, data 0/{len(rows)})')
err += 1
print(f" 📊 {ok}✅/{err}❌")
# 验证
print(f"\n{'='*50}")
print("📊 验证")
print(f"{'='*50}")
for db in dbs:
r = safe_dm8_exec(client_holder, f"SELECT COUNT(*) FROM ALL_TABLES WHERE OWNER='{db.upper()}';")
cnt = '0'
for l in r.split('\n'):
if l.strip().isdigit(): cnt = l.strip()
print(f" {db}: {cnt}")
client_holder['client'].close()
print("\n✅ 完成")
if __name__ == "__main__":
main()
#!/bin/bash
# DM8 容器构建脚本
# 用于在 192.168.9.75 服务器上构建 DM8 Docker 镜像
set -e
# 配置参数
SERVER_IP="192.168.9.75"
SERVER_USER="root"
SERVER_PASS="Ubains@123"
IMAGE_NAME="dm8-arm64"
IMAGE_TAG="v1.0"
DM_INSTALL_SRC="/usr/local/dm8"
BUILD_DIR="/tmp/dm8-docker-build"
echo "=== DM8 Docker 镜像构建脚本 ==="
echo "服务器: ${SERVER_IP}"
echo "镜像名称: ${IMAGE_NAME}:${IMAGE_TAG}"
# 检查 SSH 连接
echo "=== 检查 SSH 连接 ==="
if ! ssh root@${SERVER_IP} "echo connected" 2>/dev/null; then
echo "ERROR: 无法连接到服务器,请检查 SSH 配置"
exit 1
fi
echo "SSH 连接正常"
# 在服务器上创建构建目录
echo "=== 创建构建目录 ==="
ssh root@${SERVER_IP} "mkdir -p ${BUILD_DIR}/dm8_install"
# 复制 DM8 安装文件到构建目录
echo "=== 复制 DM8 安装文件 ==="
echo "源路径: ${DM_INSTALL_SRC}"
echo "目标路径: ${BUILD_DIR}/dm8_install"
ssh root@${SERVER_IP} "cp -r ${DM_INSTALL_SRC}/* ${BUILD_DIR}/dm8_install/"
# 复制 Docker 构建文件到服务器
echo "=== 上传构建文件到服务器 ==="
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
scp ${SCRIPT_DIR}/Dockerfile root@${SERVER_IP}:${BUILD_DIR}/
scp ${SCRIPT_DIR}/entrypoint.sh root@${SERVER_IP}:${BUILD_DIR}/
scp ${SCRIPT_DIR}/init_instance.sh root@${SERVER_IP}:${BUILD_DIR}/
scp ${SCRIPT_DIR}/dm.ini.template root@${SERVER_IP}:${BUILD_DIR}/
# 设置脚本权限
ssh root@${SERVER_IP} "chmod +x ${BUILD_DIR}/entrypoint.sh ${BUILD_DIR}/init_instance.sh"
# 执行 Docker 构建
echo "=== 构建 Docker 镜像 ==="
ssh root@${SERVER_IP} "cd ${BUILD_DIR} && \
docker build \
--build-arg DM_INSTALL_PATH=./dm8_install \
-t ${IMAGE_NAME}:${IMAGE_TAG} \
-f Dockerfile \
."
# 清理构建临时文件(可选)
echo "=== 清理构建临时文件 ==="
ssh root@${SERVER_IP} "rm -rf ${BUILD_DIR}/dm8_install"
echo "=== 构建完成 ==="
echo "镜像: ${IMAGE_NAME}:${IMAGE_TAG}"
echo ""
# 显示镜像信息
echo "=== 镜像信息 ==="
ssh root@${SERVER_IP} "docker images ${IMAGE_NAME}"
echo ""
echo "=== 下一步操作 ==="
echo "1. 运行容器(首次运行会自动初始化实例):"
echo " docker run -d \
--name dm8-server \
-p 5236:5236 \
-v /data/dm8:/opt/dm8/data \
-e DM_SYSDBA_PWD=SYSDBA001 \
${IMAGE_NAME}:${IMAGE_TAG}"
echo ""
echo "2. 查看容器日志:"
echo " docker logs -f dm8-server"
echo ""
echo "3. 连接数据库:"
echo " docker exec -it dm8-server /opt/dm8/bin/disql SYSDBA/SYSDBA001@localhost:5236"
exit 0
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
对比 MySQL 和达梦数据库的所有表字段差异
重点检查字段名大小写问题
"""
import pymysql
import dmPython
# MySQL 配置
MYSQL_CONFIG = {
'host': '192.168.5.41',
'port': 8306,
'user': 'root',
'password': 'dNrprU&2S',
'charset': 'utf8mb4',
'database': 'ubains'
}
# 达梦配置
DM_CONFIG = {
'user': 'DM_UBAINS',
'password': 'Ubains@2026Pwd',
'server': '192.168.5.40',
'port': 5236
}
def get_mysql_columns(cursor, table_name):
"""获取 MySQL 表的所有字段信息(保持原样大小写)"""
cursor.execute(f"""
SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH,
NUMERIC_PRECISION, NUMERIC_SCALE, IS_NULLABLE, COLUMN_DEFAULT,
COLUMN_COMMENT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'ubains' AND TABLE_NAME = %s
ORDER BY ORDINAL_POSITION
""", (table_name,))
columns = {}
for row in cursor.fetchall():
col_name = row[0] # 保持原样
columns[col_name] = {
'name': row[0],
'name_upper': row[0].upper(),
'data_type': row[1],
'char_length': row[2],
'num_precision': row[3],
'num_scale': row[4],
'nullable': row[5],
'default': row[6],
'comment': row[7]
}
return columns
def get_dm_columns(cursor, table_name):
"""获取达梦表的所有字段信息(保持原样大小写)"""
cursor.execute(f"""
SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH,
DATA_PRECISION, DATA_SCALE, NULLABLE, DATA_DEFAULT
FROM DBA_TAB_COLUMNS
WHERE OWNER = 'DM_UBAINS' AND TABLE_NAME = '{table_name.upper()}'
ORDER BY COLUMN_ID
""")
columns = {}
for row in cursor.fetchall():
col_name = row[0] # 保持原样
columns[col_name] = {
'name': row[0],
'name_upper': row[0].upper(),
'data_type': row[1],
'data_length': row[2],
'data_precision': row[3],
'data_scale': row[4],
'nullable': row[5],
'default': row[6]
}
return columns
def get_mysql_tables(cursor):
"""获取 MySQL 所有表名"""
cursor.execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ubains' AND TABLE_TYPE = 'BASE TABLE'")
return [row[0] for row in cursor.fetchall()]
def get_dm_tables(cursor):
"""获取达梦所有表名"""
cursor.execute("SELECT TABLE_NAME FROM DBA_TABLES WHERE OWNER = 'DM_UBAINS'")
return [row[0] for row in cursor.fetchall()]
def main():
print("=" * 80)
print("对比 MySQL 和达梦数据库表字段差异(检查大小写问题)")
print("=" * 80)
# 连接 MySQL
mysql_conn = pymysql.connect(**MYSQL_CONFIG)
mysql_cursor = mysql_conn.cursor()
# 连接达梦
dm_conn = dmPython.connect(**DM_CONFIG)
dm_cursor = dm_conn.cursor()
try:
# 获取表列表
mysql_tables = get_mysql_tables(mysql_cursor)
dm_tables = get_dm_tables(dm_cursor)
print(f"\nMySQL 表数量: {len(mysql_tables)}")
print(f"达梦表数量: {len(dm_tables)}")
# 对比关键表的字段大小写
print("\n" + "=" * 80)
print("检查错误日志中提到的具体表(RMS_MANAGE_USER_AREA 和 SYS_CONFIGURATION)")
print("=" * 80)
# RMS_MANAGE_USER_AREA 表
print("\n表 RMS_MANAGE_USER_AREA:")
mysql_table_name_lower = 'rms_manage_user_area'
mysql_cols = get_mysql_columns(mysql_cursor, mysql_table_name_lower)
dm_cols = get_dm_columns(dm_cursor, 'RMS_MANAGE_USER_AREA')
print(f" MySQL 字段(原样): {list(mysql_cols.keys())}")
print(f" 达梦字段(原样): {list(dm_cols.keys())}")
print(f" 达梦字段(大写): {list(dm_cols.keys())}")
# 检查 USER_ID 字段
print("\n 检查 USER_ID 字段:")
mysql_user_id = 'user_id' in mysql_cols
dm_user_id_upper = 'USER_ID' in dm_cols
dm_user_id_lower = 'user_id' in dm_cols
print(f" MySQL 有 user_id: {mysql_user_id}")
print(f" 达梦有 USER_ID (大写): {dm_user_id_upper}")
print(f" 达梦有 user_id (小写): {dm_user_id_lower}")
# SYS_CONFIGURATION 表
print("\n表 SYS_CONFIGURATION:")
mysql_table_name_lower = 'sys_configuration'
mysql_cols = get_mysql_columns(mysql_cursor, mysql_table_name_lower)
dm_cols = get_dm_columns(dm_cursor, 'SYS_CONFIGURATION')
print(f" MySQL 字段(原样): {list(mysql_cols.keys())}")
print(f" 达梦字段(原样): {list(dm_cols.keys())}")
# 检查 TYPE_ID 字段
print("\n 检查 TYPE_ID 字段:")
mysql_type_id = 'type_id' in mysql_cols
dm_type_id_upper = 'TYPE_ID' in dm_cols
dm_type_id_lower = 'type_id' in dm_cols
print(f" MySQL 有 type_id: {mysql_type_id}")
print(f" 达梦有 TYPE_ID (大写): {dm_type_id_upper}")
print(f" 达梦有 type_id (小写): {dm_type_id_lower}")
# 统计所有小写字段名的表
print("\n" + "=" * 80)
print("统计达梦中所有小写字段名的表")
print("=" * 80)
lowercase_column_tables = {}
for dm_table in dm_tables:
dm_cols = get_dm_columns(dm_cursor, dm_table)
lowercase_cols = [col for col in dm_cols.keys() if col != col.upper()]
if lowercase_cols:
lowercase_column_tables[dm_table] = lowercase_cols
if lowercase_column_tables:
print(f"\n发现 {len(lowercase_column_tables)} 张表有小写字段名:")
total_lower_cols = 0
for table_name, lower_cols in sorted(lowercase_column_tables.items()):
total_lower_cols += len(lower_cols)
print(f" {table_name}: {len(lower_cols)} 个小写字段")
if len(lower_cols) <= 10: # 只显示少于10个的详细列表
print(f" 字段: {lower_cols}")
print(f"\n总计: {total_lower_cols} 个小写字段名需要转换为大写")
else:
print("\n所有字段名都已是大写!")
finally:
mysql_cursor.close()
mysql_conn.close()
dm_cursor.close()
dm_conn.close()
if __name__ == '__main__':
main()
\ No newline at end of file
# -*- coding: utf-8 -*-
"""查询达梦 DM_DEVOPS 库中各表的数据行数"""
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.5.40', port=22, username='root', password='Ubains@123', timeout=10)
# 获取所有表名
cmd = '''docker exec -i dm8-server bash <<'EOF'
export LD_LIBRARY_PATH=/opt/dmdbms/bin
/opt/dmdbms/bin/disql SYSDBA/Dameng2026Pwd@localhost:5236 <<'EOSQL'
SELECT TABLE_NAME FROM DBA_TABLES WHERE OWNER='DM_DEVOPS' ORDER BY TABLE_NAME;
EOSQL
EOF
'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
output = stdout.read().decode('utf-8', errors='ignore')
# 解析表名
tables = []
for line in output.split('\n'):
line = line.strip()
if not line:
continue
if 'TABLE_NAME' in line or 'LINEID' in line or '-----' in line:
continue
if 'SERVER' in line or 'login' in line or 'disql' in line:
continue
if 'rows got' in line or 'used time' in line:
continue
if line.startswith('SQL>') or line.startswith(']0;'):
continue
# 提取表名(格式:行号 表名)
parts = line.split()
if len(parts) >= 2:
table_name = parts[-1]
tables.append(table_name)
print("=" * 80)
print("达梦 DM_DEVOPS 库各表数据行数")
print("=" * 80)
print()
# 查询每个表的行数
total_rows = 0
empty_tables = []
non_empty_tables = []
for table in tables:
# 查询行数
cmd = f'''docker exec -i dm8-server bash <<'EOF'
export LD_LIBRARY_PATH=/opt/dmdbms/bin
/opt/dmdbms/bin/disql SYSDBA/Dameng2026Pwd@localhost:5236 <<'EOSQL'
SELECT COUNT(*) FROM DM_DEVOPS."{table}";
EOSQL
EOF
'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=30)
output = stdout.read().decode('utf-8', errors='ignore')
# 解析行数
count = 0
for line in output.split('\n'):
line = line.strip()
if line and line[0].isdigit() and ' ' not in line:
try:
count = int(line.split()[0])
break
except:
pass
total_rows += count
if count == 0:
empty_tables.append(table)
else:
non_empty_tables.append((table, count))
print(f"{table:40s} {count:>10d} 行")
print()
print("=" * 80)
print("汇总统计")
print("=" * 80)
print(f"总表数: {len(tables)}")
print(f"有数据的表: {len(non_empty_tables)}")
print(f"空表: {len(empty_tables)}")
print(f"总数据行数: {total_rows}")
if empty_tables:
print()
print("空表列表:")
for t in empty_tables[:20]:
print(f" - {t}")
if len(empty_tables) > 20:
print(f" ... 还有 {len(empty_tables) - 20} 张空表")
ssh.close()
\ No newline at end of file
此差异已折叠。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
查看 DM8 容器日志和状态
"""
import paramiko
import sys
import os
# 设置输出编码为 UTF-8
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
# 服务器配置
SERVER_IP = "192.168.5.46"
SERVER_PORT = 22
SERVER_USER = "root"
SERVER_PASS = "Ubains@123"
# DM8 容器配置
DM8_CONTAINER = "dm8-server"
def get_ssh_client():
"""创建 SSH 连接"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(SERVER_IP, SERVER_PORT, SERVER_USER, SERVER_PASS, timeout=30)
return client
def exec_cmd(client, cmd, timeout=60):
"""执行远程命令"""
stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout)
out = stdout.read().decode('utf-8', errors='replace')
err = stderr.read().decode('utf-8', errors='replace')
exit_code = stdout.channel.recv_exit_status()
return out, err, exit_code
def main():
client = get_ssh_client()
print("="*70)
print("📋 DM8 容器日志(最后100行)")
print("="*70)
out, err, code = exec_cmd(client, f"docker logs --tail 100 {DM8_CONTAINER}")
print(out)
print("\n" + "="*70)
print("📋 DM8 容器内进程")
print("="*70)
out, err, code = exec_cmd(client, f"docker exec {DM8_CONTAINER} ps aux")
print(out)
print("\n" + "="*70)
print("📋 DM8 数据目录")
print("="*70)
out, err, code = exec_cmd(client, f"docker exec {DM8_CONTAINER} ls -la /opt/dmdbms/data/")
print(out)
print("\n" + "="*70)
print("📋 检查 dmserver 进程")
print("="*70)
out, err, code = exec_cmd(client, f"docker exec {DM8_CONTAINER} pgrep -a dmserver")
print(out if out else "未找到 dmserver 进程")
client.close()
if __name__ == "__main__":
main()
\ No newline at end of file
#!/usr/bin/env python3
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='192.168.5.40', port=22, username='root', password='Ubains@123', timeout=10)
cmd = 'docker exec -i dm8-server bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql SYSDBA/Dameng2026Pwd@localhost:5236"'
# 查询 tb_meeting_role 表的字段
sql = """
SELECT COLUMN_NAME, DATA_TYPE, DATA_DEFAULT
FROM DBA_TAB_COLUMNS
WHERE OWNER = 'DM_HUAZHAO2' AND TABLE_NAME = 'tb_meeting_role'
ORDER BY COLUMN_ID;
"""
s, o, e = ssh.exec_command(cmd, timeout=60)
s.write(sql)
s.close()
o.channel.recv_exit_status()
print('=== DM_HUAZHAO2.tb_meeting_role 表结构 ===')
print(o.read().decode('utf-8', errors='ignore'))
ssh.close()
\ No newline at end of file
此差异已折叠。
# -*- coding: utf-8 -*-
"""
查询 MySQL 中数据量最大的表
"""
import paramiko
import sys
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.5.41', port=22, username='root', password='Ubains@123', timeout=10)
cmd = '''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' --batch --skip-column-names devops -e "SELECT TABLE_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='devops' AND TABLE_ROWS > 10000 ORDER BY TABLE_ROWS DESC;" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
output = stdout.read().decode('utf-8', errors='ignore')
print("MySQL devops 库中数据量超过10000行的表:")
print("=" * 60)
for line in output.strip().split('\n'):
if line:
parts = line.split('\t')
if len(parts) >= 2:
table = parts[0]
rows = parts[1]
print(f"{table:40s} {rows:>10s} 行")
ssh.close()
# -*- coding: utf-8 -*-
"""
检查 MySQL 中实际存在的表和数据
"""
import paramiko
import sys
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.5.41', port=22, username='root', password='Ubains@123', timeout=10)
# 1. 列出所有表
print("=" * 80)
print("MySQL devops 库所有表列表")
print("=" * 80)
cmd = '''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' --batch --skip-column-names devops -e "SHOW TABLES;" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
output = stdout.read().decode('utf-8', errors='ignore')
tables = [line.strip() for line in output.strip().split('\n') if line.strip()]
print(f"总表数: {len(tables)}")
# 查找相关表
keywords = ['servermonitor', 'datemonitor', 'recordtime', 'permission', 'roommeeting']
print("\n包含关键字的表:")
for table in tables:
for keyword in keywords:
if keyword in table.lower():
print(f" - {table}")
break
# 2. 检查数据行数
print("\n" + "=" * 80)
print("数据量超过100行的表")
print("=" * 80)
cmd = '''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' --batch --skip-column-names devops -e "SELECT TABLE_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='devops' AND TABLE_ROWS > 100 ORDER BY TABLE_ROWS DESC;" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
output = stdout.read().decode('utf-8', errors='ignore')
for line in output.strip().split('\n'):
if line:
parts = line.split('\t')
if len(parts) >= 2:
print(f" {parts[0]:40s} {parts[1]:>10s} 行")
# 3. 检查关键表是否存在数据
print("\n" + "=" * 80)
print("关键表数据检查")
print("=" * 80)
key_tables = [
'AUTH_PERMISSION',
'UVOICE_ROOMMEETING',
'DJANGO_MIGRATIONS',
'DJANGO_CONTENT_TYPE',
'CMDB_SERVERMONITOR_DATE',
'CMDB_DATEMONITOR',
]
for table in key_tables:
cmd = f'''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' --batch --skip-column-names devops -e "SELECT COUNT(*) FROM {table};" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=30)
output = stdout.read().decode('utf-8', errors='ignore')
count = output.strip().split('\n')[0] if output.strip() else 'ERROR'
print(f" {table:40s} {count:>10s} 行")
ssh.close()
\ No newline at end of file
# -*- coding: utf-8 -*-
"""查询 MySQL devops 库中各表的数据行数,识别需要迁移的表"""
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.5.41', port=22, username='root', password='Ubains@123', timeout=10)
# 获取所有表名
cmd = '''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' devops -e "SHOW TABLES;" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
output = stdout.read().decode('utf-8', errors='ignore')
# 解析表名
tables = []
for line in output.strip().split('\n')[1:]: # 跳过表头
if line.strip():
tables.append(line.strip())
print("=" * 80)
print("MySQL devops 库各表数据行数")
print("=" * 80)
print()
# 查询每个表的行数
total_rows = 0
empty_tables = []
non_empty_tables = []
for table in tables:
# 查询行数
cmd = f'''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' devops -e "SELECT COUNT(*) FROM \`{table}\`;" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=30)
output = stdout.read().decode('utf-8', errors='ignore')
# 解析行数
count = 0
for line in output.strip().split('\n'):
if line.strip() and line.strip().isdigit():
count = int(line.strip())
break
total_rows += count
if count == 0:
empty_tables.append(table)
else:
non_empty_tables.append((table, count))
print(f"{table:40s} {count:>10d} 行")
print()
print("=" * 80)
print("汇总统计")
print("=" * 80)
print(f"总表数: {len(tables)}")
print(f"有数据的表: {len(non_empty_tables)}")
print(f"空表: {len(empty_tables)}")
print(f"总数据行数: {total_rows}")
print()
print("=" * 80)
print("需要迁移的表(有数据的表)")
print("=" * 80)
for table, count in non_empty_tables:
print(f" {table:40s} {count:>10d} 行")
# 保存到文件
with open('Docs/mysql_devops_data_stats.txt', 'w', encoding='utf-8') as f:
f.write("MySQL devops 库数据统计\n")
f.write("=" * 80 + "\n\n")
f.write(f"总表数: {len(tables)}\n")
f.write(f"有数据的表: {len(non_empty_tables)}\n")
f.write(f"空表: {len(empty_tables)}\n")
f.write(f"总数据行数: {total_rows}\n\n")
f.write("需要迁移的表:\n")
for table, count in non_empty_tables:
f.write(f" {table}: {count} 行\n")
print()
print("[INFO] 统计结果已保存到: Docs/mysql_devops_data_stats.txt")
ssh.close()
\ No newline at end of file
#!/usr/bin/env python3
import paramiko
ssh40 = paramiko.SSHClient()
ssh40.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh40.connect('192.168.5.40', port=22, username='root', password='Ubains@123', timeout=10)
cmd = 'docker exec -i dm8-server bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql SYSDBA/Dameng2026Pwd@localhost:5236"'
stdin, stdout, stderr = ssh40.exec_command(cmd, timeout=30)
# 查看主键列
sql = """SELECT COLS.COLUMN_NAME
FROM DBA_CONS_COLUMNS COLS
JOIN DBA_CONSTRAINTS CONS ON COLS.CONSTRAINT_NAME = CONS.CONSTRAINT_NAME AND COLS.OWNER = CONS.OWNER
WHERE CONS.OWNER='DM_NACOS' AND CONS.TABLE_NAME='CONFIG_INFO' AND CONS.CONSTRAINT_TYPE='P'
ORDER BY COLS.POSITION;
"""
stdin.write(sql.encode('utf-8'))
stdin.close()
out = stdout.read().decode('utf-8', errors='replace')
print('CONFIG_INFO PK columns:')
print(out)
ssh40.close()
\ No newline at end of file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
检查服务器环境脚本
检查 MySQL 和 DM8 容器状态
"""
import paramiko
import sys
import os
# 设置输出编码为 UTF-8
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
# 服务器配置
SERVER_IP = "192.168.5.46"
SERVER_PORT = 22
SERVER_USER = "root"
SERVER_PASS = "Ubains@123"
# MySQL 容器配置
MYSQL_CONTAINER = "umysql"
MYSQL_USER = "root"
MYSQL_PASS = "dNrprU&2S"
# DM8 容器配置
DM8_CONTAINER = "dm8-server"
DM8_USER = "SYSDBA"
DM8_PASS = "Dameng2026Pwd"
DM8_PORT = 5236
def get_ssh_client():
"""创建 SSH 连接"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
client.connect(SERVER_IP, SERVER_PORT, SERVER_USER, SERVER_PASS, timeout=30)
return client
except Exception as e:
print(f"❌ SSH 连接失败: {e}")
sys.exit(1)
def exec_cmd(client, cmd, timeout=60):
"""执行远程命令并返回输出"""
stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout)
out = stdout.read().decode('utf-8', errors='replace')
err = stderr.read().decode('utf-8', errors='replace')
exit_code = stdout.channel.recv_exit_status()
return out, err, exit_code
def check_containers(client):
"""检查容器状态"""
print("\n" + "="*70)
print("📦 检查容器状态")
print("="*70)
# 检查所有容器
out, err, code = exec_cmd(client, "docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'")
if code != 0:
print(f"❌ 获取容器列表失败: {err}")
return False
print(out)
# 检查 MySQL 容器
print("\n🔍 MySQL 容器详情:")
out, err, code = exec_cmd(client, f"docker ps | grep {MYSQL_CONTAINER}")
print(out if out else f"容器 '{MYSQL_CONTAINER}' 不在运行列表中")
mysql_running = MYSQL_CONTAINER in out
# 检查 DM8 容器
print("\n🔍 DM8 容器详情:")
out, err, code = exec_cmd(client, f"docker ps | grep {DM8_CONTAINER}")
print(out if out else f"容器 '{DM8_CONTAINER}' 不在运行列表中")
dm8_running = DM8_CONTAINER in out
return mysql_running, dm8_running
def check_mysql_databases(client):
"""检查 MySQL 容器内的数据库"""
print("\n" + "="*70)
print("📊 检查 MySQL 数据库")
print("="*70)
# 列出 MySQL 数据库
print(f"\n📋 MySQL 数据库列表:")
cmd = f"docker exec {MYSQL_CONTAINER} mysql -u{MYSQL_USER} -p'{MYSQL_PASS}' -e 'SHOW DATABASES;'"
out, err, code = exec_cmd(client, cmd)
if code != 0:
# 可能密码错误,尝试其他密码
print(f"⚠️ 使用密码 '{MYSQL_PASS}' 连接失败,尝试其他密码...")
for pwd in ["dNrprU&2S", "Ubains@123", "root", "123456"]:
cmd = f"docker exec {MYSQL_CONTAINER} mysql -u{MYSQL_USER} -p'{pwd}' -e 'SHOW DATABASES;'"
out, err, code = exec_cmd(client, cmd)
if code == 0:
print(f"✅ 找到正确密码: {pwd}")
print(out)
break
if code == 0:
print(out)
# 解析数据库列表
databases = [line.strip() for line in out.split('\n') if line.strip() and line.strip() != 'Database']
print(f"\n数据库数量: {len(databases)}")
return databases
else:
print(f"❌ 无法连接 MySQL: {err}")
return False
def check_dm8_instance(client):
"""检查 DM8 容器实例状态"""
print("\n" + "="*70)
print("📊 检查 DM8 实例")
print("="*70)
# 检查 DM8 实例是否初始化
print(f"\n📋 DM8 实例状态:")
cmd = f"docker exec {DM8_CONTAINER} /opt/dmdbms/bin/disql {DM8_USER}/{DM8_PASS}@localhost:{DM8_PORT} -e 'SELECT ID CODE, NAME\\$ FROM v\\$INSTANCE;'"
out, err, code = exec_cmd(client, cmd, timeout=10)
if code != 0:
print(f"⚠️ 连接 DM8 失败,可能实例未初始化")
print(f"错误: {err}")
# 检查容器日志
print(f"\n📋 DM8 容器日志(最后50行):")
out, err, code = exec_cmd(client, f"docker logs --tail 50 {DM8_CONTAINER}")
print(out)
return False
else:
print("✅ DM8 实例已初始化")
print(out)
return True
def main():
"""主函数"""
print("="*70)
print("🚀 检查服务器环境")
print(f"服务器: {SERVER_IP}")
print("="*70)
# 创建 SSH 连接
print("\n🔌 连接服务器...")
client = get_ssh_client()
print("✅ SSH 连接成功")
# 检查容器状态
mysql_running, dm8_running = check_containers(client)
# 检查 MySQL 数据库
mysql_databases = None
if mysql_running:
mysql_databases = check_mysql_databases(client)
# 检查 DM8 实例
dm8_ready = False
if dm8_running:
dm8_ready = check_dm8_instance(client)
# 总结
print("\n" + "="*70)
print("📝 检查结果总结")
print("="*70)
print(f"MySQL 容器: {'✅ 运行中' if mysql_running else '❌ 未运行'}")
if mysql_databases:
print(f"MySQL 数据库: ✅ 已找到 {len(mysql_databases)} 个数据库")
for db in mysql_databases:
if db not in ['Database', 'information_schema', 'mysql', 'performance_schema', 'sys']:
print(f" - {db}")
print(f"DM8 容器: {'✅ 运行中' if dm8_running else '❌ 未运行'}")
print(f"DM8 实例: {'✅ 已初始化' if dm8_ready else '⚠️ 未初始化或不可连接'}")
client.close()
print("\n✅ 检查完成")
if __name__ == "__main__":
main()
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
查看关键表的用途和字段结构
"""
import paramiko
import sys
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.5.41', port=22, username='root', password='Ubains@123', timeout=10)
tables_to_check = [
('CMDB_SERVERMONITOR_DATE', '服务器监控日期'),
('CMDB_DATEMONITOR', '日期监控'),
('CMDB_SERVERMONITOR', '服务器监控'),
('UVOICE_RECORDTIME', '录音时间记录'),
('AUTH_PERMISSION', '权限表'),
('UVOICE_ROOMMEETING', '会议室会议'),
]
for table, desc in tables_to_check:
print("\n" + "=" * 80)
print(f"表名: {table} ({desc})")
print("=" * 80)
# 查看表结构
cmd = f'''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' --batch devops -e "DESCRIBE {table};" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
output = stdout.read().decode('utf-8', errors='ignore')
if output.strip():
print("\n表结构:")
print(output)
# 查看前3行数据
cmd = f'''docker exec umysql mysql -h 192.168.5.41 -P 8306 -uroot -p'dNrprU&2S' --batch devops -e "SELECT * FROM {table} LIMIT 3;" 2>/dev/null'''
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=60)
output = stdout.read().decode('utf-8', errors='ignore')
print("\n示例数据(前3行):")
print(output)
else:
print("表不存在或无数据")
ssh.close()
\ No newline at end of file
#!/usr/bin/env python3
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='192.168.5.40', port=22, username='root', password='Ubains@123', timeout=10)
def exe_sql(sql):
cmd = 'docker exec -i dm8-server bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql SYSDBA/Dameng2026Pwd@localhost:5236"'
s, o, e = ssh.exec_command(cmd, timeout=60)
s.write(sql)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore')
# 检查 token 列是否有默认值
output = exe_sql("SELECT COLUMN_NAME, DATA_DEFAULT FROM DBA_TAB_COLUMNS WHERE OWNER='DM_DEVOPS_VOICE' AND TABLE_NAME='uvoice_roomuser' AND COLUMN_NAME='token';\n")
print('验证结果:')
print(output)
ssh.close()
\ No newline at end of file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
查看 USER 表的结构
"""
import paramiko
SSH_HOST = '192.168.5.40'
SSH_USER = 'root'
SSH_PWD = 'Ubains@123'
CONTAINER = 'dm8-server'
DM_PORT = 5236
DM_SYSDBA_PWD = 'Dameng2026Pwd'
DM_DB_USER = 'DM_UBAINS'
def main():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=SSH_HOST, port=22, username=SSH_USER, password=SSH_PWD, timeout=10)
sql = f"""
SELECT COLUMN_NAME, DATA_TYPE, DATA_DEFAULT
FROM DBA_TAB_COLUMNS
WHERE OWNER = '{DM_DB_USER}' AND TABLE_NAME = 'USER'
ORDER BY COLUMN_ID;
"""
cmd = f'docker exec -i {CONTAINER} bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql SYSDBA/{DM_SYSDBA_PWD}@localhost:{DM_PORT}"'
s, o, e = ssh.exec_command(cmd, timeout=30)
s.write(sql)
s.close()
o.channel.recv_exit_status()
output = o.read().decode('utf-8', errors='ignore')
print(f"USER 表结构:\n{output}")
ssh.close()
if __name__ == '__main__':
main()
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
对比 MySQL 和达梦数据库的所有表字段差异
找出达梦中缺失的字段
"""
import pymysql
import dmPython
# MySQL 配置
MYSQL_CONFIG = {
'host': '192.168.5.41',
'port': 8306,
'user': 'root',
'password': 'dNrprU&2S',
'charset': 'utf8mb4',
'database': 'ubains'
}
# 达梦配置
DM_CONFIG = {
'user': 'DM_UBAINS',
'password': 'Ubains@2026Pwd',
'server': '192.168.5.40',
'port': 5236
}
def get_mysql_columns(cursor, table_name):
"""获取 MySQL 表的所有字段信息"""
cursor.execute(f"""
SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH,
NUMERIC_PRECISION, NUMERIC_SCALE, IS_NULLABLE, COLUMN_DEFAULT,
COLUMN_COMMENT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'ubains' AND TABLE_NAME = %s
ORDER BY ORDINAL_POSITION
""", (table_name,))
columns = {}
for row in cursor.fetchall():
col_name = row[0].upper() # 统一转为大写
columns[col_name] = {
'name': row[0],
'data_type': row[1],
'char_length': row[2],
'num_precision': row[3],
'num_scale': row[4],
'nullable': row[5],
'default': row[6],
'comment': row[7]
}
return columns
def get_dm_columns(cursor, table_name):
"""获取达梦表的所有字段信息"""
# 达梦中表名是大写的
cursor.execute(f"""
SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH,
DATA_PRECISION, DATA_SCALE, NULLABLE, DATA_DEFAULT
FROM DBA_TAB_COLUMNS
WHERE OWNER = 'DM_UBAINS' AND TABLE_NAME = '{table_name.upper()}'
ORDER BY COLUMN_ID
""")
columns = {}
for row in cursor.fetchall():
col_name = row[0].upper() # 统一转为大写
columns[col_name] = {
'name': row[0],
'data_type': row[1],
'data_length': row[2],
'data_precision': row[3],
'data_scale': row[4],
'nullable': row[5],
'default': row[6]
}
return columns
def get_mysql_tables(cursor):
"""获取 MySQL 所有表名"""
cursor.execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'ubains' AND TABLE_TYPE = 'BASE TABLE'")
return [row[0].upper() for row in cursor.fetchall()]
def get_dm_tables(cursor):
"""获取达梦所有表名"""
cursor.execute("SELECT TABLE_NAME FROM DBA_TABLES WHERE OWNER = 'DM_UBAINS'")
return [row[0].upper() for row in cursor.fetchall()]
def convert_mysql_type_to_dm(col_info):
"""将 MySQL 字段类型转换为达梦类型"""
mysql_type = col_info['data_type'].upper()
char_len = col_info['char_length']
num_prec = col_info['num_precision']
num_scale = col_info['num_scale']
# 类型映射
type_mapping = {
'INT': 'INT',
'INTEGER': 'INT',
'TINYINT': 'TINYINT',
'SMALLINT': 'SMALLINT',
'BIGINT': 'BIGINT',
'VARCHAR': f"VARCHAR({char_len})" if char_len else "VARCHAR(255)",
'CHAR': f"CHAR({char_len})" if char_len else "CHAR(1)",
'TEXT': 'TEXT',
'LONGTEXT': 'CLOB',
'MEDIUMTEXT': 'CLOB',
'TINYTEXT': 'VARCHAR(255)',
'DATETIME': 'DATETIME',
'TIMESTAMP': 'TIMESTAMP',
'DATE': 'DATE',
'TIME': 'TIME',
'DECIMAL': f"DECIMAL({num_prec},{num_scale})" if num_prec and num_scale else "DECIMAL(10,2)",
'FLOAT': 'FLOAT',
'DOUBLE': 'DOUBLE',
'BLOB': 'BLOB',
'LONGBLOB': 'BLOB',
'MEDIUMBLOB': 'BLOB',
'TINYBLOB': 'BLOB',
'BIT': 'BIT'
}
return type_mapping.get(mysql_type, 'VARCHAR(255)')
def generate_alter_sql(table_name, missing_columns):
"""生成 ALTER TABLE 添加字段的 SQL"""
sqls = []
for col_name, col_info in missing_columns.items():
dm_type = convert_mysql_type_to_dm(col_info)
# 处理默认值
default_clause = ""
if col_info['default'] is not None:
default_val = col_info['default']
if default_val == 'NULL':
default_clause = " DEFAULT NULL"
else:
# 需要转义单引号
default_val_str = str(default_val).replace("'", "''")
default_clause = f" DEFAULT '{default_val_str}'"
# 处理 NOT NULL
null_clause = " NOT NULL" if col_info['nullable'] == 'NO' else ""
# 检查是否为达梦保留字
dm_reserved_words = ['COMMENT', 'USER', 'PASSWORD', 'INDEX', 'KEY', 'VALUE', 'ORDER', 'GROUP',
'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'ALTER',
'TABLE', 'FROM', 'WHERE', 'AND', 'OR', 'NOT', 'NULL', 'TRUE', 'FALSE']
col_name_quoted = f'"{col_name}"' if col_name.upper() in dm_reserved_words else col_name
sql = f"ALTER TABLE {table_name} ADD {col_name_quoted} {dm_type}{default_clause}{null_clause};"
sqls.append(sql)
return sqls
def main():
print("=" * 80)
print("对比 MySQL 和达梦数据库表字段差异")
print("=" * 80)
# 连接 MySQL
mysql_conn = pymysql.connect(**MYSQL_CONFIG)
mysql_cursor = mysql_conn.cursor()
# 连接达梦
dm_conn = dmPython.connect(**DM_CONFIG)
dm_cursor = dm_conn.cursor()
try:
# 获取表列表
mysql_tables = get_mysql_tables(mysql_cursor)
dm_tables = get_dm_tables(dm_cursor)
print(f"\nMySQL 表数量: {len(mysql_tables)}")
print(f"达梦表数量: {len(dm_tables)}")
# 找出 MySQL 有但达梦没有的表
missing_tables = set(mysql_tables) - set(dm_tables)
if missing_tables:
print(f"\n达梦缺失的表 ({len(missing_tables)}):")
for t in sorted(missing_tables):
print(f" - {t}")
# 对比每个表的字段差异
all_missing_columns = {}
common_tables = set(mysql_tables) & set(dm_tables)
print(f"\n开始对比 {len(common_tables)} 张共同表的字段差异...")
for table_name in sorted(common_tables):
mysql_cols = get_mysql_columns(mysql_cursor, table_name)
dm_cols = get_dm_columns(dm_cursor, table_name)
# 找出 MySQL 有但达梦没有的字段
missing_cols = {}
for col_name, col_info in mysql_cols.items():
if col_name not in dm_cols:
missing_cols[col_name] = col_info
if missing_cols:
all_missing_columns[table_name] = missing_cols
# 输出结果
if all_missing_columns:
print("\n" + "=" * 80)
print("缺失字段统计")
print("=" * 80)
total_missing = 0
for table_name in sorted(all_missing_columns.keys()):
missing = all_missing_columns[table_name]
total_missing += len(missing)
print(f"\n表 {table_name} 缺失 {len(missing)} 个字段:")
for col_name, col_info in missing.items():
print(f" - {col_name}: {col_info['data_type']}" +
(f"({col_info['char_length']})" if col_info['char_length'] else "") +
(f" DEFAULT {col_info['default']}" if col_info['default'] else "") +
(f" NOT NULL" if col_info['nullable'] == 'NO' else ""))
print(f"\n总计: {len(all_missing_columns)} 张表缺失 {total_missing} 个字段")
# 生成 SQL
print("\n" + "=" * 80)
print("生成补充字段的 SQL 语句")
print("=" * 80)
for table_name in sorted(all_missing_columns.keys()):
missing = all_missing_columns[table_name]
print(f"\n-- 表 {table_name}")
sqls = generate_alter_sql(table_name, missing)
for sql in sqls:
print(sql)
else:
print("\n没有发现字段缺失!")
# 检查错误日志中提到的具体表
print("\n" + "=" * 80)
print("检查错误日志中提到的具体表")
print("=" * 80)
for table_name in ['RMS_MANAGE_USER_AREA', 'SYS_CONFIGURATION']:
print(f"\n表 {table_name}:")
if table_name in all_missing_columns:
print(f" 缺失字段: {list(all_missing_columns[table_name].keys())}")
else:
# 打印表的所有字段
mysql_cols = get_mysql_columns(mysql_cursor, table_name)
dm_cols = get_dm_columns(dm_cursor, table_name)
print(f" MySQL 字段: {list(mysql_cols.keys())}")
print(f" 达梦字段: {list(dm_cols.keys())}")
finally:
mysql_cursor.close()
mysql_conn.close()
dm_cursor.close()
dm_conn.close()
if __name__ == '__main__':
main()
\ No newline at end of file
#!/bin/bash
# DM8 容器启动入口脚本(挂载版本)
# 操作模式:不构建新镜像,直接使用已有基础镜像 + 挂载 DM8 安装目录
#
# 用法:docker run -d --name dm8-server ... dm8-arm64:v1.0
# 或直接:bash dm8_container_start.sh
set -e
echo "=== DM8 Container Start (Mount Mode) ==="
echo "时间: $(date)"
# 基础设置
DM_HOME=${DM_HOME:-/opt/dm8}
DM_DATA=${DM_DATA:-/opt/dm8/data}
DM_INSTANCE_NAME=${DM_INSTANCE_NAME:-DAMENG}
DM_PORT=${DM_PORT:-5236}
echo "DM_HOME=${DM_HOME}"
echo "DM_DATA=${DM_DATA}"
echo "DM_INSTANCE_NAME=${DM_INSTANCE_NAME}"
echo "DM_PORT=${DM_PORT}"
# 检查 DM8 安装
if [ ! -f "${DM_HOME}/bin/dmserver" ]; then
echo "ERROR: dmserver not found at ${DM_HOME}/bin/dmserver"
exit 1
fi
# 检查数据目录
if [ ! -d "${DM_DATA}/${DM_INSTANCE_NAME}" ]; then
echo "=== 首次启动,初始化数据目录 ==="
mkdir -p ${DM_DATA}
fi
# 启动 dmap 辅助服务
if [ -f "${DM_HOME}/bin/dmap" ]; then
echo "=== 启动 dmap 服务 ==="
if ! pgrep -x "dmap" > /dev/null 2>&1; then
${DM_HOME}/bin/dmap dmap_ini=${DM_HOME}/bin/dmap.ini > /dev/null 2>&1 &
sleep 2
echo "dmap 服务已启动"
else
echo "dmap 服务已在运行"
fi
fi
# 检查 dm.ini
DM_INI="${DM_DATA}/${DM_INSTANCE_NAME}/dm.ini"
if [ ! -f "${DM_INI}" ]; then
echo "ERROR: dm.ini not found at ${DM_INI}"
echo "请先执行 dminit 初始化实例"
exit 1
fi
echo "=== 启动 dmserver ==="
echo "实例: ${DM_INSTANCE_NAME}"
echo "配置文件: ${DM_INI}"
echo "端口: ${DM_PORT}"
# 前台启动 dmserver
exec ${DM_HOME}/bin/dmserver ${DM_INI} -noconsole
\ No newline at end of file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""验证各 Schema 表数量"""
import paramiko, sys, io
if sys.platform == 'win32':
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.5.46', 22, 'root', 'Ubains@123', timeout=30)
schemas = ['DEVOPS', 'DEVOPS_VOICE', 'HUAZHAO2', 'NACOS_MYSQL', 'OFFLINE', 'UBAINS']
for schema in schemas:
# 方法: 创建 shell 脚本然后用 bash heredoc
script = f"""cat > /tmp/v_{schema}.sh << 'ENDSCRIPT'
#!/bin/bash
/opt/dmdbms/bin/disql SYSDBA/Dameng2026Pwd@localhost:5236 << 'EOSQL'
SELECT COUNT(*) FROM ALL_TABLES WHERE OWNER='{schema}';
exit
EOSQL
ENDSCRIPT
"""
stdin, stdout, stderr = client.exec_command(script, timeout=10)
cmd = f"docker cp /tmp/v_{schema}.sh dm8-server:/tmp/v_{schema}.sh && docker exec dm8-server bash -c 'chmod +x /tmp/v_{schema}.sh && /tmp/v_{schema}.sh'"
stdin, stdout, stderr = client.exec_command(cmd, timeout=30)
out = stdout.read().decode('utf-8', errors='replace')
# 解析数字
for line in out.split('\n'):
line = line.strip()
if line.isdigit():
print(f" {schema}: {line} 个表")
client.close()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
从定义文件中提取缺失表的 DDL 并在达梦中创建
"""
import paramiko
import re
SSH_HOST = '192.168.5.40'
SSH_USER = 'root'
SSH_PWD = 'Ubains@123'
CONTAINER = 'dm8-server'
DM_PORT = 5236
DM_SYSDBA_PWD = 'Dameng2026Pwd'
# 需要创建的表
TABLES_TO_CREATE = [
'UVOICE_VOICEPRINT_GROUP_MEMBER',
'UVOICE_AI_MODEL_CONFIG',
'UVOICE_AI_USAGE_LOG',
'UVOICE_MEETING_ACTION_ITEMS',
'UVOICE_MEETING_MINUTES_TEMPLATE',
'UVOICE_MEETING_PERSON_SUMMARY',
'UVOICE_MEETING_SUMMARY',
'UVOICE_MEETING_SUMMARY_TEMPLATE',
'UVOICE_OA_DEPARTMENT',
'UVOICE_OA_SYNC_LOG',
'UVOICE_OPERATION_LOG',
'UVOICE_ROOMVISIBILITY',
'UVOICE_VOICEPRINT_GROUP',
]
def extract_table_ddl(sql_file, table_name):
"""从 SQL 文件中提取指定表的 DDL"""
with open(sql_file, 'r', encoding='utf-8') as f:
content = f.read()
# 匹配 CREATE TABLE 语句
# 格式: CREATE TABLE "UVOICE"."TABLE_NAME" ( ... );
pattern = re.compile(
rf'CREATE TABLE\s+"UVOICE"\s*\.\s*"{table_name}"\s*\((.*?)\);',
re.IGNORECASE | re.DOTALL
)
match = pattern.search(content)
if match:
columns_def = match.group(1)
# 构建 DDL,使用 DM_DEVOPS_VOICE schema
ddl = f'CREATE TABLE "DM_DEVOPS_VOICE"."{table_name}"\n({columns_def}\n);'
return ddl
return None
def create_ssh():
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=SSH_HOST, port=22, username=SSH_USER, password=SSH_PWD, timeout=10)
return ssh
def exe_sql(ssh, sql):
cmd = f'docker exec -i {CONTAINER} bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql SYSDBA/{DM_SYSDBA_PWD}@localhost:{DM_PORT}"'
s, o, e = ssh.exec_command(cmd, timeout=120)
s.write(sql)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore')
def main():
print("=" * 60)
print("创建缺失的表")
print("=" * 60)
ssh = create_ssh()
print("\nSSH 连接成功")
sql_file = 'Docs/PRD/达梦数据库/定义文件/UVOICE.sql'
success = 0
failed = 0
not_found = 0
for table_name in TABLES_TO_CREATE:
print(f"\n[{TABLES_TO_CREATE.index(table_name) + 1}/{len(TABLES_TO_CREATE)}] {table_name}")
# 提取 DDL
ddl = extract_table_ddl(sql_file, table_name)
if not ddl:
print(" 未找到定义")
not_found += 1
continue
# 执行 DDL
output = exe_sql(ssh, ddl)
if 'executed successfully' in output or ('error' not in output.lower() and '错误' not in output):
print(" 创建成功")
success += 1
elif 'already exists' in output.lower() or '已存在' in output:
print(" 表已存在")
success += 1
else:
print(f" 创建失败: {output[:200]}")
failed += 1
ssh.close()
print("\n" + "=" * 60)
print(f"完成: 成功 {success}, 失败 {failed}, 未找到定义 {not_found}")
print("=" * 60)
if __name__ == '__main__':
main()
\ No newline at end of file
#!/bin/bash
# 将新 DM8 实例部署到端口 5236
set -e
echo "=== 停止旧容器 ==="
docker stop dm8-server 2>/dev/null || true
docker rm dm8-server 2>/dev/null || true
# 备份原数据
if [ -d /home/dmdba/dm8/data/DAMENG ] && [ ! -d /home/dmdba/dm8/data/DAMENG.bak_20260629 ]; then
echo "=== 备份原数据 ==="
mv /home/dmdba/dm8/data/DAMENG /home/dmdba/dm8/data/DAMENG.bak_20260629
echo "原数据已备份到 DAMENG.bak_20260629"
fi
# 清理测试数据
rm -rf /data/dm8_test
echo "=== 使用 dminit 初始化新实例(端口 5236) ==="
/usr/local/dm8/bin/dminit PATH=/home/dmdba/dm8/data INSTANCE_NAME=DAMENG PORT_NUM=5236 SYSDBA_PWD=Dameng123 SYSAUDITOR_PWD=Dameng123 2>&1
# 修正权限
chown -R 1001:1001 /home/dmdba/dm8/data/DAMENG 2>/dev/null || true
echo ""
echo "=== 启动 DM8 容器 ==="
docker run -d \
--name dm8-server \
--restart unless-stopped \
-p 5236:5236 \
-v /usr/local/dm8:/usr/local/dm8:ro \
-v /home/dmdba/dm8:/home/dmdba/dm8 \
--entrypoint "" \
kkfile_arm:latest \
sh -c '/usr/local/dm8/bin/dmap dmap_ini=/usr/local/dm8/bin/dmap.ini & sleep 2; exec /usr/local/dm8/bin/dmserver /home/dmdba/dm8/data/DAMENG/dm.ini -noconsole'
echo "等待启动..."
sleep 25
echo ""
echo "=== 容器状态 ==="
docker ps --filter name=dm8-server
echo ""
echo "=== 许可证 ==="
docker logs dm8-server 2>&1 | grep -iE "license|expire|READY"
echo ""
echo "=== 端口 ==="
netstat -tlnp | grep 5236
echo ""
echo "=== 连接测试 ==="
docker exec dm8-server /usr/local/dm8/bin/disql SYSDBA/Dameng123@localhost:5236 -e "SELECT SYSDATE FROM DUAL;" 2>&1
echo ""
echo "=== 创建测试表验证功能 ==="
docker exec dm8-server sh -c '/usr/local/dm8/bin/disql SYSDBA/Dameng123@localhost:5236 -e "CREATE TABLE T_DEPLOY(ID INT, NAME VARCHAR(50)); INSERT INTO T_DEPLOY VALUES(1, '\''container-5236-ok'\''); SELECT * FROM T_DEPLOY;"' 2>&1
echo ""
echo "=== 部署完成 ==="
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
# -*- coding: utf-8 -*-
"""删除重复的小写列"""
import paramiko
from collections import defaultdict
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='192.168.5.40', port=22, username='root', password='Ubains@123', timeout=10)
def exe(cmd, stdin_data=None, timeout=120):
s,o,e = ssh.exec_command(cmd, timeout=timeout)
if stdin_data:
s.write(stdin_data)
s.close()
o.channel.recv_exit_status()
return o.read().decode('utf-8', errors='ignore'), e.read().decode('utf-8', errors='ignore')
PWD='Dameng2026Pwd'
# Get all columns and find duplicates
sql = 'SET LINESHOW OFF;\nSET HEADING OFF;\nSELECT TABLE_NAME, COLUMN_NAME FROM USER_TAB_COLUMNS WHERE TABLE_NAME != \'user\' ORDER BY TABLE_NAME, COLUMN_NAME;'
o,e = exe(f'docker exec -i dm8-server bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql DM_UBAINS/{PWD}@localhost:5236"', stdin_data=sql)
table_cols = defaultdict(list)
for line in o.split('\n'):
parts = line.strip().split()
if len(parts) == 2:
t, c = parts[0], parts[1]
table_cols[t].append(c)
drop_sqls = []
for table, cols in table_cols.items():
upper_cols = {c.upper() for c in cols}
lower_cols = [c for c in cols if c != c.upper()]
for lc in lower_cols:
if lc.upper() in upper_cols:
drop_sqls.append(f'ALTER TABLE {table} DROP COLUMN "{lc}";')
print(f'Deleting {len(drop_sqls)} duplicate lowercase columns...')
# Execute in batches
batch_size = 50
success = 0
fail = 0
for i in range(0, len(drop_sqls), batch_size):
batch = drop_sqls[i:i+batch_size]
sql_batch = '\n'.join(batch) + '\n'
o,e = exe(f'docker exec -i dm8-server bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql DM_UBAINS/{PWD}@localhost:5236"', stdin_data=sql_batch, timeout=120)
s = o.count('executed successfully')
f = o.count('Error in line')
success += s
fail += f
print(f'Batch {i//batch_size+1}: success={s}, fail={f}')
print(f'Total: success={success}, fail={fail}')
# Verify remaining lowercase columns
sql = 'SELECT COUNT(*) FROM USER_TAB_COLUMNS WHERE COLUMN_NAME != UPPER(COLUMN_NAME) AND TABLE_NAME != \'user\';'
o,e = exe(f'docker exec -i dm8-server bash -c "export LD_LIBRARY_PATH=/opt/dmdbms/bin && /opt/dmdbms/bin/disql DM_UBAINS/{PWD}@localhost:5236"', stdin_data=sql)
import re
rem = -1
for line in o.split('\n'):
m = re.search(r'^\s*\d+\s+(\d+)\s*$', line.strip())
if m:
rem = int(m.group(1))
break
print(f'Remaining lowercase columns: {rem}')
ssh.close()
\ No newline at end of file
#!/bin/bash
# DM8 容器入口脚本
# 功能:检查并初始化实例,然后启动 dmserver
set -e
echo "=== DM8 Docker Entrypoint ==="
echo "时间: $(date)"
echo "主机名: $(hostname)"
# 环境变量
DM_HOME=${DM_HOME:-/opt/dm8}
DM_DATA=${DM_DATA:-/opt/dm8/data}
DM_INSTANCE_NAME=${DM_INSTANCE_NAME:-DAMENG}
DM_PORT=${DM_PORT:-5236}
echo "DM_HOME=${DM_HOME}"
echo "DM_DATA=${DM_DATA}"
echo "DM_INSTANCE_NAME=${DM_INSTANCE_NAME}"
echo "DM_PORT=${DM_PORT}"
# 检查 DM8 安装目录
if [ ! -d "${DM_HOME}/bin" ]; then
echo "ERROR: DM8 安装目录不存在: ${DM_HOME}/bin"
exit 1
fi
# 检查 dmserver 可执行文件
if [ ! -x "${DM_HOME}/bin/dmserver" ]; then
echo "ERROR: dmserver 可执行文件不存在或不可执行"
exit 1
fi
# 检查数据目录
if [ ! -d "${DM_DATA}/${DM_INSTANCE_NAME}" ]; then
echo "=== 数据目录不存在,执行初始化 ==="
/init_instance.sh
fi
# 检查 dm.ini 文件
DM_INI="${DM_DATA}/${DM_INSTANCE_NAME}/dm.ini"
if [ ! -f "${DM_INI}" ]; then
echo "ERROR: dm.ini 配置文件不存在: ${DM_INI}"
exit 1
fi
# 检查端口是否已监听(防止重复启动)
if netstat -tlnp 2>/dev/null | grep -q ":${DM_PORT}"; then
echo "WARNING: 端口 ${DM_PORT} 已被监听,可能已有 dmserver 运行"
fi
# 检查 dmap 服务(DM8 辅助服务)
if [ -x "${DM_HOME}/bin/dmap" ]; then
echo "=== 启动 dmap 服务 ==="
if ! pgrep -x "dmap" > /dev/null; then
${DM_HOME}/bin/dmap dmap_ini=${DM_HOME}/bin/dmap.ini &
sleep 2
echo "dmap 服务已启动"
else
echo "dmap 服务已在运行"
fi
fi
echo "=== 启动 dmserver ==="
echo "命令: dmserver ${DM_INI} -noconsole"
# 启动 dmserver(前台运行)
exec ${DM_HOME}/bin/dmserver ${DM_INI} -noconsole
\ No newline at end of file
#!/bin/bash
# DM8 最终部署脚本 - 端口 5236,数据持久化在 /data/dm8
# 密码:SYSDBA/Dameng123
set -e
echo "=== 清理旧容器 ==="
docker rm -f dm8-server dm8-test 2>/dev/null || true
echo "=== 启动 DM8 容器 ==="
docker run -d \
--name dm8-server \
--restart unless-stopped \
-p 5236:5236 \
-v /usr/local/dm8:/usr/local/dm8:ro \
-v /data/dm8:/data/dm8 \
--entrypoint "" \
kkfile_arm:latest \
sh -c '/usr/local/dm8/bin/dmap dmap_ini=/usr/local/dm8/bin/dmap.ini & sleep 2; exec /usr/local/dm8/bin/dmserver /data/dm8/DAMENG/dm.ini -noconsole'
echo "等待启动..."
sleep 30
echo ""
echo "=== 容器状态 ==="
docker ps --filter name=dm8-server --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo "=== 许可证有效期 ==="
docker logs dm8-server 2>&1 | grep -iE "license|expire|SYSTEM IS READY"
echo ""
echo "=== 端口监听 ==="
netstat -tlnp | grep 5236
echo ""
echo "=== 连接测试 ==="
docker exec dm8-server /usr/local/dm8/bin/disql SYSDBA/Dameng123@localhost:5236 -e "SELECT SYSDATE FROM DUAL;" 2>&1
echo ""
echo "=== 功能测试 ==="
docker exec dm8-server sh -c '/usr/local/dm8/bin/disql SYSDBA/Dameng123@localhost:5236 -e "CREATE TABLE DM8_OK(ID INT, MSG VARCHAR(20)); INSERT INTO DM8_OK VALUES(1, '\''5236-ready'\''); SELECT * FROM DM8_OK;"' 2>&1
echo ""
echo "=== 部署完成!==="
echo "容器名: dm8-server"
echo "端口: 5236"
echo "密码: SYSDBA/Dameng123"
echo "数据目录: /data/dm8/DAMENG"
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论