Linux-Shell: Leiten Sie stderr und stdout gleichzeitig in eine Datei UND in einzelne Dateien um (mit tee?)

Linux-Shell: Leiten Sie stderr und stdout gleichzeitig in eine Datei UND in einzelne Dateien um (mit tee?)

Ich möchte einen Pipe-Stream bilden, der stdout in einer Datei und stderr in einer anderen Datei erfasst UND beides in einer dritten Datei (sodass auch die gesamte Terminalausgabe in einer Datei ist).

irgendwie so:

process ----+-- <stdout> --- + --- stdlog.txt 
            |                |
            |                }---- <terminal> --- alllog.txt
            |                |
            \-- <stderr> --- +---- errlog.txt 

Ich weiß, dass ich tee verwenden muss, aber ich komme nicht dahinter. Habt ihr eine Lösung? Am besten Bash/sh …

Danke für jede Hilfe, ich weiß das wirklich zu schätzen!!!

Antwort1

Erstens: Ich würde Ihnen das nicht empfehlen. Den protokollierten Nachrichten in einer einzigen Datei Zeitstempel und Bezeichnungen wie [INFO] und [ERROR] oder in Ihren beiden Dateien nur Zeitstempel voranzustellen, ist auf lange Sicht wahrscheinlich die bessere und zuverlässigere Idee. Gleichzeitig haben Sie weiterhin die Möglichkeit, die gewünschte andere Datei mithilfe von grep oder durch Sortieren zu erstellen.

Zu Ihrem Problem: Ich musste es noch nie tun, aber Sie müssen wahrscheinlich benannte Pipes verwenden. Ungetestetes Bash-Beispiel:

# Log one output type
function logger() {
    unique_file="$1"
    common_file="$2"
    # Tee reads from the function's standard input, writes to unique_file, appends to common_file, then outputs what was written
    tee "$unique_file" | tee -a "$common_file"
}

# Call your code's main function to start processing
main > >(logger info_log_file common_log_file) 2> >(logger error_log_file common_log_file >&2)

Sie könnten versucht sein, zu verwenden exec >"$info_pipe" 2>"$error_pipe". Tun Sie das nicht, sonst erzeugen Sie eine Schleife, die dazu führt, dass Ihre Protokolldatei den gesamten verfügbaren Speicherplatz füllt.

Beachten Sie: Wenn Ihre Bash implizite Named Pipes nicht unterstützt (sie sollte es, aber ich habe Umgebungen gesehen, bei denen das nicht der Fall war), möchten Sie diese möglicherweise explizit durch den Aufruf von mkfifo verwenden. Dies erfordert jedoch mehr Aufwand:

# Log one output type
function logger() {
    unique_file="$1"
    common_file="$2"
    # Tee reads from the function's standard input, writes to unique_file, appends to common_file, then outputs what was written
    tee "$unique_file" | tee -a "$common_file"
}

# Setup logging
function prepare() {
    tmp_pipe_dir="$(mktemp -d)"
    error_pipe="$(mkfifo "$tmp_pipe_dir/error")"
    info_pipe="$(mkfifo "$tmp_pipe_dir/info")"
}

function cleanup() {
    rm -rf "$tmp_pipe_dir"
}

prepare
# Start logging, note that logger won't stop on its own. Removing the pipe files should do the trick
logger info_log_file common_log_file <"$info_pipe" &
logger error_log_file common_log_file <"$error_pipe" >&2 &
# Call your code's main function to start processing
main >"$info_pipe" 2>"$error_pipe"
cleanup

verwandte Informationen