跳到主要内容

使用rsync实现跨机器批量迁移数据

2023-05-31

在东京开通了新机器, 想要把孟买的数据迁移过去. 期望是网站应用和数据库都能够在新机器直接启动不受影响, 最担心的是数据传送出现丢失而不知道. 另外想要维持文件的各种属性, 出现问题的时候想要能够继续重试, 也不想打包tar再进行传输. 其实如果为了完整, 全部压缩为单个tar包再进行传输是最放心的, 只要scp和md5sum两个命令就能解决, 但搬砖人太懒了, 不想额外进行压缩和解压缩. 咨询了chatgpt, rsync命令和md5sum批量校验命令都给了出来, so easy.

Tips

  • 本地端和目标端都使用root账号操作(修改root账号密码sudo passwd root), 可以免去许多麻烦. 比如mysql数据库的磁盘数据, 普通用户其实是没有权限查看操作的,就需要root账号; 远端要保留文件夹的用户属性更是需要高级用户才行.

  • 提前通过ssh-keygen生成待迁移root账号的ssh密钥, 然后放置到对面机器的root文件夹.ssh中, 可以免去后续输入密码操作.

  • 迁移的时候所有应用都停运(比如docker-compose down). 在迁移过程中mysql会产生binlog日志, web应用更是不停打印后台日志, 不停运的话会导致迁移前后的md5校验不相同.

md5sum: WARNING: 13 computed checksums did NOT match
oot@VM-0-4-ubuntu:/abc# grep -vi ok /abc/mdcheck.txt
/data/gitea/data/gitea/log/gitea.log: FAILED
/data/mysql/data/gitea/public_key.ibd: FAILED
/data/mysql/data/ibdata1: FAILED
/data/mysql/data/mysql.ibd: FAILED
/data/mysql/data/#ib_16384_0.dblwr: FAILED
/data/mysql/data/wordpress/wp_options.ibd: FAILED
/data/mysql/data/undo_001: FAILED
/data/mysql/data/binlog.000006: FAILED
/data/mysql/data/#innodb_redo/#ib_redo36: FAILED
/data/mysql/data/undo_002: FAILED
/data/log/caddy/muddy-access.log: FAILED
/data/log/caddy/wordpress-access.log: FAILED
/data/log/caddy/gitea-access.log: FAILED

核心操作

rsync同步文件夹

从本地的/data目录, 传递到远程的/data目录.

sudo rsync -avzcP  /data root@124.156.00.00:/

注意, 如果没有写目的地的文件夹, 传输的还是在本地...

# error, 没有目的文件夹, 其实是传输到本地文件夹 /root@124.156.00.00
sudo rsync -avzcP /data root@124.156.00.00

来自chatgpt的命令说明:

在这个命令中,-a 选项表示使用归档模式同步文件,包括保留文件的权限、时间戳等信息;-v 选项表示输出详细信息;-z 选项表示启用压缩传输; -P (progress)代表显示传输进度; -c (--checksum)选项表示启用校验和比较;

发送端和接收端使用root账号, 可以省掉许多麻烦.

md5批量比对数据迁移结果

其实rsync命令里有-c命令, 在传输过程中已经会启用checksum计算进行校验和比较, 但终归没有证据不放心, 还是得自己亲自计算md5sum.

本地端通过find命令查询所有文件, 然后使用md5sum进行批量md5计算.

sudo find /data -type f -print0 | sudo  xargs -0 md5sum > data-md5sum.txt

来自chatgpt的命令说明

在这个命令中,find 命令会查找 /path/to/folder 文件夹中的所有文件,并将它们的路径输出到标准输出中。-type f 选项表示只查找普通文件,而不包括目录和符号链接等其他类型的文件。-print0 选项表示使用 null 字符作为文件名的分隔符,以避免文件名中包含空格或其他特殊字符时出现问题。 xargs 命令会将 find 命令输出的文件路径作为参数传递给 md5sum 命令,并计算每个文件的 MD5 校验和。-0 选项表示使用 null 字符作为参数的分隔符,以避免文件名中包含空格或其他特殊字符时出现问题。 最后,将 md5sum 命令的输出重定向到 /path/to/md5sum.txt 文件中,以便在后续检查数据时使用。 在检查数据时,可以使用 md5sum -c 命令读取 /path/to/md5sum.txt 文件中的 MD5 校验和,并将其与相应的文件进行比较,以检查文件是否被修改或损坏。

