Оболочка Linux: перенаправить stderr и stdout в один файл И в отдельные файлы одновременно (используя tee?)

Оболочка Linux: перенаправить stderr и stdout в один файл И в отдельные файлы одновременно (используя tee?)

Я хотел бы сформировать конвейерный поток, который захватывает stdout в один файл и stderr в другой файл И оба в третий файл (чтобы полный вывод терминала был в одном файле)

Ну вот как то так:

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

Я знаю, что мне нужно использовать tee, но я не могу понять. У вас есть решение? Предпочтительнее Bash/sh...

Спасибо за любую помощь, я действительно это ценю!!!

решение1

Во-первых: я бы вам этого не рекомендовал. Добавление временных меток и меток, таких как [INFO] и [ERROR], к зарегистрированным сообщениям в одном файле или просто временных меток в двух файлах, вероятно, будет лучшей и более надежной идеей в долгосрочной перспективе. При этом вы по-прежнему сможете создать другой нужный вам файл с помощью grep или сортировки.

По вашей проблеме: мне никогда не приходилось этого делать, но вам, вероятно, нужно использовать именованные каналы. Непроверенный пример bash:

# 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)

У вас может возникнуть соблазн использовать exec >"$info_pipe" 2>"$error_pipe". Не делайте этого, иначе вы создадите цикл, который заполнит все доступное дисковое пространство вашим файлом журнала.

Обратите внимание, что если ваш bash не поддерживает неявные именованные каналы (должен, но я видел среды, в которых этого не было), вы можете использовать их явно, вызвав mkfifo, однако для этого потребуется больше усилий:

# 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

Связанный контент