一、总体架构

┌─────────────────────┐         ┌─────────────────────┐
│   CentOS 应用服务器  │         │   Windows 服务器     │
│                     │  445端口 │                     │
│  1. mongodump       │ ──────▶ │  共享目录            │
│     备份到本地       │ smb协议 │  D:\backups\mongo    │
│  2. smbclient 上传  │         │  专用备份账号        │
│  3. 清理旧备份       │         │                     │
└─────────────────────┘         └─────────────────────┘
         │
         │(如 MongoDB 在另一台机器)
         ▼
   MongoDB 服务器 (27017)

部署顺序建议:先配 Windows → 再配 CentOS → 手动测试 → 加定时任务。


二、Windows 服务器配置

2.1 创建专用备份账号

不要用管理员账号做备份。创建一个专用本地账号,只给共享目录权限。

图形界面操作步骤:

  1. Win + R 输入 lusrmgr.msc 回车,打开「本地用户和组」
    • Windows Server 也可以:右键「此电脑」→「管理」→「计算机管理」→「本地用户和组」→「用户」
  2. 右键「用户」→「新用户」
  3. 用户名填 mongobak,设置一个强密码,描述可填「MongoDB备份专用账号」
  4. 取消勾选「用户下次登录时须更改密码」,勾选「密码永不过期」
  5. 点「创建」

注意:

  • 这个账号不需要加入 Administrators 组,保持普通用户即可,权限最小化。
  • 如果是 Windows 家庭版(没有 lusrmgr.msc),可用「设置 → 账户 → 其他用户」添加本地用户,或用管理员命令提示符执行 net user mongobak 密码 /add。

2.2 创建备份目录并设置共享

  1. 打开资源管理器,在 D 盘新建文件夹 backups,进入后再新建子文件夹 mongo
    • mongo 子目录对应脚本里的 WIN_SUBDIR,名字要保持一致
  2. 右键 backups 文件夹 →「属性」→「共享」选项卡 →「高级共享」
  3. 勾选「共享此文件夹」,共享名填 backups
  4. 点「权限」按钮:
    • 删除 Everyone
    • 点「添加」→ 输入 mongobak → 确定
    • 给 mongobak 勾选「完全控制」→ 确定
  5. 切到「安全」选项卡 →「编辑」→「添加」→ 输入 mongobak → 确定
    • 给 mongobak 勾选「修改」权限 → 确定

共享权限(第 4 步)和 NTFS 权限(第 5 步)两层都要设置,缺一不可。实际生效权限取两者的交集。

2.3 防火墙放行 SMB(445 端口)

  1. 打开「控制面板」→「系统和安全」→「Windows Defender 防火墙」
  2. 点左侧「高级设置」,打开「高级安全 Windows Defender 防火墙」
  3. 点左侧「入站规则」
  4. 在规则列表中找到「文件和打印机共享(SMB-In)」(专用/公用配置文件各一条)
  5. 右键 →「启用规则」

也可以在第 2 步点「允许应用或功能通过 Windows Defender 防火墙」,勾选「文件和打印机共享」。

2.4 验证共享

在任意一台 Windows 机器上,Win + R 输入:

\\192.168.1.10\backups

用 mongobak 账号登录,能进入并新建文件即成功。

也可以直接在 CentOS 上验证,见 3.4 节。


三、CentOS 应用服务器配置

3.1 安装必要软件

# 安装 smbclient(用于上传)
sudo yum install -y samba-client