使用两个sudo, 是因为测试发现管道|前后两个操作的权限是分离的, 不额外设置还是会报权限问题, 如果都临时使用root账号就没有这类奇葩的边缘问题了.

find: ‘/data/gitea/data/ssh’: Permission denied
find: ‘/data/mysql/data/geepack’: Permission denied
find: ‘/data/mysql/data/mysql’: Permission denied
find: ‘/data/mysql/data/sys’: Permission denied
find: ‘/data/mysql/data/performance_schema’: Permission denied
find: ‘/data/mysql/data/#innodb_redo’: Permission denied
find: ‘/data/mysql/data/#innodb_temp’: Permission denied
md5sum: /data/mysql/data/private_key.pem: Permission denied
md5sum: /data/mysql/data/ibdata1: Permission denied
md5sum: /data/mysql/data/mysql/slow_log.CSM: Permission denied                         
md5sum: /data/mysql/data/mysql/slow_log_214.sdi: Permission denied
md5sum: /data/mysql/data/mysql/slow_log.CSV: Permission denied
md5sum: /data/mysql/data/mysql/general_log.CSV: Permission denied
md5sum: /data/mysql/data/binlog.000001: Permission denied
md5sum: /data/mysql/data/client-key.pem: Permission denied
md5sum: /data/mysql/data/ca-key.pem: Permission denied

数据传输后, 在远端进行批量md5sum重新校验

md5sum -c data-md5sum.txt    

操作实录

源机器操作

  • 停用所有运行应用
docker-compose down
  • 批量生成md5文件
ubuntu@VM-0-15-ubuntu:~$ sudo find /data -type f -print0 | sudo  xargs -0 md5sum > data-md5sum.txt
ubuntu@VM-0-15-ubuntu:~$ wc -l data-md5sum.txt
51487 data-md5sum.txt
  • rsync传送md5数据文件
