回答編集履歴

4

2020/02/24 19:56 ソースコードの再アップに伴いコメントも記載修正。

2020/02/24 10:59

投稿

gaccha
gaccha

スコア6

test CHANGED
@@ -22,30 +22,50 @@
22
22
 
23
23
 
24
24
 
25
- otn様より頂いた記法がシンプルかつ確実でしたので、使用させて頂きました。
25
+ ~~otn様より頂いた記法がシンプルかつ確実でしたので、使用させて頂きました。~~
26
-
27
-
28
-
26
+
27
+
28
+
29
- 個人的な思いとしては
29
+ ~~個人的な思いとしては
30
30
 
31
31
  ・エラーならとりあえずcatchして独自エラーを吐き、処理をメインに戻す。
32
32
 
33
- ・継続させたい場合もあるので、終了処理はメイン処理の中で判断して記載する。
33
+ ・継続させたい場合もあるので、終了処理はメイン処理の中で判断して記載する。~~
34
-
34
+
35
- ・なるべくメインシェルには共通関数導入による記法制限をかけたくない。
35
+ ~~・なるべくメインシェルには共通関数導入による記法制限をかけたくない。
36
36
 
37
37
  というところがありまして、出来れば「set -E」はつけたくない思いがありました。
38
38
 
39
-
39
+ ~~
40
-
40
+
41
- エラーでも継続させたい場合は「||」で繋げて独自エラー関数を呼び出すような仕組みにしてみました。(これが制約となってしまいましたが・・・)
41
+ ~~エラーでも継続させたい場合は「||」で繋げて独自エラー関数を呼び出すような仕組みにしてみました。(これが制約となってしまいましたが・・・)
42
+
42
-
43
+ ~~
44
+
45
+
46
+
43
-
47
+ 2020/02/24 19:56 : 記載修正、シェル再アップ
48
+
49
+ otn様とやりとりを重ねた結果、当初と実装手法がことなりましたので最終版をアップしました。
44
50
 
45
51
  とても助かりました!ありがとうございました!
46
52
 
47
53
 
48
54
 
55
+ ・「set -E」でサブシェル内の処理までERRトラップが行われる。
56
+
57
+  ※「set -e」とは異なり、エラー終了はされない。
58
+
59
+ ・上記注釈記載により「||」による実装制約は解消。ただし、コマンドエラーの結果はcatch()で処理するようにしているため、実装処理では一律$RCでステータスコードを取る制約とする。
60
+
61
+ ・サブシェルでERRトラップした場合、親シェルでもう一度ERRトラップが走ってしまい、余計なメッセージが出力されてしまう為、catch()内で「サブシェル→親シェル」に戻ったかを判定する処理を実装。(サブシェルでセットした変数の値は親シェルに引き継がれない為、ファイルで管理)
62
+
63
+ ・パイプラインのエラーに対応する為、「set -o pipefail」を追加。
64
+
65
+ ・シェルを共通関数「cmn_func.sh」と実装シェル「main_shell.sh」に分離。
66
+
67
+
68
+
49
69
  **■ cmn_func.sh**
50
70
 
