reindirizzare e registrare l'output dello script


8

Sto cercando di riordinare i seguenti frammenti, gli obiettivi di progettazione sono di registrare tutto l'output di uno script e non dovrebbe essere un wrapper. Meno linee sono migliori.

Non mi interessa l'input dell'utente (in questa fase), gli script target vengono eseguiti in modo non interattivo.

Lo snippet deve

  • output stdout per il log ed eco sempre alla console
  • emette stderr per il log ed echo per console se il debug è abilitato
  • i messaggi stderr devono essere preceduti da timestamp e altra utilità

Al momento ho il seguente che prova solo nelle versioni recenti di bash (4.2+?) Come in Ubuntu preciso, ma si comporta male su 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}

Poi questo...

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

Invece di echoposso chiamare una di quelle procedure di msg, ad es msg_con "hello world".
Anche l'output dello script andrà quindi su stderr impostando come variabile di ambiente al momento della chiamata, ad es  DEBUG_TEST=true myscript.

Ho letto che exec potrebbe non funzionare in alcune shell come busybox. C'è una combinazione mkfifo e fork su https://stackoverflow.com/a/5200754 che fa qualcosa di simile ma preferirei non usare fork se non assolutamente necessario.

Preferisci esempi bash per favore, ma qualcosa che funziona sotto sh o è più portatile sarebbe bello. Qualche idea?

Risposte:


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) ==="
}

Devi avere $ logfile impostato su qualcosa


Questo è abbastanza bello, nel modo in cui lo sto leggendo usi gawk per aggiungere le intestazioni dei messaggi. Ciò avrà l'ulteriore effetto collaterale di aggiungere anche quelli agli output dei comandi.
— Glenn,

Il motivo per usare gawk per aggiungere un timestamp (e ID processo) a ciascuna riga di registro è perché verrà eseguito ogni volta che viene scritto l'output e quindi aggiorna il timestamp. Inoltre è importante usare gawk e non awk perché penso che la funzione strftime sia un'estensione GNU.
— Angelo,

0

exec > filenamedovrebbe funzionare in sh, e in realtà funziona in busybox v1.15.3 (Nov 2011). Ma la sostituzione del processo >(command)è insostituibile poiché è estensione bash. Evita di usarlo negli script. Perché >>non è abbastanza per te?

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

Un'altra soluzione è specificare il reindirizzamento al di fuori dei tuoi script. Quando il tuo script viene invocato in background (da cron, o script di sistema, ecc.), Dovrebbero essere chiamati in questo modo

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

Quando invochi manualmente lo script e vuoi vedere l'output, chiamalo senza reindirizzamenti.


1
Chi pone la domanda vuole che l'output dello script vada sia alla console che al file di registro.

0

Questi due esempi faranno quali sono i tuoi obiettivi dichiarati

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

o

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

0

È possibile utilizzare il teecomando o scriptentrambi i comandi sono davvero utili.


lo script sembra interessante, ma in realtà non fa ciò di cui ho bisogno, il comportamento deve essere modificabile durante il runtime.
— Glenn,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.