bashスクリプトは失敗時にstderrを印刷します。

bashスクリプトは失敗時にstderrを印刷します。

すべてがうまくいけば、bashスクリプトを自動的に作成しようとしていますが、何らかの理由でクラッシュした場合は、すべてのstderrとデバッグ情報を印刷します。以下は私が今まで持っているものです。

#!/usr/bin/bash

set -e

rm -f /tmp/err
trap "sleep 1 && cat /tmp/err" ERR

l() {
    ts >> /tmp/err
}

echo "About to download stuff:" > >(l)
# curl blah blah 2> >(l)

# something goes wrong in the script
invalid_cmd

私が好きではない「スリープ1」がある場合にのみ正常に動作します。

眠らないでください:

❯ ./demo2.sh    
./demo2.sh: line 18: invalid_cmd: command not found

睡眠中:

❯ ./demo2.sh
./demo2.sh: line 18: invalid_cmd: command not found
Feb 25 15:20:44 About to download stuff:

プロセスの置き換えがバックグラウンドで実行されているため、完了しない可能性があるためです。また、waitすべてのバックグラウンドタスクを盲目的に実行したくありません。この問題を解決するより良い方法はありますか?

答え1

もう少しハッキングした後、私は次の解決策を見つけました。

#!/usr/bin/bash

set -e

make_temp_fds() {
    local tfile=$(mktemp)
    exec {fdw}>$tfile {fdr1}<$tfile {fdr2}<$tfile
    rm $tfile
}
    
setup_err_fd() {
    make_temp_fds
    local raw_fdw=$fdw raw_fdr=$fdr1

    make_temp_fds
    local ts_fdw=$fdw ts_fdr=$fdr1

    ts <&$raw_fdr >&$ts_fdw &
    tspid=$!
    trap "wait $tspid && cat <&$ts_fdr" ERR

    err_fd=$raw_fdw
}

# Calling this function, will give you $err_fd
# Anything written to $err_fd will be saved in a temporary file with timestamps 
# and printed out if the script fails with an error. 
# Will be lost if script exits successfully
setup_err_fd

echo "all setup"

echo "debug line 1" >&$err_fd

echo "debug line 2" >&$err_fd

not_ok
#echo "ok"

echo "bye"

残念ながら、2つの一時ファイルが含まれています。そのうちの1つをパイプラインにしようとしましたが、うまくいきませんでした。いつでも改善してください

関連情報