Shell do Linux: canalize stderr e stdout para um arquivo E para arquivos individuais ao mesmo tempo (usando tee?)

Shell do Linux: canalize stderr e stdout para um arquivo E para arquivos individuais ao mesmo tempo (usando tee?)

Eu gostaria de formar um pipe-stream que capture stdout para um arquivo e stderr para outro arquivo E ambos em um terceiro arquivo (assim também a saída completa do terminal está em um arquivo)

de alguma forma assim:

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

Eu sei que tenho que usar camiseta, mas não consigo descobrir. Vocês têm uma solução? Bash/sh preferido...

Obrigado por qualquer ajuda, eu realmente aprecio isso !!!

Responder1

Primeiro: não é algo que eu recomendo que você faça, anexar mensagens registradas com carimbos de data e hora e rótulos como [INFO] e [ERROR] em um único arquivo ou apenas carimbos de data e hora em seus dois arquivos provavelmente seria uma ideia melhor e mais confiável no longo prazo. enquanto ainda permite que você crie o outro arquivo desejado usando grep ou classificação.

Para o seu problema: nunca precisei fazer isso, mas provavelmente você precisará usar pipes nomeados. Exemplo de bash não testado:

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

Você pode ficar tentado a usar exec >"$info_pipe" 2>"$error_pipe". Não faça isso, ou você gerará um loop que fará com que seu arquivo de log preencha todo o espaço disponível em disco

Observe que se o seu bash não suporta pipes nomeados implícitos (deveria, mas já vi ambientes que não suportam), você pode querer usá-los explicitamente chamando mkfifo, no entanto, isso requer mais encanamento:

# 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

informação relacionada