0

好的,所以我是 bash 脚本的初学者,我知道这个问题的措辞可能有点尴尬,但我会尽可能清楚!

我编写了以下脚本来在文件夹中创建存储库的备份。脚本如下:

#!/bin/bash

SVNREPO="/var/svn"
TEMP="/var/tmp"
BACKUP="/home/helix/backups"

cd $SVNREPO

if [ $# -eq 0 ]; then
    for REPO in *; do
        ARRAY+=($REPO)
    done
else
    for REPO in $@; do
        ARRAY+=($REPO)
    done
fi

for REPO in ${ARRAY[@]}; do
    svnadmin dump $SVNREPO/$REPO -r HEAD | gzip > $TEMP/$REPO.svn.gzip sd
    cp $TEMP/$REPO.svn.gzip $BACKUP/$REPO.svn.gzip
    rm $TEMP/$REPO.svn.gzip 
done

当不带参数调用该脚本时,此脚本成功生成 'var/svn' 中所有存储库的 .gzip 备份,并创建称为参数的特定存储库的 .gzip 备份。伟大的!

但是,如果脚本使用与存在的存储库不对应的参数运行,则程序将崩溃并显示错误消息:svnadmin: E000002: Can't open file '/var/svn/ada/format': No such file or directory. 我想要实现的是捕捉这个错误并将更用户友好的输出打印到控制台。我一直在尝试使用“陷阱”来做到这一点。

首先,我添加了以下行:

trap 'echo ERROR! The repository or repositories that you are trying to backup do not exist!' ERR

...然后我在最后一个 for 循环中将错误推送到 /dev/null :

svnadmin dump $SVNREPO/$REPO -r HEAD 2>/dev/null | gzip > $TEMP/$REPO.svn.gzip

我在我所做的地方推送到 /dev/null 文件,因为这是程序出错的地方。但是,该脚本似乎不再起作用。我在这里做错了什么?与2>/dev/null在一行中间有问题吗?如果是这样,我该如何重构这段代码,使其不需要管道中间的管道?

非常感谢您的帮助,我希望我的问题相当清楚!为了确认,最终的非工作代码如下:

#!/bin/bash

SVNREPO="/var/svn"
TEMP="/var/tmp"
BACKUP="/home/helix/backups"

cd $SVNREPO

if [ $# -eq 0 ]; then
    for REPO in *; do
        ARRAY+=($REPO)
    done
else
    for REPO in $@; do
        ARRAY+=($REPO)
    done
fi

trap 'echo ERROR! The repository or repositories that you are trying to backup do not exist!' ERR

for REPO in ${ARRAY[@]}; do
    svnadmin dump $SVNREPO/$REPO -r HEAD 2>/dev/null | gzip > $TEMP/$REPO.svn.gzip sd
    cp $TEMP/$REPO.svn.gzip $BACKUP/$REPO.svn.gzip
    rm $TEMP/$REPO.svn.gzip 
done
4

2 回答 2

1

使用@cdarke 检查文件是否存在的建议,我现在可以使用以下代码:

#!/bin/bash

SVNREPO="/var/svn"
TEMP="/var/tmp"
BACKUP="/home/helix/backups"

cd $SVNREPO

if [ $# -eq 0 ]; then
    for REPO in *; do
        ARRAY+=($REPO)
    done
else
    for REPO in $@; do
        ARRAY+=($REPO)
    done
fi

for REPO in ${ARRAY[@]}; do
    if [ -f $SVNREPO/$REPO/format ]; then
        vnadmin dump $SVNREPO/$REPO -r HEAD 2>/dev/null | gzip > $TEMP/$REPO.svn.gzip
        cp $TEMP/$REPO.svn.gzip $BACKUP/$REPO.svn.gzip
        rm $TEMP/$REPO.svn.gzip 
    else
        echo ERROR! The repository $REPO does not exist. No backup has been made for this argument.
    fi
done
于 2017-02-21T17:17:04.940 回答
1

我不确切知道trap命令是如何工作的,但我会建议另一种可能以另一种方式解决您的问题的方法:

首先,在你的for循环之前,添加这一行:

set -o pipefail

这意味着当管道中的任何命令失败时,如果有任何失败,最后一个退出代码 ( $?) 将包含错误代码。

在您svnadmin致电后,我建议您添加以下内容:

if [ $? -ne 0 ]; then
    echo "ERROR! Received error code $? for repository '$REPO'."
    continue
fi

您当然可以根据自己的喜好更改错误消息。功能应该很清楚:如果svnadminbzip失败,它将打印一条错误消息并继续for循环中的下一项。

希望这可以帮助。

于 2017-02-21T16:55:11.820 回答