Bashスクリプトの出力にプレフィックスを追加するには? [コピー]

Bashスクリプトの出力にプレフィックスを追加するには? [コピー]

スクリプトが実行されると、その中のコマンドはいくつかのテキストをstdout / stderrに出力できます。 Bash自体もいくつかのテキストを出力できます。

ただし、複数のスクリプトを同時に実行すると、エラーがどこで発生するのかを理解するのが難しい場合があります。

では、スクリプトのすべての出力にプレフィックスを挿入することは可能ですか?それは次のとおりです。

#!/bin/bash
prefix 'PREFIX' &2
echo "wrong!" >&2

それから:

$ ./script.sh
PREFIXwrong!

答え1

選択したプレフィックスを追加するプロセスの置き換えにstderr / stdoutをリダイレクトできます。たとえば、次のスクリプトは次のようになります。

#! /bin/bash
exec > >(trap "" INT TERM; sed 's/^/foo: /')
exec 2> >(trap "" INT TERM; sed 's/^/foo: (stderr) /' >&2)
echo foo
echo bar >&2
date

次の出力が生成されます。

foo: foo
foo: (stderr) bar
foo: Fri Apr 27 20:04:34 IST 2018

最初の2行は、stdoutとstderrを入力にfoo:追加するsedコマンドにそれぞれリダイレクトします。シェル組み込み呼び出しは終了スクリプトを使用するか、 。これにより、シャットダウン信号も受信されたため、シャットダウン時にファイル記述子が消えるため、シェルがスクリプトを強制的にシャットダウンしないようにすることができます。実際には、基本スクリプトで終了トラップを引き続き使用でき、終了トラップを実行したときに生成されたすべての出力を処理するために引き続き実行されます。サブシェルはメインスクリプトの終了後も終了しなければプロセスは永久に実行されません。foo: (stderr)
trapCtrl+CSIGTERMkill $pidstdoutsedsedsed

答え2

行を置き換える方法で出力をパイプできます。

some long running stuff | sed -e 's/^/Some said: /;'

また確認24337

または、ターミナル/...(1)タブ/タブの別々のファイル/画面に別々の出力を直接指定します。

答え3

Bashの1つのオプションは、次のようにプロセス交換にリダイレクトしてこれを行うことです。

./script.sh > >(sed 's/^/script: /') 2> >(sed 's/^/script (err): /' >&2)

これには、出力が順序に合わない可能性があるという問題があります(Charles Duffyがコメントで述べたように)。これも本当に不便です。しかし、これに対するラッパー関数を作ることができます。

prefixwith() {
    local prefix="$1"
    shift
    "$@" > >(sed "s/^/$prefix: /") 2> >(sed "s/^/$prefix (err): /" >&2)
}
prefixwith "From script" ./script.sh

または、コマンド名を前に付けて簡単に作成できます。

prefixoutput() {
    local prefix="From ${1##*/}"
    "$@" > >(sed "s/^/$prefix: /") 2> >(sed "s/^/$prefix (err): /" >&2)
}
prefixoutput ./script.sh

関連情報