如何编写一个返回是否发生错误的shell函数?

时间:2014-01-10 23:32:13

标签: linux bash shell

我的脚本下面该函数询问您是否要安装node.js.我知道我可以使用$?检查上一个命令的成功。但现在我有了这个node()功能。如何有效地检查shell函数中的任何地方是否发生错误?

node () {
    apt-get -y install python g++ make checkinstall
    mkdir ~/src && cd $_
    wget -N http://nodejs.org/dist/node-latest.tar.gz
    tar xzvf node-latest.tar.gz && cd node-v*
    ./configure
    checkinstall -y --install=no --pkgversion 0.10.24 # Replace with current version number.
    dpkg -i node_*
    cd ~
    rm -r ~/src
    # If an error occured anywhere in this function,
    # an error value should be returned so that the if-clause below fails,
    # for to exit the whole script
}

read -p "[q] Install node.js? [y/n] "
if [ $REPLY = "y" ]; then
    echo "[x] node script"
    node > /dev/null # This should 'get' the error so that ...
else
    echo "[s] Skipping installation of node.js"
fi
if [ $? -gt 0 ]; then echo "[e] An error occured"; exit 1; fi # ... it is caught here

echo "[f] Finished successfully"

exit 0

3 个答案:

答案 0 :(得分:1)

node () {
    code=0
    apt-get -y install python g++ make checkinstall  || ((code +=1))
    mkdir ~/src && cd $_ || ((code+=4)
    wget -N http://nodejs.org/dist/node-latest.tar.gz  || ((code+=8))
    tar xzvf node-latest.tar.gz && cd node-v* || ((code+=16))
    ./configure  || ((code++32))
    checkinstall -y --install=no --pkgversion 0.10.24 || ((code+=64))
    dpkg -i node_*  || (code+=128))
    cd ~  || ((code+=256))
    rm -r ~/src || ((code+=512))
    return "$code"
}

如果node返回错误代码,则可以使用shell的按位比较运算符来确定哪一行失败。例如,要测试wget行是否失败:

node
code=$?
(( $code & 8 )) && echo "wget failed in node"

如果您想知道哪一行失败而没有执行任何后续行,请使用:

node () {
    apt-get -y install python g++ make checkinstall  || return 1
    mkdir ~/src && cd $_ || return 2
    wget -N http://nodejs.org/dist/node-latest.tar.gz  || return 3
    tar xzvf node-latest.tar.gz && cd node-v* || return 4
    ./configure  || return 5
    checkinstall -y --install=no --pkgversion 0.10.24 || return 6
    dpkg -i node_*  || return 7
    cd ~  || return 8
    rm -r ~/src || return 9
}

答案 1 :(得分:0)

Bash有一个return语句,它将被调用者中$?的值设置为return中函数中指定的数值。例如:

function fun1(){
  return 2
}

fun1
echo "fun1 returned" $?

应输出

fun1 returned 2

答案 2 :(得分:0)

在您的情况下,如果其中一个命令失败,您肯定会想要停止,而不是仅仅运行它们并检查最后的状态。

您可以通过使用子shell和set -e模拟try-catch来实现此目的:

myfunction() {
  (  # Start subshell
    set -e # Exit on error
    cmd1
    cmd2
    cmd3
  ) 
  value=$?
  cleanup # any command to run regardless of status
  return $value
}

if myfunction
then
  echo "All commands executed successfully"
else
  echo "One of the commands failed, so execution was aborted"
fi

如果此子shell中有任何您不想中止的命令,则可以使用cmd || true,即使失败也会运行cmd并继续。