bashで、ツギハギツギハギで機能拡張しながら、お小遣い管理のショボイ仕組みを作ってます。
機能拡張した部分は、拡張前の部分から source される場合が多いのですが、エラーの取り扱いで錯乱したのでまとめました。
結論:source元がsourceした部分の処理結果に応じて次の動きを変えたいなら、(. ./file)が吉。
soruceされる側は exit N で自分の仕事がどうなったか、呼んだ側に伝えます。
呼んだ側は、$? を見て、それを知ります。
ある種の見本です。
main
#!/bin/bash
#
# main
# この人が棟梁。
# 下請けの仕事の状況に応じていろいろアゴで使う。
#
#
# child1 は元請けその1
#
(. ./child1)
case $? in
0) echo 'main knows that child1 got "a"' && exit ;;
1) echo 'main knows that child1 got "b"' && exit ;;
2) echo 'main knows that child1-1 worked' && exit ;;
3) echo 'main knows that child1-1 failed' && exit ;;
4) echo 'main knows that child1 gave up so sourcing child2'
#
# child1 がヘマこいたら child2 を駆り出す
#
(. ./child2) ;;
esac
#
# child2の出来栄えに応じてまたいろいろな。。
#
case $? in
0) echo 'main knows that child2 did the job' ;;
1) echo 'main knows that child2 failed' ;;
esac
child1
#
# child1
# 真っ先に駆り出される元請け
#
[[ $1 = 'a' ]] && echo 'child1 got "a"' && exit 0
[[ $1 = 'b' ]] && echo 'child1 got "b"' && exit 1
if [[ $1 = 'c' ]]; then
#
# 時としてさらに下請けに出したりする。
#
echo 'child1 sourcing child1-1'
(. './child1-1') && exit 2
exit 3
fi
echo "child1 cannot handle this arg \"$1\""
exit 4
child1-1
#
# child1の下請け=孫請け
#
[[ $2 = 'a' ]] && echo 'child1-1 can handle this' && exit 0
echo 'child1-1 cannot handle this'
exit 1
child2
#
# child1の仕事の出来栄え次第で駆り出される時がある人
#
[[ $1 = 'd' ]] && echo 'child 2 can handle this' && exit 0
echo 'child2 cannot handle this' && exit 1
以下の諸々はゴタクです。
カッコで括っても括らなくても変数は渡せる。
test_1
#!/bin/bash
a='AA'
. ./test_2
(. ./test_3)
test_2
echo "test_2 ${a}"
test_3
echo "test_3 ${a}"
実行結果
~/work$ ./test_1
test_2 AA
test_3 AA
~/work$
呼ばれた側での exit の効き目は?
test_1
#!/bin/bash
a='AA'
. ./test_2
(. ./test_3)
echo 'back in test_1'
test_2
echo "test_2 ${a}"
exit
test_3
echo "test_3 ${a}"
exit
実行結果
~/work$ ./test_1
test_2 AA
~/work$
カッコ付いてない呼び出しはexit効く。
test_1
#!/bin/bash
a='AA'
. ./test_2
(. ./test_3)
echo 'back in test_1'
test_2
echo "test_2 ${a}"
#exit ここ、コメントアウト
test_3
echo "test_3 ${a}"
exit
実行結果
~/work$ ./test_1
test_2 AA
test_3 AA
back in test_1
~/work$
カッコ付いてる呼び出しは exit 効かない。
カッコ付いてる呼び出しは本当に exit 効かないのか?
test_1
#!/bin/bash
a='AA'
. ./test_2 || echo 'test_2 failed'
(. ./test_3) || echo 'test_3 failed'
echo 'back in test_1'
test_2
echo "test_2 ${a}"
exit 1
test_3
echo "test_3 ${a}"
exit 1
実行結果(1)
~/work$ ./test_1
test_2 AA
~/work$
カッコなしで source すると、呼んだ側では呼ばれた側の終了コードを捉えられないけど、
実行結果(2)
~/work$ ./test_1 || echo 'test_1 failed'
test_2 AA
test_1 failed
~/work$
カッコなしで source すると、呼ばれた側の終了コードは呼び元の終了コードになる
#【結論】カッコつけて source すると、呼んだ側に終了コードを渡せる#
test_1
#!/bin/bash
a='AA'
. ./test_2 || echo 'test_2 failed'
(. ./test_3) || echo 'test_3 failed'
echo 'back in test_1'
test_2
echo "test_2 ${a}"
#exit 1 ここ、コメントアウト
test_3
echo "test_3 ${a}"
exit 1
実行結果(1)
~/work$ ./test_1
test_2 AA
test_3 AA
test_3 failed
back in test_1
~/work$
#【おまけ】カッコつけて source でなくて、コマンドとして呼んだら、そもそも変数が渡せない(コマンドの引数にしない限り、渡せない)#
test_1
#!/bin/bash
a='AA'
. ./test_2 || echo 'test_2 failed'
./test_3 || echo 'test_3 failed' # source じゃなくて外部コマンド
echo 'back in test_1'
test_2
echo "test_2 ${a}"
#exit 1 ここ、コメントアウト
test_3
#!/bin/bash
#↑外部コマンド
echo "test_3 ${a}"
exit 1
実行結果(1)
~/work$ ./test_1
test_2 AA
test_3
test_3 failed
back in test_1
~/work$