# 安装 mongodb-database-tools(提供 mongodump/mongorestore)
# 先添加 MongoDB 官方源(以 7.0 为例,按你的服务端版本调整)
cat << 'EOF' | sudo tee /etc/yum.repos.d/mongodb-org-7.0.repo
[mongodb-org-7.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/7.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://pgp.mongodb.com/server-7.0.asc
EOF

sudo yum install -y mongodb-database-tools

# 验证
mongodump --version
smbclient --version

mongodump 大版本最好与 MongoDB 服务端大版本一致,避免兼容问题。

3.2 创建本地备份目录

sudo mkdir -p /data/dbbackup

3.3 创建凭证文件

sudo mkdir -p /root/.smb
sudo tee /root/.smb/win_cred << 'EOF'
username=mongobak
password=你的备份账号密码
EOF
sudo chmod 600 /root/.smb/win_cred
  • 密码改成你在 2.1 步设置的实际密码。
  • 如果 Windows 服务器在域里,加一行 domain=域名;本地账号不用加。
  • chmod 600 必须做,否则凭证会被其他用户读到。

3.4 测试共享连通性

# 列目录测试(能列出 mongo 目录说明通了)
smbclient -m SMB3 "//192.168.1.10/backups" -A /root/.smb/win_cred -c "ls"

# 写入测试
echo "test" > /tmp/smb_test.txt
smbclient -m SMB3 "//192.168.1.10/backups" -A /root/.smb/win_cred \
  -c "cd mongo; put /tmp/smb_test.txt smb_test.txt"
smbclient -m SMB3 "//192.168.1.10/backups" -A /root/.smb/win_cred \
  -c "cd mongo; ls; del smb_test.txt"

如果这里报错,先解决再继续,常见报错见第五节排查表。

3.5 部署备份脚本

  1. 把脚本上传到服务器,例如 /opt/scripts/mongo_backup.sh
  2. 修改脚本开头的配置区:
DB_HOST="127.0.0.1"        # MongoDB 不在本机就改成它的 IP
DB_PORT="27017"
TARGET_DBS=("TestDB")      # 要备份的数据库列表,空格分隔可写多个,如 ("TestDB" "OtherDB")
# 备份所有数据库则改成:TARGET_DBS=("ALL")

WIN_SHARE_IP="192.168.1.10" # 改成 Windows 服务器实际 IP
WIN_SHARE_PATH="backups"
WIN_SUBDIR="mongo"
  1. 注意换行符问题:如果脚本是在 Windows 上编辑后传过去的,行尾可能是 CRLF,运行会报「没有那个文件或目录」。先转换:
sudo yum install -y dos2unix
sudo dos2unix /opt/scripts/mongo_backup.sh
  1. 赋权并手动测试:
sudo chmod +x /opt/scripts/mongo_backup.sh
sudo /opt/scripts/mongo_backup.sh
  1. 检查两处结果:
    • 本地 /data/dbbackup/ 下有 TestDB_backup_xxx.gzip
    • Windows 的 D:\backups\mongo\ 下有同名文件

3.6 配置定时任务

sudo crontab -e

添加一行(每天凌晨 2 点备份,日志追加到文件):

0 2 * * * /opt/scripts/mongo_backup.sh >> /var/log/mongo_backup.log 2>&1

查看日志:

tail -50 /var/log/mongo_backup.log

3.7 MongoDB 在其他机器时的额外检查

如果 DB_HOST 不是 127.0.0.1,需要确认:

  1. MongoDB 的 bindIp 允许应用服务器访问,在 mongod.conf 中:

    net:
      bindIp: 127.0.0.1,192.168.x.x   # 加上 MongoDB 服务器的内网 IP
    

    改完重启 mongod。

  2. MongoDB 服务器防火墙放行 27017 给应用服务器:

    sudo firewall-cmd --permanent --new-zone=mongo
    sudo firewall-cmd --permanent --zone=mongo --add-source=应用服务器IP/32
    sudo firewall-cmd --permanent --zone=mongo --add-port=27017/tcp
    sudo firewall-cmd --reload
    
  3. 如果 MongoDB 开了认证,在脚本里填 DB_USER / DB_PASS,该账号至少需要 backup 角色或对目标库的读权限。


四、恢复数据的方法

# 从本地备份恢复
mongorestore --host 127.0.0.1 --port 27017 \
  --gzip --archive=/data/dbbackup/TestDB_backup_20260825_020000.gzip \
  --db TestDB --drop

# 文件在 Windows 共享上时,先拉回来再恢复
smbclient -m SMB3 "//192.168.1.10/backups" -A /root/.smb/win_cred \
  -c "cd mongo; get TestDB_backup_20260825_020000.gzip /tmp/restore.gzip"
mongorestore --gzip --archive=/tmp/restore.gzip --db TestDB --drop

--drop 会先删除现有集合再恢复,生产环境慎用;恢复到新库名可以去掉 --db 改用 --nsFrom/--nsTo。
如果用的是 ALL 模式备份,恢复单个库时加 --nsInclude 过滤,例如 --nsInclude="TestDB.*"。


五、常见问题排查

现象 可能原因 解决办法
无法执行 xxx.sh: 没有那个文件或目录(文件明明存在) 脚本带 Windows 换行符(CRLF) dos2unix 或 sed -i 's/\r$//' 转换,见 3.5 节
NT_STATUS_ACCESS_DENIED 账号密码错 / 没共享权限 / NTFS 权限不足 核对凭证文件;检查共享权限和「安全」选项卡都有 mongobak
NT_STATUS_LOGON_FAILURE 密码错误或账号被锁 在 Windows 上重置密码,同步更新凭证文件
NT_STATUS_BAD_NETWORK_NAME 共享名不对 smbclient -L //IP -A 凭证 列出所有共享核对名字
连接超时 防火墙 / 445 不通 telnet 192.168.1.10 445 测试;按 2.3 节放行文件和打印机共享
protocol negotiation failed SMB 协议协商失败 脚本已加-m SMB3;确认 Windows 没禁用 SMB3
中文目录乱码 系统 locale 不对 脚本已强制 UTF-8;确认 CentOS 装了中文 locale
mongodump 连不上 bindIp / 防火墙 / 认证 见 3.7 节
定时任务没执行 cron 环境变量差异 脚本内用绝对路径;查看/var/log/mongo_backup.log 和 /var/log/cron

六、安全建议

  1. 备份账号 mongobak 不要加入任何管理员组,只对 D:\backups 有权限。
  2. 凭证文件必须 chmod 600,属 root。
  3. 备份文件包含业务数据,共享目录不要对 Everyone 开放。
  4. 建议定期(比如每季度)做一次恢复演练,确认备份文件真的可用。
  5. 本地只保留 7 天(LOCAL_RETENTION_DAYS),共享保留 30 天(WIN_RETENTION_DAYS),可按磁盘容量调整。