2012-03-14

Bash: builtin command `local' returns status

成功したら何も出さないけど、失敗したらエラー内容を出力して終わりたい、ということがある。

test1.sh:

#!/bin/bash

compute() {
    $((3 / 0))
}

echo -n 'computing ... '
out=$(compute 2>&1)
ret=$?
if [ $ret -eq 0 ] ; then
    echo '[OK]'
else
    echo '[NG]'
    echo "$out"
fi
exit $ret

これは意図通りに動く。

$ bash test1.sh
computing ... [NG]
test1.sh: line 4: 3 / 0: division by 0 (error token is "0")

しかし Bash を使っていて local を使わないなんて あり得ない ので、

test2.sh:

#!/bin/bash

compute() {
    $((3 / 0))
}

main() {
    echo -n 'computing ... '
    local out=$(compute 2>&1)
    local ret=$?
    if [ $ret -eq 0 ] ; then
	echo '[OK]'
    else
	echo '[NG]'
	echo "$out"
    fi
    return $ret
}

main
$ bash test2.sh
computing ... [OK]

はい、動かなくなったー。何で!?

長い間この理由が分からなくて、挙句 Bash のバグじゃねーの?と疑ったこともあったが、ずっと後になって謎が解けた。

local が実行結果を返すなんて知らなかったよ・・・。 orz

local は関数内で使われる限り失敗しないので、「local out=$(...)」の結果は常に真になる。なので正しくはこう。

test3.sh:

#!/bin/bash

compute() {
    $((3 / 0))
}

main() {
    echo -n 'computing ... '
    local out
    out=$(compute 2>&1)
    local ret=$?
    if [ $ret -eq 0 ] ; then
	echo '[OK]'
    else
	echo '[NG]'
	echo "$out"
    fi
    return $ret
}

main
$ bash test3.sh
computing ... [NG]
test3.sh: line 4: 3 / 0: division by 0 (error token is "0")

もう Bash さん、疑ったりして本当にすみません。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。