1 #!/bin/bash
2
3 # #############################################################################
4 #
5 # 功能: 使用 mongoexport 导出 MongoDB。支持指定库、表、认证信息和输出路径。
6 #
7 # 使用方法: ./export_mongo.sh -d <db_name> [选项]
8 # 通过 ./export_mongo.sh -h 查看所有选项。
9 #
10 # #############################################################################
11
12 # --- 默认配置 ---
13 HOST="localhost"
14 PORT="27017"
15 AUTH_DB="admin" # 用于认证的数据库
16
17 # --- 函数定义 ---
18
19 # 显示用法说明
20 usage() {
21 cat <<EOF
22 使用方法: $0 -d <数据库名> [选项]
23
24 这是一个用于导出 MongoDB 数据的多功能脚本。
25
26 必须参数:
27 -d <数据库名> 要导出的数据库名称。
28
29 可选参数:
30 -c <集合名> 要导出的集合名称。如果省略,则导出指定数据库中的所有集合。
31 -o <输出路径> 指定保存导出文件的目录。如果省略,将自动创建一个带时间戳的目录。
32 -u <用户名> 用于数据库认证的用户名。
33 -p <密码> 用于数据库认证的密码。
34 -h 显示此帮助信息。
35
36 示例:
37 # 1. 显示帮助信息
38 $0 -h
39
40 # 2. 导出单个集合到自动生成的目录
41 $0 -d my_app_db -c users
42
43 # 3. 导出单个集合到指定目录 (带认证)
44 $0 -d my_app_db -c users -u admin -p 's3cr3t' -o /mnt/mongo_backups
45
46 # 4. 导出整个数据库到指定目录
47 $0 -d my_app_db -o /tmp/db_full_export
48
49 # 5. 导出整个数据库 (带认证) 到自动生成的目录
50 $0 -d my_app_db -u admin -p 's3cr3t'
51
52 EOF
53 exit 1
54 }
55
56 # --- 参数解析 (使用 getopts) ---
57 DB_NAME=""
58 COLLECTION_NAME=""
59 OUTPUT_DIR=""
60 USERNAME=""
61 PASSWORD=""
62
63 while getopts "d:c:o:u:p:h" opt; do
64 case ${opt} in
65 d ) DB_NAME=$OPTARG;;
66 c ) COLLECTION_NAME=$OPTARG;;
67 o ) OUTPUT_DIR=$OPTARG;;
68 u ) USERNAME=$OPTARG;;
69 p ) PASSWORD=$OPTARG;;
70 h ) usage;;
71 \? ) echo "无效的选项: -$OPTARG" >&2; usage;;
72 : ) echo "选项 -$OPTARG 需要一个参数。" >&2; usage;;
73 esac
74 done
75
76 # --- 参数验证 ---
77 if [ -z "$DB_NAME" ]; then
78 echo "❌ 错误: 必须使用 -d 提供数据库名称。"
79 usage
80 fi
81
82 if [ -n "$USERNAME" ] && [ -z "$PASSWORD" ]; then
83 echo "❌ 错误: 提供了用户名 (-u),但必须同时提供密码 (-p)。"
84 usage
85 fi
86
87 # --- 准备输出目录 ---
88 if [ -z "$OUTPUT_DIR" ]; then
89 # 如果用户未指定输出目录,则自动创建
90 # 将基路径设置为 dotnet/mongo_export
91 OUTPUT_DIR="dotnet/mongo_export/export_${DB_NAME}_$(date +%Y%m%d_%H%M%S)"
92 echo "未指定输出目录,将使用自动生成的目录: $OUTPUT_DIR"
93 fi
94
95 mkdir -p "$OUTPUT_DIR"
96 if [ $? -ne 0 ]; then
97 echo "❌ 错误: 无法创建输出目录 '$OUTPUT_DIR'。请检查权限。"
98 exit 1
99 fi
100 echo "所有导出的文件将保存在: $OUTPUT_DIR"
101
102
103 # --- 构建命令选项 ---
104 AUTH_OPTIONS=""
105 if [ -n "$USERNAME" ]; then
106 AUTH_OPTIONS="--username $USERNAME --password \"$PASSWORD\" --authenticationDatabase $AUTH_DB"
107 fi
108
109 CONNECTION_OPTIONS="--host $HOST --port $PORT"
110
111 # --- 核心导出逻辑 ---
112
113 if [ -n "$COLLECTION_NAME" ]; then
114 # --- 情况 1: 导出单个集合 ---
115 echo "--------------------------------------------------"
116 echo "模式: 导出单个集合"
117 echo "数据库: '$DB_NAME', 集合: '$COLLECTION_NAME'"
118
119 OUTPUT_FILE="$OUTPUT_DIR/${DB_NAME}_${COLLECTION_NAME}.json"
120 COMMAND="mongoexport --db \"$DB_NAME\" --collection \"$COLLECTION_NAME\" $CONNECTION_OPTIONS $AUTH_OPTIONS --out \"$OUTPUT_FILE\" --jsonArray"
121
122 eval $COMMAND
123 if [ $? -eq 0 ]; then
124 echo "✅ 成功! 文件已保存至: $OUTPUT_FILE"
125 else
126 echo "❌ 失败! 导出时发生错误。"
127 fi
128 else
129 # --- 情况 2: 导出整个数据库 ---
130 echo "--------------------------------------------------"
131 echo "模式: 导出整个数据库"
132 echo "数据库: '$DB_NAME'"
133
134 # 构建 mongosh 连接 URI
135 MONGO_URI="mongodb://"
136 if [ -n "$USERNAME" ]; then
137 ENCODED_USER=$(printf %s "$USERNAME" | jq -sRr @uri)
138 ENCODED_PASS=$(printf %s "$PASSWORD" | jq -sRr @uri)
139 MONGO_URI="${MONGO_URI}${ENCODED_USER}:${ENCODED_PASS}@"
140 fi
141 MONGO_URI="${MONGO_URI}${HOST}:${PORT}/${DB_NAME}?authSource=${AUTH_DB}"
142
143 echo "正在获取集合列表..."
144 # 使用 mongosh 获取集合列表,并处理可能的错误
145 COLLECTIONS=$(mongosh "$MONGO_URI" --quiet --eval "try { db.getCollectionNames().join(' ') } catch (e) { print('') }" 2>/dev/null)
146
147 if [ -z "$COLLECTIONS" ]; then
148 echo "❌ 警告: 在数据库 '$DB_NAME' 中找不到任何集合,或者连接/认证失败。请检查数据库名、认证信息和 MongoDB 服务状态。"
149 # 如果目录是自动创建且为空,则删除
150 [[ "$OUTPUT_DIR" == "dotnet/mongo_export/export_"* ]] && rmdir "$OUTPUT_DIR" 2>/dev/null
151 exit 1
152 fi
153
154 echo "找到的集合: $COLLECTIONS"
155 echo "--------------------------------------------------"
156
157 SUCCESS_COUNT=0
158 FAIL_COUNT=0
159 TOTAL_COUNT=$(echo $COLLECTIONS | wc -w)
160 CURRENT_COUNT=1
161
162 for collection in $COLLECTIONS; do
163 echo " -> [${CURRENT_COUNT}/${TOTAL_COUNT}] 正在导出集合: $collection..."
164 OUTPUT_FILE="$OUTPUT_DIR/${DB_NAME}_${collection}.json"
165 COMMAND="mongoexport --db \"$DB_NAME\" --collection \"$collection\" $CONNECTION_OPTIONS $AUTH_OPTIONS --out \"$OUTPUT_FILE\" --jsonArray"
166
167 eval $COMMAND
168 if [ $? -eq 0 ]; then
169 echo " ✅ 成功! 文件: ${OUTPUT_FILE}"
170 SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
171 else
172 echo " ❌ 失败! 导出集合 '$collection' 时出错。"
173 FAIL_COUNT=$((FAIL_COUNT + 1))
174 fi
175 CURRENT_COUNT=$((CURRENT_COUNT + 1))
176 done
177
178 echo "--------------------------------------------------"
179 echo "导出完成!"
180 echo "总计: $SUCCESS_COUNT 个成功, $FAIL_COUNT 个失败。"
181 fi