51
71
  ```ここに言語を入力

3

2020/02/24 19:45 サブシェル対応およびpipelineを想定した現時点のソースに再修正致しました。

2020/02/24 10:59

投稿

gaccha
gaccha

スコア6

test CHANGED
@@ -52,35 +52,79 @@
52
52
 
53
53
  #!/bin/bash
54
54
 
55
- set -ET
55
+ set -E -o pipefail
56
+
57
+
58
+
59
+ #### 初期化処理
60
+
61
+ RC=0
62
+
63
+ echo 0 > SUBSHELL
64
+
65
+
66
+
67
+ #### 処理開始メッセージ
68
+
69
+ Msg="============ Script(${BASH_SOURCE[1]}) be in started. =>=>=>=>"
70
+
71
+ echo -e ${Msg}
56
72
 
57
73
 
58
74
 
59
75
  #### 各種トラップおよび独自メッセージ定義
60
76
 
61
- trap 'catch $LINENO "${BASH_COMMAND}" ; kill $$' ERR
77
+ trap 'catch "${BASH_COMMAND}"' ERR
62
78
 
63
79
  function catch(){
64
80
 
65
81
  RC=(${PIPESTATUS[@]})
66
82
 
83
+
84
+
85
+ ## サブシェル対応(現時点が親シェルの場合、サブシェルから復帰しているか確認)
86
+
87
+ if [ $BASH_SUBSHELL -eq 0 -a `cat SUBSHELL` -ne 0 ] ; then
88
+
89
+ echo $BASH_SUBSHELL > SUBSHELL
90
+
67
- A_LineNo=$1
91
+ return 0
92
+
68
-
93
+ fi
94
+
95
+
96
+
69
- A_SrcCode=$2
97
+ A_SrcCode=$1
98
+
99
+ L_LineNo=$BASH_LINENO
70
100
 
71
101
  L_ExecCMD=`eval "echo $A_SrcCode"`
72
102
 
103
+ Msg=
104
+
73
- Msg=">>>> Script Error Occurred! ($0): \n\
105
+ Msg+=">>>> Script Error Occurred! ($0:$$): \n"
74
-
106
+
75
- SorceFile: ${BASH_SOURCE[1]} \n\
107
+ Msg+="SorceFile: ${BASH_SOURCE[1]} \n"
76
-
108
+
77
- LineNo(${FUNCNAME[1]}): $A_LineNo \n\
109
+ Msg+="LineNo(${FUNCNAME[1]}): $L_LineNo \n"
110
+
78
-
111
+ if [ ${#RC[@]} -eq 1 ] ; then
112
+
79
- Sorce_Code: $A_SrcCode \n\
113
+ Msg+="Sorce_Code: $A_SrcCode \n"
80
-
114
+
81
- Execute_CMD: $L_ExecCMD \n\
115
+ Msg+="Execute_CMD: $L_ExecCMD \n"
116
+
82
-
117
+ else
118
+
119
+ Msg+="Sorce_Code: $A_SrcCode ( Pipeline be in used. Please check one lines. ) \n"
120
+
121
+ Msg+="Execute_CMD: $L_ExecCMD ( Pipeline be in used. Please check one lines. ) \n"
122
+
123
+ fi
124
+
125
+ Msg+="Sub_Shell: $BASH_SUBSHELL \n"
126
+
83
- Exited with status: ${RC[@]}."
127
+ Msg+="Exited with status: ${RC[@]}."
84
128
 
85
129
  echo -e ${Msg}
86
130
 
@@ -88,21 +132,35 @@
88
132
 
89
133
 
90
134
 
135
+ ## サブシェル対応(判定処理の為に、現在のサブシェル状態をファイルへ書き込み)
136
+
137
+ if [ $BASH_SUBSHELL -ne 0 ] ; then
138
+
139
+ echo $BASH_SUBSHELL > SUBSHELL
140
+
141
+ fi
142
+
143
+
144
+
91
145
  }
92
146
 
93
147
 
94
148
 
149
+ #### 終了処理
150
+
95
- trap 'echo FINALLY' EXIT
151
+ trap finary EXIT
96
-
97
-
98
-
99
- #### エラー時も続行させる際の独自メッセージ定義
152
+
100
-
101
- function Warn(){
153
+ function finary(){
154
+
102
-
155
+ Msg=
156
+
103
- RC=(${PIPESTATUS[@]})
157
+ Msg="=>=>=>=>=>=> Script(${BASH_SOURCE[1]}) finished. ============="
104
-
158
+
105
- echo $1
159
+ echo -e ${Msg}
160
+
161
+
162
+
163
+ rm SUBSHELL
106
164
 
107
165
  }
108
166
 
@@ -128,61 +186,65 @@
128
186
 
129
187
  ## 事前処理
130
188
 
131
- echo pre
189
+ echo -e "pre \n"
132
190
 
133
191
  A_dir=$1
134
192
 
135
193
 
136
194
 
137
- ## エラーで落とす場合はコマンド記載のみ
138
-
139
- ls $A_dir ; cd $A_dir
140
-
141
- #tar cvf - -C $A_dir | tar xvf $A_dir
142
-
143
-
144
-
145
- ## エラーで落とす場合はコマンド記載のみ(サブシェル版)
146
-
147
- #(ls $A_dir ; cd $A_dir)
148
-
149
-
150
-
151
- ## エラー時も継続させる場合は「||」で繋げてWarn関数を呼び出す
152
-
153
- #ls $A_dir || Warn "続行"
154
-
155
- #cd $A_dir || Warn "続行"
156
-
157
-
158
-
159
- ## エラー時も継続させる場合の判定処理
160
-
161
- #tar cvf - -C $A_dir | tar xvf $A_dir || Warn "続行"
162
-
163
- #if [ ${RC[0]} -ne 0 ] ; then
164
-
165
- # echo "リターンコードに応じた例外処理"
166
-
167
- #fi
168
-
169
-
170
-
171
- ## エラー時も継続させる場合は「||」で繋げてWarn関数を呼び出す(サブシェル版)
172
-
173
- #(ls $A_dir ; cd $A_dir) || Warn "続行"
174
-
175
- #if [ ${RC} -ne 0 ] ; then
176
-
177
- # echo "リターンコードに応じた例外処理"
178
-
179
- #fi
180
-
181
-
182
-
183
-
184
-
185
- echo post
195
+ ## サブシェルコマンド
196
+
197
+ (ls -d $A_dir ; cd $A_dir)
198
+
199
+
200
+
201
+ ## 判定を入れて例外処理や終了処理を入れる(サブシェル)
202
+
203
+ if [ $RC -ne 0 ] ; then
204
+
205
+ echo -e "サブシェル版例外処理\n"
206
+
207
+ # exit 10
208
+
209
+ fi
210
+
211
+
212
+
213
+ ## 親シェルコマンド
214
+
215
+ ls -d $A_dir ; cd $A_dir
216
+
217
+ #ls -d ${A_dir} | xargs -I {} echo "Current Directory is {}." # パイプラインエラーテスト X | 0
218
+
219
+ #echo "test" | xargs ls -d # パイプラインエラーテスト 0 | X
220
+
221
+ #ls -d ${A_dir} | xargs cd # パイプラインエラーテスト X | X
222
+
223
+
224
+
225
+ ## 判定を入れて例外処理や終了処理を入れる(親シェル)
226
+
227
+ total=0
228
+
229
+ for val in ${RC[@]} ; do
230
+
231
+ total=$((val + total))
232
+
233
+ done
234
+
235
+ RC=$total
236
+
237
+ if [ $RC -ne 0 ] ; then
238
+
239
+ echo -e "親シェル版例外処理\n"
240
+
241
+ # exit 10
242
+
243
+ fi
244
+
245
+
246
+
247
+ echo -e "post \n"
186
248
 
187
249
 
188
250
 

2

2020/02/23 21:11 otn様より頂いた質問に回答する為、現時点のソースに再修正致しました。

2020/02/24 10:27

投稿

gaccha
gaccha

スコア6

test CHANGED
@@ -46,6 +46,8 @@
46
46
 
47
47
 
48
48
 
49
+ **■ cmn_func.sh**
50
+
49
51
  ```ここに言語を入力
