recover_enter_server.sh 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #!/bin/bash
  2. # 恢复 game_enter_server 数据
  3. # 依赖: mysql 命令行、mongosh(或 mongo)
  4. # 运行: bash recover_enter_server.sh > recover.sql
  5. # ========== 配置 ==========
  6. MYSQL_HOST="127.0.0.1"
  7. MYSQL_PORT="3306"
  8. MYSQL_USER="root"
  9. MYSQL_PASS="wch123.com"
  10. MYSQL_DB="sdk"
  11. MONGO_HOST="127.0.0.1"
  12. MONGO_PORT="27017"
  13. # ==========================
  14. # 判断用 mongosh 还是旧版 mongo
  15. if command -v mongosh &>/dev/null; then
  16. MONGO_CMD="mongosh --quiet"
  17. elif command -v mongo &>/dev/null; then
  18. MONGO_CMD="mongo --quiet"
  19. else
  20. echo "-- 错误: 未找到 mongosh 或 mongo 命令" >&2
  21. exit 1
  22. fi
  23. MYSQL_CLI="mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASS} ${MYSQL_DB} -N -s"
  24. echo "-- 恢复 game_enter_server (game_server.tag=11)"
  25. echo "-- 生成时间: $(date '+%Y-%m-%d %H:%M:%S')"
  26. echo ""
  27. # 查询 tag=11 的区服列表: id|sid|db_name|tag|open_time|megre_server
  28. # megre_server>0 表示已合服,值为主服 id
  29. SERVERS=$($MYSQL_CLI 2>/dev/null <<'EOF'
  30. SELECT CONCAT(id,'|',IFNULL(sid,''),'|',IFNULL(db_name,''),'|',tag,'|',open_time,'|',megre_server)
  31. FROM game_server
  32. WHERE tag=11;
  33. EOF
  34. )
  35. if [ -z "$SERVERS" ]; then
  36. echo "-- 未查询到 tag=11 的区服" >&2
  37. exit 1
  38. fi
  39. SERVER_COUNT=$(echo "$SERVERS" | wc -l | tr -d ' ')
  40. echo "-- 共找到 ${SERVER_COUNT} 个 tag=11 区服" >&2
  41. TOTAL=0
  42. # 记录已查询过的 db_name,避免重复查同一个 mongo 库
  43. declare -A QUERIED_DB
  44. while IFS='|' read -r SERVER_ID SID DB_NAME TAG OPEN_TIME MEGRE_SERVER; do
  45. # 判断是否合服
  46. if [ -n "$MEGRE_SERVER" ] && [ "$MEGRE_SERVER" -gt 0 ] 2>/dev/null; then
  47. # 合服:查主服的 db_name
  48. MAIN_DB=$($MYSQL_CLI 2>/dev/null <<EOF
  49. SELECT IFNULL(db_name,'') FROM game_server WHERE id=${MEGRE_SERVER} LIMIT 1;
  50. EOF
  51. )
  52. if [ -z "$MAIN_DB" ]; then
  53. echo "-- [SKIP] server_id=${SERVER_ID} 合服主服 id=${MEGRE_SERVER} 未找到" >&2
  54. continue
  55. fi
  56. QUERY_DB="$MAIN_DB"
  57. echo "-- server_id=${SERVER_ID} 已合服到主服 id=${MEGRE_SERVER},使用库 ${QUERY_DB}" >&2
  58. else
  59. # 未合服:用自己的 db_name
  60. if [ -z "$DB_NAME" ]; then
  61. echo "-- [SKIP] server_id=${SERVER_ID} db_name 为空" >&2
  62. continue
  63. fi
  64. QUERY_DB="$DB_NAME"
  65. fi
  66. # 该 db 已查询过,跳过
  67. if [ "${QUERIED_DB[$QUERY_DB]+isset}" ]; then
  68. echo "-- [SKIP] server_id=${SERVER_ID} 库 ${QUERY_DB} 已查询过,跳过" >&2
  69. continue
  70. fi
  71. QUERIED_DB[$QUERY_DB]=1
  72. if [ -n "$OPEN_TIME" ] && [ "$OPEN_TIME" -gt 0 ] 2>/dev/null; then
  73. CREATE_TIME="FROM_UNIXTIME(${OPEN_TIME})"
  74. else
  75. CREATE_TIME="NOW()"
  76. fi
  77. # 从 MongoDB 查询 char 集合,取 uid(newUniqueTag 最后一段)
  78. UIDS=$($MONGO_CMD --host ${MONGO_HOST} --port ${MONGO_PORT} <<EOF 2>/dev/null
  79. db = db.getSiblingDB('${QUERY_DB}');
  80. db.char.find({newUniqueTag: {\$exists: true, \$ne: ""}}, {newUniqueTag:1, _id:0}).forEach(function(doc){
  81. var parts = doc.newUniqueTag.split('|');
  82. var uid = parts[parts.length - 1];
  83. if(uid && /^\d+$/.test(uid)) {
  84. print('OK|' + uid);
  85. } else {
  86. print('WARN|' + doc.newUniqueTag);
  87. }
  88. });
  89. EOF
  90. )
  91. COUNT=$(echo "$UIDS" | grep -c . 2>/dev/null || echo 0)
  92. echo "-- [${QUERY_DB}] server_id=${SERVER_ID} 角色数=${COUNT}" >&2
  93. if [ -z "$UIDS" ]; then continue; fi
  94. BATCH=()
  95. while IFS= read -r LINE; do
  96. [ -z "$LINE" ] && continue
  97. PREFIX="${LINE%%|*}"
  98. UID_VAL="${LINE#*|}"
  99. if [ "$PREFIX" = "WARN" ]; then
  100. echo "-- [WARN] 异常 newUniqueTag: ${UID_VAL}" >&2
  101. continue
  102. fi
  103. if [ "$PREFIX" != "OK" ]; then
  104. echo "-- [SKIP] 非预期输出: ${LINE}" >&2
  105. continue
  106. fi
  107. SAFE_UID=$(echo "$UID_VAL" | sed "s/'/\\\\'/g")
  108. BATCH+=("('${SAFE_UID}', '${SID}', ${CREATE_TIME}, '${SID}', ${TAG})")
  109. TOTAL=$((TOTAL + 1))
  110. if [ ${#BATCH[@]} -ge 500 ]; then
  111. echo "INSERT INTO \`game_enter_server\` (\`uid\`, \`server_id\`, \`create_time\`, \`first_server_id\`, \`tag\`) VALUES"
  112. IFS=','; echo "${BATCH[*]};"|sed 's/),(/),\n(/g'; unset IFS
  113. echo ""
  114. BATCH=()
  115. fi
  116. done <<< "$UIDS"
  117. if [ ${#BATCH[@]} -gt 0 ]; then
  118. echo "INSERT INTO \`game_enter_server\` (\`uid\`, \`server_id\`, \`create_time\`, \`first_server_id\`, \`tag\`) VALUES"
  119. IFS=','; echo "${BATCH[*]};"|sed 's/),(/),\n(/g'; unset IFS
  120. echo ""
  121. BATCH=()
  122. fi
  123. done <<< "$SERVERS"
  124. echo "-- 完成,共生成 ${TOTAL} 条记录" >&2