POSIXシェルの「ロガー」にすべての出力を送信するには?

POSIXシェルの「ロガー」にすべての出力を送信するには?

.xprofile.NETを使用するときは、stdoutとstderrを別々に記録したいと思いますlogger。 Bashでは、次のように見えると思います。

exec 1> >(logger --priority user.notice --tag $(basename $0)) \
     2> >(logger --priority user.error --tag $(basename $0))

POSIXでこれをどのように実行しますか? /bin/sh互換性のある方法は?

ベストアンサー1

POSIX コマンド/プロセスの置換


_log()( x=0
    while  [ -e "${TMPDIR:=/tmp}/$$.$((x+=1))" ]
    do     continue; done        &&
    mkfifo -- "$TMPDIR/$$.$x"    &&
    printf %s\\n "$TMPDIR/$$.$x" || exit
    exec >&- >/dev/null
    {  rm -- "$TMPDIR/$$.$x"
       logger --priority user."$1" --tag "${0##*/}"
    }  <"$TMPDIR/$$.$x" &
)   <&- </dev/null

次のように使用できる必要があります。

exec >"$(_log notice)" 2>"$(_log error)"

次のコマンドを使用するバージョンは次のとおりですmktemp

_log()( p=
    mkfifo "${p:=$(mktemp -u)}"    &&
    printf %s "$p"                 &&
    exec  <&- >&- <>/dev/null >&0  &&
    {   rm "$p"
        logger --priority user."$1" --tag "${0##*/}"
    }   <"$p" &
)

mktemp...ファイル名を選択できることを除いて、ほぼ同じことを行います。これはうまくいきます。プロセスの交換決して魔法ではなく、次のように動作します。コマンドの置き換え。拡張子をその中で実行されるコマンドの値に置き換える代わりにコマンドの置き換えする、プロセスの交換これを出力を見つけることができるファイルシステムリンクの名前に置き換えます。

POSIXシェルはこれに直接結果を与えませんが、これをシミュレートするのは非常に簡単です。あなたがしなければならないのは、ファイルを作成し、コマンドの置き換えによってその名前を標準で印刷してから、ファイルに出力されるのと同じ背景でコマンドを実行することだけです。これで、その拡張の値にリダイレクトできます。正確にプロセス交換で行ったのと同じです。したがって、POSIXシェルは必要なすべてのツールを確実に提供します。必要なのは、自分に合った方法でツールを使用することだけです。

上記の両方のバージョンを使用する前に、作成/使用するパイプのファイルシステムリンクを破壊します。つまり、後でクリーンアップする必要はなく、さらに重要なことは、そのストリームを元々開いたプロセスでのみ使用できることです。したがって、そのファイルシステムリンクをロギングアクティビティをスヌーピング/ハイジャックする手段として使用することはできません。ファイルシステムリンクをファイルシステムに残すと、潜在的なセキュリティの脆弱性が発生します。


もう一つの方法は包装することです。スクリプト内で実行できます。

x=${x##*[!0-9]*}
_log(){ 
    logger --priority user."$1" --tag "${0##*/}"
}   2>/dev/null >&2

cd ../"$PPID.$x" 2>/dev/null &&
trap 'rm -rf -- "${TMPDIR:-/tmp}/$PPID.$x"' 0 || 
{   until cd -- "${TMPDIR:=/tmp}/$$.$x"
    do    mkdir -- "$TMPDIR/$$.$((x+=1))"
    done  && 
    x=$x "$0" "$@" | _log notice
    exit
}   2>&1 | _log error

これにより、スクリプトはデフォルトで自分自身を呼び出すことができ(まだ呼び出されていない場合)、起動する一時作業ディレクトリを提供できます。

おすすめ記事