標準エラーをファイルにパイプし、標準エラーのままにしますか?


2

出力と標準エラーを記録するスクリプト(フラグメント)があります。

#!/bin/sh
#...
{
   date "+%Y-%m-%d %T"
   cd $workdir
   ls -ltr validfile badfile #example command that provides stdout, stderr
} | tee -a $logfile

上記を行うと、ログファイルに標準出力が表示されます。そこで標準エラーを取得するには、これを行うことができます:

#!/bin/sh
#...
{
   date "+%Y-%m-%d %T"
   cd $workdir
   ls -ltr validfile badfile
} 2>&1 | tee -a $logfile

ただし、コマンドラインから呼び出されたスクリプトのこのバージョンでは、エラーを解析できません。

$ ./script.sh 2>/dev/null

すべての標準出力と標準エラーを単に表示します。今回、エラーをただ破棄したい場合はどうすればよいですか?

標準エラーをログにパイプする方法を教えてもらえますが、コマンドラインまたは別のスクリプトを介して呼び出された場合に備えて、標準エラーのままにしますか?

AIX 7.1、ksh(bashなし)

回答:


3

派手な出力リダイレクトを使用すると、プロセスへの基本的なbashリダイレクトなしでこれを実現できます。

標準エラーを記録し、標準エラーパイプに保持する

#!/bin/sh
exec 4>&1    # important as it "saves" stdout (usually /dev/tty2 for example)
exec 3>&1    # work-in-progress file descriptor
logfile=/var/log/myscript.out

{
   {
      date "+%Y-%m-%d %T"
      cd $workdir
      ls -ltr validfile badfile
   } 2>&1 1>&3 | tee -a $logfile 1>&2 2>/dev/null 3>&4
} 3>&1 | tee -a $logfile

exec 4>&-   # proper form is to clean up when you're done
exec 3>&-

説明:
exec 4>&1そしてexec 3>&1、新しいファイル記述子3と4 を作成します。これらは両方とも、標準出力が指しているもの(おそらく、ご使用の端末)を指します。

2>&1第2レベルの中括弧全体の標準エラーを標準出力にリダイレクトします。1>&3fd3が指しているものに標準出力をリダイレクトします(これは標準出力ですが、パイプ1ではなく、重要です!)

| tee -a $logfileログファイルと標準出力の両方に標準入力(2番目のレベルの中括弧、つまり古いstderrから来る)を複製します。標準を標準エラーに1>&2移動します(そのため、元の場所に戻ります)2>/dev/nullおそらく必要ではありませんが、エラー出力をteeからリダイレクトし、それを破棄します。3>&4パイプ3をパイプ4にリダイレクトします(これは、ちなみにstdoutを指しているのを覚えていますか?)。

3>&1第1レベルの中括弧のパイプ3を取得し、通常の標準出力に送信ます。| tee -a $logfile標準入力(ブレースの[調整済み]標準出力)をキャプチャし、ログと標準出力に複製します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.