我的第一个bash脚本

时间:2017-02-21 16:45:25

标签: linux bash bash-trap dev-null

好的,所以我是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

2 个答案:

答案 0 :(得分:1)

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

首先,在for循环之前,添加以下行:

set -o pipefail

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

svnadmin来电后,我会建议添加:

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

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

希望这有帮助。

答案 1 :(得分: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