当且仅当 mysqldump 不产生任何错误时,我想压缩 sql 转储。我尝试输入错误的密码,但它仍然执行 gzip。
mysqldump -u username -ppassword dbname |& if [ $? == 0 ]; then gzip > test.gz; else echo "error"; fi
我的命令有什么问题或者有更好的解决方案吗?
答案1
我认为你可以删除|&
(原因是你不需要将 stdout 或 stderr 通过管道传输到下一个条件,如果有的话,你可以使用 ';' 作为命令分隔符)。像这样的东西可能应该有效:
#!/bin/bash
mysqldump -u myuser -p mypasswd > mydb.dump
if [[ $? -eq 0 ]]; then
gzip mydb.dump
else
echo >&2 "DB backup failed"
exit 1
fi
编辑:要检查 gzip 是否成功,您可以执行以下操作:
mysqldump -u myuser -p mypasswd | gzip > mydb.dump.gz && echo "success" || echo "failure"
然而,即使mysqldump
失败,即如果备份因除 gzip 填充磁盘之外的大多数原因而失败,这也会报告成功。
答案2
你也可以
mysqldump -someparams dump.sql && gzip dump.sql || echo "Backup failed"
或者
mysqldump -someparams dump.sql
[[ $? == 0 ]] && gzip dump.sql || echo "Backup failed "
答案3
管道并行执行两侧。您尝试执行此操作的方式在概念上是不可能的:mysqldump
如果您与 的执行并行执行此测试,则在命令完成之前您无法测试命令的状态mysqldump
。您需要运行mysqldump
,等待它完成,然后然后决定是否跑步gzip
。
由于mysqldump
必须完成运行,因此它的输出必须到达某个地方。大概您希望输出很大,因为您正在压缩它。因此,明智的选择是对其进行压缩。因此无条件压缩输出。
mysqldump -u username -ppassword dbname | gzip > test.gz
注意,我用的是|
,而不是|&
。在这里使用|&
是没有意义的:如果有任何错误消息,它们最终会与转储混合在一起,并且不可能恢复转储。
尚待解决的问题是检测是否mysqldump
成功。假设这是一个 bash 或 ksh 脚本(即它以#!/bin/bash
or#!/bin/ksh
等开头,而不是以 开头#!/bin/sh
),设置pipefail
选项,以便管道在任何部分发生故障时也会发生故障。 (默认情况下,管道的状态是其最右边命令的状态,其他命令的状态将被忽略。)
#!/bin/bash
set -o pipefail -o errexit
tmp="mydump.tmp.$$.gz"
trap 'rm -f "$tmp"' ERR INT TERM HUP
mysqldump … | gzip >"$tmp"
mv "$tmp" mydump.gz
设置该errexit
选项可确保如果管道失败,则脚本会在该点退出(与管道具有相同的错误状态)。因此,mydump.gz
仅当转储成功时才会创建名为的文件。该trap
命令设置一个陷阱,以便如果脚本失败或被列出的信号之一终止,则临时文件将被删除。
答案4
如果您想避免使用临时文件,另一个解决方案是在出错时删除生成的文件:
( mysqldump ... || rm -f test.gz ) | gzip > test.gz
或者,如果您想要一个明确的标志,如下所示:
rm -f test.ok
( mysqldump ... && touch test.ok ) | gzip > test.gz
if [[ $? -eq 0 && -r test.ok ]]; then
echo it worked
else
echo something went wrong
fi