shell 脚本:什么时候测试最后一个命令?
shell scripting : when to test on the last command?
我有这个导入 mongo 数据库的小 bash 脚本,通过 运行 一个 java 程序对其进行一些更改,最后导出修改后的数据库:
#!/bin/bash
credentials="-u xx -p yy"
#import database
ssh user@$viaDbHost <<EOF
scp user@$prodDumpHost:$prodDumpPath $viaDbWhitedumpTmpDir
mongorestore --drop --host localhost --db whitedb $credentials --gzip --archive=$viaDbWhitedumpTmpDir/db.gz
rm $viaDbWhitedumpTmpDir/db.gz
EOF
#run a java program
javacp=/appli/java/lib/*
java -cp "$javacp" xx.yy.zz.MyApplication
#export database
ssh user@$viaDbHost "mongodump --host localhost --db darkDb $credentials --gzip --archive=$darkdumpPath"
我想在发生错误时停止我的脚本并显示一条消息,所以我将 shell 更改为这个版本:
#!/bin/bash
credentials="-u xx -p yy"
#import database
ssh user@$viaDbHost <<EOF
scp user@$prodDumpHost:$prodDumpPath $viaDbWhitedumpTmpDir
if [ $? != 0 ]; then
echo "@@@@@ ------- xxxxx"
exit 1
fi
mongorestore --drop --host localhost --db whitedb $credentials --gzip --archive=$viaDbWhitedumpTmpDir/db.gz
if [ $? != 0 ]; then
echo "@@@@@ ------- yyyy"
exit 1
fi
rm $viaDbWhitedumpTmpDir/db.gz
if [ $? != 0 ]; then
echo "@@@@@ ------- zzzz"
exit 1
fi
EOF
#run a java program
javacp=/appli/java/lib/*
java -cp "$javacp" xx.yy.zz.MyApplication
if [ $? != 0 ]; then
echo "@@@@@ ------- blablabla"
exit 1
fi
#export database
ssh nf2@$viaDbHost "mongodump --host localhost --db darkDb $credentials --gzip --archive=$darkdumpPath"
if [ $? != 0 ]; then
echo "@@@@@ ------- blablabla 2"
exit 1
fi
exit 0
我觉得因为这些测试,我的脚本变丑了,行数变多了!
有没有办法提高这篇文章的写作水平?
或者只检测要测试的线路的方法?
首先,确保将错误消息发送到 stderr。你可以试试:
!/bin/bash
credentials='-u xx -p yy'
die() { printf "%s${1:+\n}" "$*"; exit 1; } >&2
try() { "$@" || die "FAILED: $*"; }
#import database
ssh user@$viaDbHost <<EOF || exit
scp user@$prodDumpHost:$prodDumpPath $viaDbWhitedumpTmpDir || { echo error >&2; exit 1; }
mongorestore --drop --host localhost --db whitedb $credentials --gzip --archive=$viaDbWhitedumpTmpDir/db.gz || { echo error >&2; exit 1; }
rm $viaDbWhitedumpTmpDir/db.gz || exit 1; # rm emits its own error message
EOF
#run a java program
javacp=/appli/java/lib/*
try java -cp "$javacp" xx.yy.zz.MyApplication
#export database
try ssh nf2@$viaDbHost "mongodump --host localhost --db darkDb $credentials --gzip --archive=$darkdumpPath"
exit 0
但老实说,对于此脚本,您可能甚至不需要费心发出任何错误消息。到处都做 cmd || exit 1
,让每个命令发出自己的错误。
您可以或多或少地通用地执行此操作,而不必单独检查每个命令。启用 -e
选项(这会导致 bash
在命令失败时退出)并使用 EXIT
陷阱来提供一些细节:
#! /bin/bash
set -e
at_exit()
{
local code=$?
local cmd=$BASH_COMMAND
if test $code -ne 0; then
echo "Command <$cmd> failed with status $code!" >&2
fi
exit $code
}
trap at_exit EXIT
# ... your script here ...
您可以将它们放在一个公共文件中(例如 exit-trap.sh
),然后 source
将其放入多个脚本中。
如果您不希望整个脚本在命令失败时退出,您可以在末尾添加|| :
:
# don't exit if this fails
dont_care_if_it_fails || :
我有这个导入 mongo 数据库的小 bash 脚本,通过 运行 一个 java 程序对其进行一些更改,最后导出修改后的数据库:
#!/bin/bash
credentials="-u xx -p yy"
#import database
ssh user@$viaDbHost <<EOF
scp user@$prodDumpHost:$prodDumpPath $viaDbWhitedumpTmpDir
mongorestore --drop --host localhost --db whitedb $credentials --gzip --archive=$viaDbWhitedumpTmpDir/db.gz
rm $viaDbWhitedumpTmpDir/db.gz
EOF
#run a java program
javacp=/appli/java/lib/*
java -cp "$javacp" xx.yy.zz.MyApplication
#export database
ssh user@$viaDbHost "mongodump --host localhost --db darkDb $credentials --gzip --archive=$darkdumpPath"
我想在发生错误时停止我的脚本并显示一条消息,所以我将 shell 更改为这个版本:
#!/bin/bash
credentials="-u xx -p yy"
#import database
ssh user@$viaDbHost <<EOF
scp user@$prodDumpHost:$prodDumpPath $viaDbWhitedumpTmpDir
if [ $? != 0 ]; then
echo "@@@@@ ------- xxxxx"
exit 1
fi
mongorestore --drop --host localhost --db whitedb $credentials --gzip --archive=$viaDbWhitedumpTmpDir/db.gz
if [ $? != 0 ]; then
echo "@@@@@ ------- yyyy"
exit 1
fi
rm $viaDbWhitedumpTmpDir/db.gz
if [ $? != 0 ]; then
echo "@@@@@ ------- zzzz"
exit 1
fi
EOF
#run a java program
javacp=/appli/java/lib/*
java -cp "$javacp" xx.yy.zz.MyApplication
if [ $? != 0 ]; then
echo "@@@@@ ------- blablabla"
exit 1
fi
#export database
ssh nf2@$viaDbHost "mongodump --host localhost --db darkDb $credentials --gzip --archive=$darkdumpPath"
if [ $? != 0 ]; then
echo "@@@@@ ------- blablabla 2"
exit 1
fi
exit 0
我觉得因为这些测试,我的脚本变丑了,行数变多了!
有没有办法提高这篇文章的写作水平?
或者只检测要测试的线路的方法?
首先,确保将错误消息发送到 stderr。你可以试试:
!/bin/bash
credentials='-u xx -p yy'
die() { printf "%s${1:+\n}" "$*"; exit 1; } >&2
try() { "$@" || die "FAILED: $*"; }
#import database
ssh user@$viaDbHost <<EOF || exit
scp user@$prodDumpHost:$prodDumpPath $viaDbWhitedumpTmpDir || { echo error >&2; exit 1; }
mongorestore --drop --host localhost --db whitedb $credentials --gzip --archive=$viaDbWhitedumpTmpDir/db.gz || { echo error >&2; exit 1; }
rm $viaDbWhitedumpTmpDir/db.gz || exit 1; # rm emits its own error message
EOF
#run a java program
javacp=/appli/java/lib/*
try java -cp "$javacp" xx.yy.zz.MyApplication
#export database
try ssh nf2@$viaDbHost "mongodump --host localhost --db darkDb $credentials --gzip --archive=$darkdumpPath"
exit 0
但老实说,对于此脚本,您可能甚至不需要费心发出任何错误消息。到处都做 cmd || exit 1
,让每个命令发出自己的错误。
您可以或多或少地通用地执行此操作,而不必单独检查每个命令。启用 -e
选项(这会导致 bash
在命令失败时退出)并使用 EXIT
陷阱来提供一些细节:
#! /bin/bash
set -e
at_exit()
{
local code=$?
local cmd=$BASH_COMMAND
if test $code -ne 0; then
echo "Command <$cmd> failed with status $code!" >&2
fi
exit $code
}
trap at_exit EXIT
# ... your script here ...
您可以将它们放在一个公共文件中(例如 exit-trap.sh
),然后 source
将其放入多个脚本中。
如果您不希望整个脚本在命令失败时退出,您可以在末尾添加|| :
:
# don't exit if this fails
dont_care_if_it_fails || :