redirect e log de saída de script

8

Estou tentando arrumar os trechos a seguir, as metas de design são registrar todas as saídas de um script e não devem ser um wrapper. Menos linhas são melhores.

Eu não me importo com as entradas do usuário (neste estágio), os scripts de destino são executados de forma não interativa.

O snippet precisa ser

  • saída stdout para logar e sempre ecoar para o console
  • efetua o stderr para efetuar o log e faz eco para o console se a depuração estiver ativada
  • as mensagens do stderr devem ser prefixadas com carimbos de hora e outra utilidade

No momento eu tenho o seguinte, que só testa em versões recentes do bash (4.2+?) como no Ubuntu, mas se comporta mal no CentOS6.

DEBUG_LOG="${0##*/}.log"

# copy stdout to log always and echo to console
exec >  >(tee -a ${DEBUG_LOG})           

# copy stderr to log only, unless debugging is enabled
[ $DEBUG_TEST = "true" ] \
  && exec 2> >(tee -a ${DEBUG_LOG} >&2) \
  || exec 2>> ${DEBUG_LOG}

Então isso ...

# Expand escaped characters, wrap at 70 chars on spaces, 
# and indent wrapped lines
msg_log() { 
  echo -e "$(date +%T) ${0##*/}: $1" \
    | fold -w70 -s | sed '2~1s/^/  /' >&2; 
}
msg_con() { 
  if [ "${DEBUG_TEST}" = "true" ]; then 
    msg_log "$1"
  else
    echo -e "$1" | fold -w70 -s | sed '2~1s/^/  /'; 
  fi
}

Em vez de echo , posso chamar um desses procedimentos de mensagem, por exemplo, msg_con "hello world" .
Além disso, a saída do script irá para stderr definindo como uma variável de ambiente no momento da chamada, por exemplo, DEBUG_TEST=true myscript .

Eu li que exec pode não funcionar em alguns shells como o busybox. Há uma combinação mkfifo e fork no link que faz algo semelhante, mas eu prefiro não usar o fork a menos que seja absolutamente necessário.

Prefira exemplos de bash por favor, mas algo que funcione sob sh ou seja mais portátil seria legal. Alguma idéia?

    
por Glenn 22.02.2013 / 09:24

4 respostas

1
function startLogging {
    exec > >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' | tee -a $logfile)
    [ ! -z "$DEBUG" ] && exec 2>&1 || exec 2> >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' >>$logfile)
    echo "=== Log started for $$ at $(date +%F-%T) ==="
}

Você precisa ter $ logfile definido para algo

    
por 17.09.2013 / 23:01
0

exec > filename deve funcionar em sh, e funciona na busybox v1.15.3 (novembro de 2011). Mas a substituição do processo >(command) não é portável, uma vez que é uma extensão bash. Apenas evite usá-lo em scripts. Por que >> não é suficiente para você?

exec 1>>${DEBUG_LOG}
exec 2>>${DEBUG_LOG}

Outra solução é especificar o redirecionamento fora dos seus scripts. Quando seu script é chamado em segundo plano (pelo cron, ou script do sistema, etc.), eles devem ser chamados assim

./my_script 1>>${DEBUG_LOG} 2>>${DEBUG_LOG}

Quando você invoca o script manualmente e deseja ver a saída, apenas chame-o sem redirecionamentos.

    
por 04.05.2013 / 11:03
0

Esses dois exemplos farão seus objetivos declarados

echo -n $(date) >> $DEBUG_LOG
command 2>&1 | tee -a $DEBUG_LOG

ou

echo -n $(date) >> $DEBUG_LOG
command >> $DEBUG_LOG 2>&1
    
por 25.07.2013 / 22:53
0

Você pode usar o comando tee ou o comando script que são realmente úteis.

    
por 12.09.2013 / 12:57