
このスクリプトは時々失敗し、時々成功します (非常に厄介な状況です)。
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{001..312}
latest_file="$(find $test_dir -type f | sort -r | head -n1)"
echo $latest_file
成功すると、次のようなログが記録されます。
++ mktemp -d
+ test_dir=/tmp/tmp.yWelcpBYB7
+ touch /tmp/tmp.yWelcpBYB7/file001 /tmp/tmp.yWelcpBYB7/file002 ... /tmp/tmp.yWelcpBYB7/file312
++ find /tmp/tmp.yWelcpBYB7 -type f
++ head -n1
++ sort -r
+ latest_file=/tmp/tmp.yWelcpBYB7/file312
+ echo /tmp/tmp.yWelcpBYB7/file312
/tmp/tmp.yWelcpBYB7/file312
失敗すると、次のようなログが記録されます。
++ mktemp -d
+ test_dir=/tmp/tmp.VzTqmgpZyG
+ touch /tmp/tmp.VzTqmgpZyG/file001 /tmp/tmp.VzTqmgpZyG/file002 ... /tmp/tmp.VzTqmgpZyG/file312
++ find /tmp/tmp.VzTqmgpZyG -type f
++ sort -r
++ head -n1
+ latest_file=/tmp/tmp.VzTqmgpZyG/file312
このecho $latest_file
線はないxtraceに表示されているにもかかわらずここで実行される
10,000ファイルを使用すると正常に実行できないので、何か関係があるのではないかと思います。頭停止する探す早い。
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{0000..9999}
latest_file="$(find $test_dir -type f | sort -r | head -n1)"
echo $latest_file
エラー時の停止を抑制すると(+e を設定)、成功します:
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{0000..9999}
set +e
latest_file="$(find $test_dir -type f | sort -r | head -n1)"
set -e
echo $latest_file
このスクリプトが最新のファイルを確実にログに記録しないのはなぜですか?
答え1
問題は-e
. Why?です-e
。プロセスがゼロ以外の終了コードで終了した場合に bash が中止します (完全なルールはもう少し複雑です)。パイプがある場合は、最後のコマンドだけがカウントされます。
は、からの残りの出力を無視するためにhead -n1
パイプを壊す必要があるため ( で確認できます)、内部的にエラー状況が発生します。strace
sort
したがって、スクリプトが で確実に動作するようにするには、パイプの末尾に-e
を追加します。は依然としてパイプを中断しますが、パイプ内の最後のコマンドではなくなるため、 では考慮されません。はパイプに対して何も行いません。cat
head
-e
cat
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{0000..9999}
latest_file="$(find $test_dir -type f | sort -r | head -n1 | cat)"
echo $latest_file
チェックしてくださいset -e (または set -o errexit、または trap ERR) が期待どおりに動作しないのはなぜですか?なぜこのような不安定な機能なのか、またそれがどのような問題を引き起こす可能性があるのかを知る必要があります-e
。最後に多くの例があります。私のお気に入りは:
#!/bin/bash
set -e
foo=$(expr 1 - 1)
echo survived
それはない印刷生き残った、その行は実行されません。しかし、 があった場合foo=$(expr 2 - 1)
、 がecho
実行されます。
独自のエラー チェックを実装する方がよいでしょうが、-e
これは最善の解決策ではありません。