ubuntu@VM-0-15-ubuntu:~$  rsync -avzcP  /home/ubuntu/data-md5sum.txt   root@124.156.00.00:/abc 
sending incremental file list
data-md5sum.txt
5,715,421 100% 33.25MB/s 0:00:00 (xfr#1, to-chk=0/1)

sent 1,504,968 bytes received 35 bytes 334,445.11 bytes/sec
total size is 5,715,421 speedup is 3.80
ubuntu@VM-0-15-ubuntu:~$ wc -l /home/ubuntu/data-md5sum.txt
51487 /home/ubuntu/data-md5sum.txt
  • 切换成root用户记录传送文件的原大小
ubuntu@VM-0-15-ubuntu:~$ su
Password:
root@VM-0-15-ubuntu:/home/ubuntu# du -sc /data/
4384664 /data/
4384664 total
  • rsync传送主体文件

一开始目的端使用ubuntu用户, 还是有一堆问题.

sudo rsync -avzc /data ubuntu@124.156.239.83:/data

全部使用root账号操作, 世界简单了好多.

sudo rsync -avzcP  /data root@124.156.239.83:/data

传输过程中进度条信息

data/wordpress/html/wp-includes/sodium_compat/namespaced/Core/Curve25519/Ge/Cached.php                                                                                                              
124 100% 1.48kB/s 0:00:00 (xfr#51397, to-chk=115/61428)
data/wordpress/html/wp-includes/sodium_compat/namespaced/Core/Curve25519/Ge/P1p1.php
120 100% 1.43kB/s 0:00:00 (xfr#51398, to-chk=114/61428)
data/wordpress/html/wp-includes/sodium_compat/namespaced/Core/Curve25519/Ge/P2.php
116 100% 1.38kB/s 0:00:00 (xfr#51399, to-chk=113/61428)

远程机器操作

  • 远程机器批量校验md5
root@VM-0-4-ubuntu:/abc# head data-md5sum.txt 
0536b1e585371384e682d77561d5a0f1 /data/geedeploy/fresh.sh
5c9df3d6e849f0fcee7112e179273b33 /data/geedeploy/gitea/.env
ebb42ed97a2360476fd0121e1fd0d4f0 /data/geedeploy/gitea/docker-compose.yml
86c67616c3b37c0fd98b52ff8f4f01b9 /data/geedeploy/mysql/.env
a21a9a837a102d81849e18e9d285d98a /data/geedeploy/mysql/docker-compose.yml
28e21ee67f3a0d2cd04bc563bb24306c /data/geedeploy/mysql/init-sql.sql
b32bfc8d419e3e227ae0710f033ead3a /data/geedeploy/README.md
c73dd5e2458b649ac1eda0a5c1a70ea7 /data/geedeploy/wordpress/wordpress.log
3762dfb8539221499d0b3b7d0a51475f /data/geedeploy/wordpress/.env
b349f948bbbcdc2649efb2c0f28012b6 /data/geedeploy/wordpress/php.ini
root@VM-0-4-ubuntu:/abc# md5sum -c data-md5sum.txt                                         
/data/geedeploy/fresh.sh: OK
/data/geedeploy/gitea/.env: OK
/data/geedeploy/gitea/docker-compose.yml: OK
/data/geedeploy/mysql/.env: OK
/data/geedeploy/mysql/docker-compose.yml: OK
/data/geedeploy/mysql/init-sql.sql: OK
/data/geedeploy/README.md: OK
/data/geedeploy/wordpress/wordpress.log: OK
/data/geedeploy/wordpress/.env: OK
/data/geedeploy/wordpress/php.ini: OK
/data/geedeploy/wordpress/docker-compose.yml: OK
/data/geedeploy/wordpress/php-www.conf: OK
...

查看是否有非ok的字段, 并没有.

root@VM-0-4-ubuntu:/abc# md5sum -c data-md5sum.txt  > data-md5sum.check
root@VM-0-4-ubuntu:/abc# wc -l data-md5sum.txt
51487 data-md5sum.txt
root@VM-0-4-ubuntu:/abc# grep -iv ok data-md5sum.check
root@VM-0-4-ubuntu:/abc# grep -i ok data-md5sum.check | wc -l
51487
  • 目标端检查文件夹大小

在传送完成后, 与源端对比发现还是差了几byte (4384664 vs 4384488), 但是md5sum是没有问题的, 不知道是什么问题, 可能操作系统版本不一致导致的?

du -sc /data
4384488 /data
4384488 total
  • 安心启动应用, 配置dns地址

检查进程和文件夹属性, 没有问题.

ps: docker容器的用户如果指定了uid环境变量的话, 需要检查在不同操作系统uid是否仍然是同一个用户, 与文件夹的属性是否一致.

杂七杂八

ubuntu修改root账号密码

先为ubuntu修改root账号,然后用root账号登录进行操作,对于文件夹权限等各种问题会顺利很多.

https://phoenixnap.com/kb/change-root-password-ubuntu

sudo passwd root

普通用户操作的话, 各种命令都会遇到用户权限问题.

ubuntu@VM-0-15-ubuntu:~$ du -sc /data/
du: cannot read directory '/data/gitea/data/ssh': Permission denied
du: cannot read directory '/data/mysql/data/geepack': Permission denied
du: cannot read directory '/data/mysql/data/mysql': Permission denied
du: cannot read directory '/data/mysql/data/sys': Permission denied
du: cannot read directory '/data/mysql/data/performance_schema': Permission denied
du: cannot read directory '/data/mysql/data/#innodb_redo': Permission denied
du: cannot read directory '/data/mysql/data/#innodb_temp': Permission denied
du: cannot read directory '/data/caddy/data/caddy/certificates': Permission denied
du: cannot read directory '/data/caddy/data/caddy/locks': Permission denied
du: cannot read directory '/data/caddy/data/caddy/acme': Permission denied
du: cannot read directory '/data/caddy/data/caddy/ocsp': Permission denied
du: cannot read directory '/data/caddy/caddy/data/caddy': Permission denied
du: cannot read directory '/data/caddy/caddy/caddy_config/caddy': Permission denied
du: cannot read directory '/data/cloudreve/uploads/1': Permission denied
du: cannot read directory '/data/cloudreve/uploads/u1': Permission denied

咨询chatgpt

linux bash脚本是典型的命令多, 参数多, 细节多, 大多数人也只能了解常见的命令和参数, 稍微复杂点的需求都得到处搜索语法, 或者找历史实现. 现在看来, chatgpt 对linux bash编程简直是降维打击, 对于有一定基础的程序员, 以后写bash脚本轻松太多了. 如果毫无基础, 那肯定还是不行, 不知道会不会一条命令下去所有数据都被删了.

picture 1

picture 2

picture 3

picture 4

picture 5

picture 7

picture 8