114

Unixシェルには、envファイルがあります(envファイルは、ログファイル名とパスなどのユーザースクリプトの実行に必要なパラメーターを定義し、出力とエラーをログファイルにリダイレクトし、データベース接続の詳細など)、すべての出力をリダイレクトします(エコーメッセージ) と、次のコードを使用して、実行されたスクリプトからログ ファイルへのエラー:

exec 1>>${LOG_FILE}
exec 2>>${LOG_FILE}

env ファイルは、各スクリプトの開始時に実行されます。環境ファイルの上記のコードにより、ユーザー出力またはエラーである可能性のあるすべてのコンソール出力が、実際に必要だったログ ファイルに直接出力されます。

しかし、コンソールとログ ファイルの両方に表示したい選択的なユーザー出力がいくつかあります。しかし、上記のコードのため、私はそうすることができません。

上記のコードを削除すると、この場合に望ましい結果が得られることはわかっていますが、他のすべての出力を手動でログ ファイルに書き込む必要がありますが、これは簡単な作業ではありません。

上記のコードを削除せずに、コンソールとログ ファイルの両方に出力を取得する方法はありますか?

4

9 に答える 9

129
exec 3>&1 1>>${LOG_FILE} 2>&1

stdout と stderr の出力をログ ファイルに送信しますが、fd 3 がコンソールに接続されたままになるので、次のことができます。

echo "Some console message" 1>&3

コンソールだけにメッセージを書き込む、または

echo "Some console and log file message" | tee /dev/fd/3

コンソールログ ファイルの両方にメッセージを書き込むには、その出力を自身の fd 1 (ここでは) と、書き込むように指示したファイル (ここでは fd 3、つまりコンソール) の両方に送信します。teeLOG_FILE

例:

exec 3>&1 1>>${LOG_FILE} 2>&1

echo "This is stdout"
echo "This is stderr" 1>&2
echo "This is the console (fd 3)" 1>&3
echo "This is both the log and the console" | tee /dev/fd/3

印刷します

This is the console (fd 3)
This is both the log and the console

コンソールに置いて

This is stdout
This is stderr
This is both the log and the console

ログファイルに。

于 2013-08-27T10:26:09.413 に答える
46

私はjoontyの答えを試しましたが、私も得ました

exec: 1: 見つかりません

エラー。これは私にとって最もうまくいくものです(zshでも動作することが確認されています):

#!/bin/bash
LOG_FILE=/tmp/both.log
exec > >(tee ${LOG_FILE}) 2>&1
echo "this is stdout"
chmmm 77 /makeError

その後、ファイル /tmp/both.log には次が含まれます

this is stdout
chmmm command not found 

-a をティーから削除しない限り、/tmp/both.log が追加されます。

ヒント:>(...)プロセス置換です。execファイルであるかのようにteeコマンドを実行できます。

于 2014-03-13T09:07:31.947 に答える
45

はい、使用したいtee

tee - 標準入力から読み取り、標準出力とファイルに書き込みます

次のように、コマンドをパイプして tee に渡し、ファイルを引数として渡します。

exec 1 | tee ${LOG_FILE}
exec 2 | tee ${LOG_FILE}

これにより、出力が STDOUT に出力され、同じ出力がログ ファイルに書き込まれます。詳細については、を参照man teeしてください。

これは stderr をログ ファイルに書き込まないことに注意してください。したがって、2 つのストリームを結合する場合は、次を使用します。

exec 1 2>&1 | tee ${LOG_FILE}
于 2013-08-27T08:09:10.417 に答える
1

目的の出力を取得する方法を見つけました。少々風変わりな方法かもしれませんが。とにかく、ここに行きます。redir.env ファイルには、次のコードがあります。

#####redir.env#####    
export LOG_FILE=log.txt

      exec 2>>${LOG_FILE}

    function log {
     echo "$1">>${LOG_FILE}
    }

    function message {
     echo "$1"
     echo "$1">>${LOG_FILE}
    }

次に、実際のスクリプトには次のコードがあります。

#!/bin/sh 
. redir.env
echo "Echoed to console only"
log "Written to log file only"
message "To console and log"
echo "This is stderr. Written to log file only" 1>&2

ここでは、エコー出力をコンソールにのみ出力し、ログ出力をログ ファイルのみに出力し、メッセージ出力をログ ファイルとコンソールの両方に出力します。

上記のスクリプト ファイルを実行すると、次の出力が得られます。

コンソールで

コンソール
内 コンソールのみ
にエコー コンソールおよびログへ

ログファイルの場合

ログ ファイル内 ログ ファイルのみに書き込まれます
これは stderr です。ログファイルのみに書き込まれる
コンソールとログに

この助けを願っています。

于 2013-08-30T05:17:17.087 に答える
0

stdout と stderr の両方をログ ファイルに追加すると非常に便利です。exec > >(tee -a)を使用してこれを達成する方法を考えていたので、alfonx による解決策を見てよかったexecです。here-doc構文とhttps://unix.stackexchange.com/questions/80707/how-to-output-text-to-both-screen-and-file-inside-a-shell.を使用したクリエイティブなソリューションに出会いました-脚本

zsh では、「multios」コンストラクトを使用してヒアドキュメント ソリューションを変更し、出力を stdout/stderr とログ ファイルの両方にコピーできることを発見しました。

#!/bin/zsh
LOG=$0.log
# 8 is an arbitrary number;
# multiple redirects for the same file descriptor 
# triggers "multios"
. 8<<\EOF /dev/fd/8 2>&2 >&1 2>>$LOG >>$LOG
# some commands
date >&2
set -x
echo hi
echo bye
EOF
echo not logged

ソリューションほど読みやすくはありませんexecが、スクリプトの一部だけをログに記録できるという利点があります。もちろん、EOF を省略した場合、スクリプト全体がログ付きで実行されます。が multios をどのようにzsh実装しているかはわかりませんが、よりもオーバーヘッドが少ない可能性がありますtee。残念ながら、マルチ OS を と一緒に使用することはできないようですexec

于 2015-07-29T21:35:42.110 に答える