50
52
 
51
53
  #!/bin/bash
@@ -60,13 +62,35 @@
60
62
 
61
63
  function catch(){
62
64
 
65
+ RC=(${PIPESTATUS[@]})
66
+
63
67
  A_LineNo=$1
64
68
 
65
69
  A_SrcCode=$2
66
70
 
71
+ L_ExecCMD=`eval "echo $A_SrcCode"`
72
+
67
- echo "Error line:$A_LineNo sorce_code:\"$A_SrcCode\" exited with status $?."
73
+ Msg=">>>> Script Error Occurred! ($0): \n\
74
+
75
+ SorceFile: ${BASH_SOURCE[1]} \n\
76
+
77
+ LineNo(${FUNCNAME[1]}): $A_LineNo \n\
78
+
79
+ Sorce_Code: $A_SrcCode \n\
80
+
81
+ Execute_CMD: $L_ExecCMD \n\
82
+
83
+ Exited with status: ${RC[@]}."
84
+
85
+ echo -e ${Msg}
86
+
87
+ echo
88
+
89
+
68
90
 
69
91
  }
92
+
93
+
70
94
 
71
95
  trap 'echo FINALLY' EXIT
72
96
 
@@ -74,17 +98,35 @@
74
98
 
75
99
  #### エラー時も続行させる際の独自メッセージ定義
76
100
 
