Shell管道与重定向原理解析及mysqldump errno 32错误调试
首先,先把完整的代码块放出来,咱们逐行拆解它的逻辑:
PULSE=$(mktemp -t shield-pipe.XXXXX) trap "rm -f ${PULSE}" QUIT TERM INT set -o pipefail mysqldump ... | tee >(tail -c1 >$PULSE) | bzip2 | s3 stream ...
一、代码逐行工作原理
创建临时文件:
PULSE=$(mktemp -t shield-pipe.XXXXX)
用mktemp生成一个唯一的临时文件,-t参数指定了文件名模板,最终会生成类似/tmp/shield-pipe.xyz78的路径,把这个路径存在PULSE变量里。这个临时文件用来做后续的“输出有效性检测”。清理临时文件的陷阱:
trap "rm -f ${PULSE}" QUIT TERM INT
设置信号捕获,当脚本收到QUIT(Ctrl+\)、TERM(系统终止信号)、INT(Ctrl+C)时,自动执行rm -f删除临时文件,避免备份中断后残留垃圾文件。开启管道失败检测:
set -o pipefail
默认情况下,Bash管道的返回值只看最后一个命令的状态,哪怕前面的命令失败了,只要最后一个命令成功,整个管道就会返回成功。开启pipefail后,只要管道里任意一个命令失败,整个管道的返回值就会是那个失败命令的退出码,这样就能准确判断整个备份流程是否真的成功了。核心备份管道流程:
mysqldump ... | tee >(tail -c1 >$PULSE) | bzip2 | s3 stream ...
这是一条串联的数据流管道,咱们从左到右看:mysqldump ...:执行MySQL导出命令,把数据库内容输出到标准输出。| tee >(tail -c1 >$PULSE):tee命令的作用是“分流”——它会把收到的输入同时发送到两个地方:一个是继续往后传给管道的下一个命令(bzip2),另一个是传给进程替换(>(...))里的命令。进程替换里的tail -c1会读取输入的最后1个字节,然后写入到$PULSE临时文件。这么做的目的是验证mysqldump是否有实际输出:如果备份成功,PULSE文件大小会是1字节;如果mysqldump没输出(比如导出失败),这个文件就是空的,后续脚本可以通过检查这个文件来判断备份有效性。| bzip2:把tee传过来的原始备份数据进行bzip2压缩,减少数据体积。| s3 stream ...:把压缩后的数据流通过s3 stream工具直接上传到对象存储,实现“流式备份”(不用先写本地磁盘再上传,节省空间)。
二、调试"Got errno 32 on write"错误
这个错误对应的是Linux系统的EPIPE(Broken pipe,管道断裂),意思是mysqldump往标准输出写数据的时候,管道后面的某个进程已经提前退出了,导致管道“断了”,mysqldump无法继续写数据。咱们一步步排查:
1. 先确认管道失败状态
因为开启了pipefail,执行备份命令后,用echo $?查看整个管道的返回码。如果返回非0,说明管道里某个环节确实失败了,接下来逐个排查。
2. 逐个隔离管道环节,定位问题点
单独测试mysqldump:先跳过后面的所有管道,直接把导出结果写到本地文件,看mysqldump本身是否正常:
mysqldump --your-actual-options-here > test-dump.sql如果这一步就报错,那问题出在mysqldump本身——比如数据库连接失败、权限不足、表损坏、磁盘空间不足(写test-dump.sql的时候)等,根据mysqldump的报错信息修复即可。
测试mysqldump + 压缩:如果mysqldump单独运行正常,再加上bzip2压缩:
mysqldump ... | bzip2 > test-dump.sql.bz2如果这里失败,可能是bzip2出问题(比如损坏),或者本地磁盘空间不足无法写入压缩文件。
测试mysqldump + tee + 压缩:加上
tee的进程替换部分,去掉s3 stream:mysqldump ... | tee >(tail -c1 >/tmp/test-pulse) | bzip2 > test-dump.sql.bz2执行完后检查
/tmp/test-pulse的大小(用ls -l /tmp/test-pulse),如果大小是1,说明前面的流程都正常,问题大概率出在s3 stream环节。单独测试s3 stream:验证上传工具是否能正常接收数据流:
echo "test backup data" | s3 stream --your-upload-options-here如果这一步失败,说明
s3 stream有问题——比如对象存储桶不存在、权限配置错误、网络连接中断、工具本身bug等,查看s3 stream的错误输出就能找到原因。
3. 增加日志输出,获取更多细节
把s3 stream的错误输出重定向到日志文件,方便排查:
mysqldump ... | tee >(tail -c1 >$PULSE) | bzip2 | s3 stream ... 2>> s3-upload-error.log
执行备份后查看s3-upload-error.log,里面会有上传过程中的具体错误信息,比如“权限不足”“连接超时”等。
4. 检查系统资源
有时候进程提前退出是因为系统资源不足:
- 用
dmesg命令查看是否有OOM Killer(内存不足时系统自动杀掉进程)的日志,如果有,说明备份时内存被占满,需要优化备份参数(比如分表导出)或者增加系统内存。 - 检查磁盘IO、CPU使用率,备份时如果资源被占满,可能导致某个进程超时退出。
内容的提问来源于stack exchange,提问作者Sybil

