获取大型gziped文件的最后一行

ahy6op9u  于 2021-06-24  发布在  Mysql
关注(0)|答案(3)|浏览(314)

在数据库备份过程中,我生成一个文本转储文件。由于数据库很大,转储文件也很大,所以我用gzip压缩它。压缩是在生成转储时内联完成的(感谢unix管道!)。
在进程结束时,我通过查看最后一行来检查转储文件的有效性,并检查是否存在“dump completed”字符串。在我的脚本中,我将最后一行提取到一个变量中:

str=`zcat ${PATHSAVE}/dumpFull.sql.gz | tail -n1`

由于数据库转储文件很大(目前超过200gb),因此此结束进程检查需要花费大量时间(目前超过180分钟)。
我正在寻找一种方法来更快地提取我的.gz文件的最后一行。。。有人知道吗?
注1:对于explain context,我们可以说数据库是mysql community,备份工具是mysqldump,生成的dumpfile是全文文件。操作系统是centos。备份脚本是bash shell脚本。
注2:我知道percona xtrabackup,但在我的情况下,我想使用mysqldump来完成这个特定的备份任务。恢复的时间需求不是问题。

v1l68za4

v1l68za41#

这是fifo(管道)和 tee 命令。备份时使用此选项。

mkfifo mypipe
tail mypipe -1 > lastline.txt & mysqldump whatever | tee mypipe | gzip >dump.gz
rm mypipe

发生什么事? mkfifo mypipe 将fifo对象放入当前工作目录。它看起来像一个文件,您可以写入和读取,在同一时间。 tail mypipe -1 >lastline.txt 使用 tail 读你写的东西 mypipe 并将最后一行保存到文件中。 mysqldump whatever | tee mypipe | gzip >dump.gz 执行转储操作,并将输出传输到 tee 命令。tee将输出写入 mypipe 把它输送到 gzip .
这个 & 在命令的两个部分之间,使两个部分同时运行。 rm mypipe 清除fifo对象。
查尔斯·达菲指出 bash )使用进程替换,因此如果使用其中一个shell,您的命令会更简单。

mysqldump whatever | tee >(tail -1 > lastline.txt ) | gzip >dump.gz

在本例中,shell将为您创建自己的管道。
信用:管道输出到两个不同的命令

irlmq6kh

irlmq6kh2#

如果您真的想检查压缩文件的完整性,您可以从gz进行更改并执行以下操作


# strings used in order to clean up if it gets messy

dd if=dump.compressed.not-gz bs=1m skip=195000 | compress-tool -df | strings | grep 'Dump complete'

编辑:在压缩一个转储时,您还可以调试gz,在这个转储中您已经注入了“dumpcomplete”字符串并发现它的签名。数据库转储是相似的,所以可能在所有转储上都是相同的。如果是这样的话,只需像上面那样对它进行grep,但不使用compress和strings命令

xyhw6mcr

xyhw6mcr3#

通过使用现有的验证(使用 zcat 以及 tail )从stdin而不是从写入的文件中读取:

mysqldump args | gzip - | tee fullDump.gz | zcat - | tail -n1

这将为您提供最后处理的行,解压后,您可以对照 Dump completed 成功的字符串。
这是相当简单,但不是完全100%的防弹,因为有一个很小的机会,这是 tee 无法完成对磁盘的写入,但已完成对标准输出的写入:
如果对任何成功打开的文件操作数的写入失败,则对其他成功打开的文件操作数的写入和标准输出应继续,但退出状态应为非零。
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/tee.html
为了防止这种可能的故障,我们可以简单地对这个管道稍加修饰:

mysqldump args | gzip - | { tee foo.gz || echo "fail" | gzip -; } | zcat - | tail -n1

这样我们就可以 fail 作为最后一行 tee 退出非0。如果您使用bash作为shell,则可以交替使用 pipefail ( set -euxo pipefail ),这将导致此管道在任何命令失败(而不仅仅是最后一个命令)时退出非0。

相关问题