77
- function LogMsg(){
101
+ function Warn(){
78
102
 
79
- true
103
+ RC=(${PIPESTATUS[@]})
80
104
 
81
105
  echo $1
82
106
 
83
107
  }
84
108
 
109
+ ```
110
+
111
+
112
+
113
+ **■ main_shell.sh**
114
+
115
+ ```ここに言語を入力
116
+
117
+ #!/bin/bssh
118
+
119
+
120
+
121
+ #### 共通関数読み込み
122
+
123
+ . ./cmn_func.sh
124
+
85
125
 
86
126
 
87
127
  #### メイン
128
+
129
+ ## 事前処理
88
130
 
89
131
  echo pre
90
132
 
@@ -96,6 +138,8 @@
96
138
 
97
139
  ls $A_dir ; cd $A_dir
98
140
 
141
+ #tar cvf - -C $A_dir | tar xvf $A_dir
142
+
99
143
 
100
144
 
101
145
  ## エラーで落とす場合はコマンド記載のみ(サブシェル版)
@@ -104,17 +148,35 @@
104
148
 
105
149
 
106
150
 
107
- ## エラー時も継続させる場合は「||」で繋げてLogMsg関数を呼び出す
151
+ ## エラー時も継続させる場合は「||」で繋げてWarn関数を呼び出す
108
152
 
109
- #ls $A_dir || LogMsg "続行"
153
+ #ls $A_dir || Warn "続行"
110
154
 
111
- #cd $A_dir || LogMsg "続行"
155
+ #cd $A_dir || Warn "続行"
112
156
 
113
157
 
114
158
 
115
- ## エラー時も継続させる場合は「||」で繋げてLogMsg関数を呼び出す(サブシェル版)
159
+ ## エラー時も継続させる場合の判定処理
116
160
 
161
+ #tar cvf - -C $A_dir | tar xvf $A_dir || Warn "続行"
162
+
163
+ #if [ ${RC[0]} -ne 0 ] ; then
164
+
165
+ # echo "リターンコードに応じた例外処理"
166
+
167
+ #fi
168
+
169
+
170
+
171
+ ## エラー時も継続させる場合は「||」で繋げてWarn関数を呼び出す(サブシェル版)
172
+
117
- #(ls $A_dir ; cd $A_dir) || LogMsg "続行"
173
+ #(ls $A_dir ; cd $A_dir) || Warn "続行"
174
+
175
+ #if [ ${RC} -ne 0 ] ; then
176
+
177
+ # echo "リターンコードに応じた例外処理"
178
+
179
+ #fi
118
180
 
119
181
 
120
182
 

1

otn様より頂いた回答を元にソースを再修正致しました。

2020/02/23 12:17

投稿

gaccha
gaccha

スコア6

test CHANGED
@@ -1,126 +1,122 @@
1
- 上記修正の上、色々と検証した結果、変数のスコープが問題のようでした。
1
+ ~~上記修正の上、色々と検証した結果、変数のスコープが問題のようでした。~~
2
2
 
3
3
 
4
4
 
5
- ・サブシェル実行時には以下の通りとなります
5
+ ~~・サブシェル実行時には以下の通りとなります~~
6
6
 
7
- A_SrcCode='cd $A_dir'
7
+ ~~A_SrcCode='cd $A_dir'~~
8
8
 
9
9
 
10
10
 
11
- ・しかし、親に処理が戻るとサブシェルが設定した値は破棄される為、前回実行したコマンドの結果が残っています。
11
+ ~~・しかし、親に処理が戻るとサブシェルが設定した値は破棄される為、前回実行したコマンドの結果が残っています。~~
12
12
 
13
- A_SrcCode='echo 'no sach directory.'
13
+ ~~A_SrcCode='echo 'no sach directory.'~~
14
14
 
15
15
 
16
16
 
17
17
 
18
18
 
19
- 仕方がないので一旦ファイルに変数の値を吐き出してゴニョゴニョすることとしました。
19
+ ~~仕方がないので一旦ファイルに変数の値を吐き出してゴニョゴニョすることとしました。~~
20
20
 
21
- より良い方法があればご教示頂けると幸いです。
21
+ ~~より良い方法があればご教示頂けると幸いです。~~
22
+
23
+
24
+
25
+ otn様より頂いた記法がシンプルかつ確実でしたので、使用させて頂きました。
26
+
27
+
28
+
29
+ 個人的な思いとしては
30
+
31
+ ・エラーならとりあえずcatchして独自エラーを吐き、処理をメインに戻す。
32
+
33
+ ・継続させたい場合もあるので、終了処理はメイン処理の中で判断して記載する。
34
+
35
+ ・なるべくメインシェルには共通関数導入による記法制限をかけたくない。
36
+
37
+ というところがありまして、出来れば「set -E」はつけたくない思いがありました。
38
+
39
+
40
+
41
+ エラーでも継続させたい場合は「||」で繋げて独自エラー関数を呼び出すような仕組みにしてみました。(これが制約となってしまいましたが・・・)
42
+
43
+
44
+
45
+ とても助かりました!ありがとうございました!
22
46
 
23
47
 
24
48
 
25
49
  ```ここに言語を入力
26
50
 
27
- #!/bin/bssh
51
+ #!/bin/bash
52
+
53
+ set -ET
28
54
 
29
55
 
30
56
 
57
+ #### 各種トラップおよび独自メッセージ定義
58
+
59
+ trap 'catch $LINENO "${BASH_COMMAND}" ; kill $$' ERR
60
+
61
+ function catch(){
62
+
31
- set -T
63
+ A_LineNo=$1
64
+
65
+ A_SrcCode=$2
66
+
67
+ echo "Error line:$A_LineNo sorce_code:\"$A_SrcCode\" exited with status $?."
68
+
69
+ }
70
+
71
+ trap 'echo FINALLY' EXIT
32
72
 
33
73
 
34
74
 
35
- #### 初期化
75
+ #### エラー時も続行させる際の独自メッセージ定義
36
76
 
37
- sub_flg=0
77
+ function LogMsg(){
38
78
 
39
- :>LineNo
79
+ true
40
80
 
41
- :>SrcCode
42
-
43
- echo 0 > SubShell
44
-
45
-
46
-
47
- #### 各種トラップ
48
-
49
- trap catch ERR
50
-
51
- trap finally EXIT
52
-
53
- function catch() {
54
-
55
- errcode=$?
56
-
57
- A_LineNo=`cat LineNo`
58
-
59
- A_SrcCode=`cat SrcCode`
60
-
61
- echo "error line:$A_LineNo sorce_code:\"$A_SrcCode\" exited with status $errcode."
62
-
63
- exit 8
64
-
65
- }
66
-
67
- function finally() {
68
-
69
- echo FINALLY
81
+ echo $1
70
82
 
71
83
  }
72
84
 
73
85
 
74
86
 
75
- trap 'trace $LINENO "${BASH_COMMAND}"' DEBUG
87
+ #### メイン
76
88
 
77
- function trace() {
89
+ echo pre
78
90
 
79
- if [ $? -ne 0 ] ; then return ; fi
80
-
81
- if [ ${FUNCNAME[1]} == "catch" ] ; then return ; fi
82
-
83
- if [ `cat SubShell` -ne 0 -a $BASH_SUBSHELL -eq 0 ] ; then
84
-
85
- echo $BASH_SUBSHELL > flg
86
-
87
- return
91
+ A_dir=$1
88
-
89
- fi
90
92
 
91
93
 
92
94
 
93
- A_LineNo=$1
95
+ ## エラーで落とす場合はコマンド記載のみ
94
96
 
95
- A_SrcCode=$2
96
-
97
- echo $A_LineNo > LineNo
97
+ ls $A_dir ; cd $A_dir
98
-
99
- echo "${A_SrcCode}" > SrcCode
100
-
101
- echo ${BASH_SUBSHELL} > SubShell
102
-
103
- }
104
98
 
105
99
 
106
100
 
107
- ##### メイ
101
+ ## エラーで落とす場合はコマド記載のみ(サブシェル版)
108
102
 
109
- echo pre
103
+ #(ls $A_dir ; cd $A_dir)
110
104
 
111
105
 
112
106
 
113
- A_dir=$1
107
+ ## エラー時も継続させる場合は「||」で繋げてLogMsg関数を呼び出す
114
108
 
115
- if [ ! -d $A_dir ] ; then
109
+ #ls $A_dir || LogMsg "続行"
116
110
 
117
- echo "no sach directory."
111
+ #cd $A_dir || LogMsg "続行"
118
-
119
- fi
120
112
 
121
113
 
122
114
 
115
+ ## エラー時も継続させる場合は「||」で繋げてLogMsg関数を呼び出す(サブシェル版)
116
+
123
- cd $A_dir
117
+ #(ls $A_dir ; cd $A_dir) || LogMsg "続行"
118
+
119
+
124
120
 
125
121
 
126
122