Redireciona stdout e / ou stderr para caminho na variável

1

Como eu redireciono o stdout e / ou o stderr para um caminho que eu especifiquei em uma variável? Nota: Eu não quero sobrescrever a variável em si , eu quero fazer std [xxx] gravar no arquivo especificado na variável.

Por exemplo: um script simples que, se o comando scp falhar, em vez de imprimir a mensagem de falha para stderr ou stdout (não sei ao certo quando ela é enviada quando falhar), ela é enviada para um arquivo de log especificado. O caminho para o arquivo de log é armazenado na variável $LOG :

LOG=/path/to/file.log
scp file1 host@remote

# do 'whatever' if scp command succeeds:
if [ $? = 0 ];
then
    whatever
else
    # else log both stdout/stderr to ${LOG} file
    &>"${LOG}"
    # DEBUG - print contents of ${LOG} var for testing purposes
    printf "${LOG}"

O resultado deste script não mostra nada no arquivo /path/to/file.log e impressões simples /path/to/file.log to stdout . Então é como se nada fosse escrito de &> .

Eu já confirmei que meu comando scp específico funciona, por isso sei que esse não é um problema em potencial.

Ou essa é a maneira mais adequada de lidar com arquivos de log personalizados? Existe uma prática melhor para configurar seu próprio sistema de registro do que o armazenamento de caminhos para arquivos de log em variáveis?

    
por Willman 18.11.2017 / 16:04

2 respostas

0

Parece que você está tentando registrar a saída após executar o comando, o que não é possível.

Se você quiser registrar a saída do comando scp incondicionalmente, basta incluir o operador de redirecionamento na mesma linha do comando em si, ou seja:

&>"${LOG}" scp file1 host@remote

Se você quiser salvar somente a saída do log se o comando falhar (como parece que você está tentando fazer no seu código), então que tal redirecionar a saída para um arquivo temporário e então mover o arquivo para o local desejado? depois? Pode parecer algo assim:

#!/bin/bash

# Set path the real log file location
LOG=/path/to/file.log

# Create a temporary file to capture standard output and standard error
TEMPLOG="$(mktemp)"

# Run command and redirect output to temporary logfile
2>"${TEMPLOG}" scp file1 host@remote

# do 'whatever' if scp command succeeds:
if [ $? = 0 ];
then
    echo 'Command successful!'

# else log both stdout/stderr to ${LOG} file
else
    # Move the log file from the temporary location to the desired location
    mv "${TEMPLOG}" "${LOG}"

    # DEBUG - print contents of ${LOG} var for testing purposes
    printf "${LOG}"
fi
    
por 18.11.2017 / 16:38
0

Parece que você acabou satisfeito com o resultado desta pergunta, mas eu proponho algo diferente.

#!/bin/bash
LOG=/path/to/file.log    
DEBUG=0 # 0 = True, 1 = False
OUTPUT=$(scp file1 host@remote 2>&1)

# do 'whatever' if scp command succeeds:
if [ $? -eq 0 ];
then
    echo "Success"
elif [[ DEBUG -eq 0 ]]
    # else log both stdout/stderr to ${LOG} file and user
    # DEBUG - Use tee to display ${LOG} contents efficiently
    printf "$OUTPUT" | tee $LOG
else
    # Send output to $LOG
    printf "$OUTPUT" >> $LOG
fi

Essencialmente capture STDIN / STDOUT em uma variável não importa o que, então se o sucesso fizer 'o que for' mas se a falha redirecionar STDIN / STDOUT para $LOG . Além disso, com o sinalizador $DEBUG , você pode tee do conteúdo de $OUTPUT na exibição e $LOG simultaneamente.

Também para comparação de números inteiros, você realmente deve usar -eq em vez de = ou ==

    
por 06.04.2018 / 16:34