解決策として I/O リダイレクトを思いつきました。Exec を使用したBash リダイレクトの記事は、私にインスピレーションを与えました。これには次の意味があります。
- echo、printf など、どのコマンドがスクリプトに出力されても、スクリプトの標準出力またはエラー出力をリダイレクトします。
- サブシェルまたはソース スクリプトの反復作業はありません。
- リダイレクションは、このスクリプト、サブスクリプト、またはそのソース スクリプトによって呼び出されているすべての実行可能ファイルに適用されます。
- フィルターは、1 つのパイプがその出力を次のパイプの入力にリダイレクトするなど、いくつかのパイプを作成することによって構成できます。
私のbash
シェルスクリプトでは、次を使用します。
alias start_log_ctx="start_filter_by_pipe_regex 2 s/.*/${0##*/}\(pid=$$\): \0/"
function start_filter_by_pipe_regex {
declare -r a="$(mktemp -u)" #1
mknod "$a" p #2
sed <"$a" ">&$1" "$2" & #3
exec "$1">"$a" #4
}
alias stop_log_ctx_by_job="stop_filter_by_pipe_job 2"
def stop_filter_by_pipe_job {
exec "$1">&- #1
wait "$2" #2
}
本質的に、start_log_ctx
エイリアスは、エラー出力に送られるスクリプトの I/Osed
を行ごとに ( .*
) フィルター処理し ( 2
)、スクリプトのベース名 ( ${0##*/}
) とプロセス ID ( pid=$$
) を各行の先頭に追加するために使用します。このstart_filter_by_pipe_regex
関数は次のように機能します。
- 絶対パスを
-U
保存しますが、一時ファイルを作成 ( ) しません。
- [1.]の絶対パスの下にパイプを作成します。
sed
バックグラウンドでフィルターとして開始します ( &
)。[2.] のパイプから読み取り ( )、標準出力 ( ) を 1. パラメーターとして指定されたファイル記述子に<
リダイレクトします。>
2. パラメータとして指定されたフィルタを に渡しますsed
。
>
1. パラメータとして与えられたファイル記述子を [2.] のパイプにリダイレクト ( ) します。
stop_log_ctx
エイリアスは、エラー出力のファイル記述子 ( ) を閉じ、以前2
に開始された が停止するのを待ちsed
ます。ファイル記述子を閉じると、暗黙的にこれが行われます。このstop_filter_by_pipe_job
関数は次のことを行います。
- 1. パラメータとして指定されたファイル記述子を閉じて、 を停止し
sed
ます。
sed
2. パラメーターとして指定された bash ジョブによって識別されるバックグラウンドが停止するまで待ちます。
メイン関数の最初に、通常は aを実行し、declare -r a="$(start_log_ctx)"
で終了しstop_log_ctx_by_job "$a"
ます。