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

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

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

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

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

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

1 ответ

Во-первых: я бы не рекомендовал вам этого делать, добавление к зарегистрированным сообщениям меток времени и меток, таких как [ИНФО] и [ОШИБКА] в одном файле или просто меток времени в двух файлах, вероятно, было бы лучшей и более надежной идеей в длительный пробег. при этом позволяя вам создать другой файл, который вы хотите, с помощью 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
Другие вопросы по тегам