web-dev-qa-db-ja.com

終了コードを返す方法は?エラー:戻り値:読み取り:数値引数が必要です

これが私のスクリプトの簡易版です。私の質問は、この場合、apt-getから終了コードを返すにはどうすればよいですか?

#!/bin/bash
install_auto() {
apt-get -h > /dev/null 2>&1
if [ $? -eq 0 ] ; then
    return $(Sudo apt-get install --assume-yes $@)
fi
return 1
}
echo "installing $@"
install_auto "$@"
echo $?
echo "finished"
exit 0

出力は次のとおりです。

./install_test.sh: line 5: return: Reading: numeric argument required

更新:私はうまくいくものを思いつきました:

return $(Sudo apt-get install --assume-yes "$@" >/dev/null 2>&1; echo $?)

それは良いアプローチですか?

7
MountainX

Bashのreturn()は数値引数のみを返すことができます。いずれの場合も、デフォルトでは、最後に実行されたコマンドの終了ステータスが返されます。したがって、本当に必要なのは次のとおりです。

#!/usr/bin/env bash
install_auto() {
apt-get -h > /dev/null 2>&1
if [ $? -eq 0 ] ; then
    Sudo apt-get install --assume-yes $@
fi
}

デフォルトでは関数は$?を返すため、返される値を明示的に設定する必要はありません。ただし、最初のaptコマンドが失敗し、ifループに入らなかった場合、これは機能しません。より堅牢にするために、これを使用します。

#!/usr/bin/env bash
install_auto() {
apt-get -h > /dev/null 2>&1
ret=$?
if [ $ret -eq 0 ] ; then
    ## If this is executed, the else is ignored and $? will be
    ## returned. Here, $?will be the exit status of this command
    Sudo apt-get install --assume-yes $@
else
    ## Else, return the exit value of the first apt-get
    return $ret
fi
}

一般的なルールは、関数が特定のジョブの終了ステータスを返すようにするためであり、必ずしも最後に実行したジョブではないため、終了ステータスを変数に保存して変数を返す必要があります。

function foo() {
    run_a_command arg1 arg2 argN
    ## Save the command's exit status into a variable
    return_value= $?

    [the rest of the function  goes here]
    ## return the variable
    return $return_value
}

編集:実際には、@ gniourf_gniourfがコメントで指摘したように、&&を使用して全体を大幅に簡略化できます。

install_auto() {
  apt-get -h > /dev/null 2>&1 &&
  Sudo apt-get install --assume-yes $@
}

この関数の戻り値は次のいずれかになります。

  1. apt-get -hが失敗した場合、終了コードを返します
  2. apt-get -hが成功すると、Sudo apt-get installの終了コードが返されます。
7
terdon

完全を期すために、@ terdonと@gniourf_gniourfによって提案されたいくつかの変更を加えた実際の関数を次に示します。

install_auto() {
    if [ ! $# -gt 0 ] ; then
        echo "usage: $0 package_name [package_name ...]"
    fi 

    apt-get -h > /dev/null 2>&1
    if [ $? -eq 0 ] ; then
        if [ -f "$@" ] || [[ "$@" =~ '/' ]] ; then
            Sudo gdebi -n "$@"
            return $?
        else    
            Sudo apt-get install --assume-yes "$@"
            return $?
        fi
    fi

    zypper help > /dev/null 2>&1
    if [ $? -eq 0 ] ; then
            Sudo zypper --non-interactive --no-gpg-checks --quiet install --auto-agree-with-licenses "$@"
            return $?
    fi

    #may check other package managers in the future

    echo "ERROR: package manager not found"
    return 255
}

これ以上の提案に感謝します。

1
MountainX