2012-01-04 14 views
8

actualmente estoy usando lo siguiente para capturar todo lo que va al terminal y tirarlo en un archivo de registro sin embargofiesta de color de camiseta quitar

exec 4<&1 5<&2 1>&2>&>(tee -a $LOG_FILE) 

, no quiero códigos de escape de color/desorden de entrar en el archivo de registro. así que tengo algo como esto que sorta funciona

exec 4<&1 5<&2 1>&2>&>(
    while read -u 0; do 
     #to terminal 
     echo "$REPLY" 
     #to log file (color removed) 
     echo "$REPLY" | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' >> $LOG_FILE 
    done 
    unset REPLY #tidy 
) 

excepto read esperas para retorno de carro que no es ideal para algunas porciones de la secuencia de comandos (por ejemplo echo -n "..." o printf sin \n).


Seguimiento de la respuesta de Jonathan Leffler:

Dado el script de ejemplo test.sh:

#!/bin/bash 

LOG_FILE="./test.log" 
echo -n >$LOG_FILE 

exec 4<&1 5<&2 1>&2>&>(tee -a >(sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > $LOG_FILE)) 


##### ##### ##### 
# Main 

echo "starting execution" 
printf "\n\n" 

echo "color test:" 
echo -e "\033[0;31mhello \033[0;32mworld\033[0m!" 
printf "\n\n" 

echo -e "\033[0;36mEnvironment:\033[0m\n foo: cat\n bar: dog\n your wife: hot\n fix: A/C" 
echo -n "Before we get started. Is the above information correct? " 
read YES 
echo -e "\n[READ] $YES" >> $LOG_FILE 
YES=$(echo "$YES" | sed 's/^\s*//;s/\s*$//') 
test ! "$(echo "$YES" | grep -iE '^y(es)?$')" && echo -e "\nExiting... :(" && exit 
printf "\n\n" 

#...some hundreds of lines of code later... 

echo "Done!" 


##### ##### ##### 
# End 

exec 1<&4 4>&- 2<&5 5>&- 

echo "Log File: $LOG_FILE" 
  1. La salida de la terminal es como se esperaba y no hay códigos de escape de color/desorden en el archivo de registro como desee. Sin embargo, al examinar test.log, no veo el [READ] ... (consulte la línea 21 de test.sh).

  2. El archivo de registro [de mi script bash real] contiene la línea Log File: ... al final, incluso después de cerrar los 4 y 5 fds. Pude resolver el problema al poner un sleep 1 antes del segundo exec - Supongo que hay una condición de carrera o chanchullos de FD a los que culpar. Desafortunadamente para ustedes, no puedo reproducir este problema con test.sh pero me interesaría cualquier especulación que alguien pueda tener.

+0

Tenga en cuenta que \ e ... códigos son específicos de VT100/VT200/etc. y pueden no ser los realmente emitidos por el programa en un tipo diferente de $ TERM. –

Respuesta

3

considerar el uso del programa de pee discutido en Is it possible to distribute stdin over parallel processes. Le permitiría enviar los datos de registro a través de su script sed, mientras sigue enviando los colores a la salida real.

Una ventaja importante de esto es que eliminaría el 'ejecutar sed una vez por línea de salida de registro'; eso es realmente diabólico para el rendimiento (en términos de cantidad de procesos ejecutados, si nada más).

+0

excelente! ¡gracias! 'exec 4 <&1 5<&2 1> & 2> &> (tee -a> (sed -r 's/\ x1B \ [([0-9] {1,2} (; [0-9] {1,2})?) ? [m | K] // g '> $ LOG_FILE)) ' – Andrew

+0

Consulte mi seguimiento – Andrew

1

Yo sé que no es una solución perfecta, pero cat -v hará caracteres no visibles como \x1B a convertir en forma visible como ^[[1;34m. La salida será desordenada, pero al menos será un texto ascii.

0

Puede intentar usar la opción -n para leer. Lee en n caracteres en lugar de esperar una nueva línea. Podrías configurarlo para uno. Esto aumentaría el número de iteraciones que ejecuta el código, pero no esperaría nuevas líneas.

Desde el hombre:

-n NCHARS read returns after reading NCHARS characters rather than waiting for a complete line of input.

Nota: No he probado esta

0

que utilizo para hacer cosas como esto estableciendo TERM=dumb antes de ejecutar mi mando. Eso prácticamente eliminó todos los caracteres de control a excepción de tab, CR y LF. No tengo idea si esto funciona para su situación, pero vale la pena intentarlo. El problema es que tampoco verás las codificaciones de color en tu terminal ya que es una terminal tonta.

También puede probar ya sea vis o cat (especialmente el parámetro -v) y ver si estos hacen algo por usted. Simplemente los había puesto en la canalización de la siguiente manera:

exec 4<&1 5<&2 1>&2>&>(tee -a | cat -v | $LOG_FILE) 

Por cierto, casi todos los programas de terminal tienen una opción para capturar la entrada, y lo más limpia para arriba para usted. ¿En qué plataforma estás y qué tipo de programa de terminal estás usando?

0

¿No podrían los comandos screen -L o script ser opciones viables en lugar de este ciclo de ejecución?

+0

¿podemos desactivar los caracteres de control con' pantalla'? – Stuart