web-dev-qa-db-ja.com

トラップとexecの両方を使用して、出力をbashのteeにリダイレクトします

ファイルから行を読み取り、各行を処理するスクリプトがあります。 Ctrl + Cを押したためにスクリプトがすべての行の読み取りを完了しなかった場合でも、後処理を実行できるように、「後処理」を実行できるようにしたいと思います。これを達成するために、私は次の両方を実行しようとしています。

  1. stdoutをファイルにリダイレクトします。後でそのファイルから後処理を行いますが、何が起こっているのかを確認したいので、「tee」にリダイレクトしたいと思います。
  2. ctrl + Cをトラップし、そこで後処理を行います

私はなんとか1つか2つの仕事をすることができましたが、同時に両方ではありませんでした:

#!/bin/bash

# 2. Either this works 
# trap ctrl-c and call ctrl_c()
trap ctrl_c INT
function ctrl_c() {
    echo "** Trapped CTRL-C"
}

# 1. Or this works    
LOGFILE=/tmp/${FILE}.tee
rm ${LOGFILE}
exec > >(tee ${LOGFILE}) 2>&1

function post_process() {
    # use ${LOGFILE}
}

egrep "(${URL_PATH})" ${FILE} |
    while read LINE ; do
        #...
    done

post_process
2
Gavriel

後処理関数の^C/SIGINTは無視してください。

preprocess(){
   yes baa
}
postprocess(){
   sed 's/a/z/g'
}
preprocess | { trap '' INT; postprocess; sleep 1; echo DONE; }

そのパイプラインを実行して^Cを押すと、preprocessは強制終了されますが、postprocessによって生成されたすべての出力が消費されるまで、preprocessは実行を継続します。

trap '' INT(ハンドラーとして空の文字列を使用)もサブプロセスのSIGINTを無視することに注意してください。たとえば、それを置き換えないでください。 trap 'echo INT trapped' INTは、親プロセスでシグナルが処理されているにもかかわらず、sedなども '^ C'によって強制終了されるためです。

1
mosvy