Saída do pipe ssh (stderr e stdout) para comandos diferentes

2

Sou um roteiro de escrita para algum tipo de backup envolvendo ssh e rsync. Toda vez que esse script é executado, eu redireciono toda a saída para um arquivo de log. Para padronizar as entradas de log, escrevi uma função de log que adiciona um registro de data e hora e um nível de log. Minha idéia era também ler o stdout e stderr de cada linha de comando por linha e chamar essa função de log. Por isso, eu segui as respostas de link .

O meu script é assim (é reduzido, suponha que todas as variáveis usadas estão definidas corretamente):

#!/bin/bash

# function: print a formatted log message including timestamp with given level and message to stdout 
# arguments: <LEVEL> <MESSAGE>
log()
{
    timestamp=$(date +"%F %T.%3N")
    level=$1
    message=$2
    echo $timestamp $level: $message
}

# function: read command output from stdin and log it with given level
# arguments: <LEVEL>
logoutput()
{
    sed 1d | \
    while read i
    do
        log "$1" "$i"
    done
}

log INFO "START ssh"
(ssh $connection mkdir -p $destStaticDirectory | logoutput INFO) 3>&1 1>&2 2>&3 | logoutput ERROR

log INFO "START rsync"
(rsync $rsyncArguments $linkDest $fromDirectory $connection:$destStaticDirectory | logoutput INFO) 3>&1 1>&2 2>&3 | logoutput ERROR

A função log() é usada para ecoar uma entrada de log e a função logoutput() é usada para ler stdout linha por linha e registrar cada.

Agora, a coisa é que tudo funciona como esperado para o comando rsync. Mas não para o comando ssh. Eu sei que não há saída para stdout ao chamar ssh $connection mkdir -p $destStaticDirectory corretamente. Então eu testei deixando o ssh conectar-se a um host desconhecido que resulta em ssh: Could not resolve hostname XXX: Name or service not known . Mas novamente nada. Eu também adicionei o mesmo comando ssh "unwrapped" ao script que imprime todas as saídas como esperado. Finalmente eu mudei o modo verboso do ssh que resultou em entradas de log de erro. Mas isso não é uma opção, já que eu não quero as mensagens de bebush do ssh no meu log.

Estou faltando alguma coisa? Existe mesmo stdout estranho, err manipulação ssh está fazendo eu não estou ciente de? Espero ter deixado claro o que estou tentando fazer.

    
por ahaertig 10.06.2015 / 18:27

2 respostas

0

Seu problema é mais provável na função logoutput, onde "sed 1d" remove a saída que você está procurando. Tente remover a linha "sed 1d" e veja se seu script se comporta como esperado.

    
por 10.06.2015 / 23:32
1

Você já considerou usar logger (1) para fazer o registro para você e adicionar timestamps etc.

Então, algo como

{ ssh ... | logger ...; }  2>&1 | logger ...

deve ser o que você deseja, já que a primeira parte envia stdout para um arquivo de log via logger e a segunda parte envia stderr para um arquivo de log. Você pode usar as opções de linha de comando do logger para selecionar qual facilidade de registro ou arquivo, etc.

Existe uma maneira mais simples de fazer isso também. Use Substituição de processos , por exemplo,

ssh ... > >(logger ...) 2> >(logger ...)

Isso evita ter que mexer com todos os descritores de arquivos.

    
por 11.06.2015 / 00:10

Tags