Shell de Linux: canalice stderr y stdout a un archivo Y a archivos individuales al mismo tiempo (¿usando tee?)

Shell de Linux: canalice stderr y stdout a un archivo Y a archivos individuales al mismo tiempo (¿usando tee?)

Me gustaría formar un flujo de tubería que capture stdout en un archivo y stderr en otro archivo Y ambos en un tercer archivo (por lo que también la salida completa del terminal está en un archivo)

de alguna manera así:

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

Sé que tengo que usar tee pero no puedo entenderlo. ¿Tienen ustedes una solución? Bash/sh preferido...

Gracias por cualquier ayuda, ¡¡¡realmente lo aprecio !!!

Respuesta1

Primero: no es algo que le recomendaría hacer, anteponer mensajes registrados con marcas de tiempo y etiquetas como [INFO] y [ERROR] en un solo archivo o simplemente marcas de tiempo en sus dos archivos probablemente sería una idea mejor y más confiable en el largo plazo. y al mismo tiempo le permite crear el otro archivo que desee mediante grep o sorting.

Para su problema: nunca tuve que hacerlo, pero probablemente necesite usar canalizaciones con nombre. Ejemplo de bash no probado:

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

Podrías sentirte tentado a utilizar exec >"$info_pipe" 2>"$error_pipe". No lo hagas, o generarás un bucle que hará que tu archivo de registro llene todo el espacio disponible en el disco.

Tenga en cuenta que si su bash no admite canalizaciones con nombres implícitos (debería hacerlo, pero he visto entornos que no lo hacen), es posible que desee usarlos explícitamente llamando a mkfifo; sin embargo, esto requiere más plomería:

# 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

información relacionada