ネストされたループを持つシェルスクリプトがあり、「終了」が実際にスクリプトを終了せずに現在のループのみを終了することがわかりました。いくつかのエラー状況でスクリプトを完全に終了する他の方法はありますか?
許容可能なエラーがあり、あまりにも多くの書き換えが必要なので、「set -e」を使用したくありません。
今、私はプロセスを手動で終了するためにkillを使用していますが、これを行うより良い方法があるはずです。
ベストアンサー1
あなたの問題はネストされたループ自体ではありません。これは内部ループがある場所です。サブシェルで実行。
これは働きます:
#!/bin/bash
for i in $(seq 1 100); do
echo i $i
for j in $(seq 1 10) ; do
echo j $j
sleep 1
[[ $j = 3 ]] && { echo "I've had enough!" 1>&2; exit 1; }
done
echo "After the j loop."
done
echo "After all the loops."
出力:
i 1
j 1
j 2
j 3
I've had enough!
これにより、説明する問題が発生します。
#!/bin/bash
for i in $(seq 1 100); do
echo i $i
cat /etc/passwd | while read line; do
echo LINE $line
sleep 1
[[ "$line" = "daemon:x:2:2:daemon:/sbin:/sbin/nologin" ]] && { echo "I've had enough!" 1>&2; exit 1; }
done
echo "After the j loop."
done
echo "After all the loops."
出力:
i 1
LINE root:x:0:0:root:/root:/bin/bash
LINE bin:x:1:1:bin:/bin:/sbin/nologin
LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
After the j loop.
i 2
LINE root:x:0:0:root:/root:/bin/bash
LINE bin:x:1:1:bin:/bin:/sbin/nologin
LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
After the j loop.
i 3
LINE root:x:0:0:root:/root:/bin/bash
(...etc...)
解決策は次のとおりです。サブシェルで実行される内部ループの戻り値をテストする必要があります。
#!/bin/bash
for i in $(seq 1 100); do
echo i $i
cat /etc/passwd | while read line; do
echo LINE $line
sleep 1
[[ "$line" = "daemon:x:2:2:daemon:/sbin:/sbin/nologin" ]] && { echo "I've had enough!" 1>&2; exit 1; }
done
err=$?; [[ $err != 0 ]] && exit $err
echo "After the j loop."
done
echo "After all the loops."
テストに注意してください:[[ $? != 0 ]] && exit $?
出力:
i 1
LINE root:x:0:0:root:/root:/bin/bash
LINE bin:x:1:1:bin:/bin:/sbin/nologin
LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
編集:現在のシェルがどのサブシェルにあるかを確認するには、「応答」スクリプトを変更して、現在のシェルのプロセスIDが何であるかを教えてください。注:これはbash 4でのみ機能します。
#!/bin/bash
for i in $(seq 1 100); do
echo pid $BASHPID i $i
cat /etc/passwd | while read line; do
echo pid $BASHPID LINE $line
sleep 1
[[ "$line" = "daemon:x:2:2:daemon:/sbin:/sbin/nologin" ]] && { echo "I've had enough!" 1>&2; exit 1; }
done
err=$?; [[ $err != 0 ]] && echo pid $BASHPID && exit $err
echo "After the j loop."
done
echo "After all the loops."
出力:
pid 31793 i 1
pid 31796 LINE root:x:0:0:root:/root:/bin/bash
pid 31796 LINE bin:x:1:1:bin:/bin:/sbin/nologin
pid 31796 LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
pid 31793
変数「i」と「j」はFortranから提供されます。良い一日をお過ごしください。 :-)