0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

bash: ()で括って source していろんな部品を使う

Last updated at Posted at 2017-01-02

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$ 
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?