12

我目前正在使用以下内容来捕获进入终端的所有内容并将其放入日志文件中

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

但是,我不希望颜色转义码/混乱进入日志文件。所以我有类似这样的东西

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
)

除了read等待回车,这对于脚本的某些部分(例如echo -n "..."printf没有\n)并不理想。


乔纳森·莱弗勒回答的后续行动:

给定示例脚本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. 终端的输出与预期一致,并且日志文件中没有所需的颜色转义码/杂乱。然而,在检查后test.log,我没有看到[READ] ...(见第 21 行test.sh)。

  2. [我的实际 bash 脚本的] 日志文件包含Log File: ...它末尾的行,即使在关闭 4 和 5 fds 之后也是如此。我能够通过sleep 1在第二个之前放置 a 来解决这个问题exec- 我认为这应该归咎于比赛条件或 fd 恶作剧。对你们来说不幸的是,我无法重现这个问题,test.sh但我会对任何人可能有的猜测感兴趣。

4

6 回答 6

6

考虑使用是否可以通过并行进程分发标准输入中pee讨论的程序。它允许您通过 sed 脚本发送日志数据,同时继续将颜色发送到实际输出。

这样做的一个主要优点是它将删除“sed每行日志输出执行一次”;这对性能来说真的很糟糕(就执行的进程数量而言,如果没有别的)。

于 2012-01-04T02:08:06.240 回答
2

我知道这不是一个完美的解决方案,但cat -v会让不可见的字符像\x1B转换成可见的形式一样^[[1;34m。输出会很乱,但至少是 ascii 文本。

于 2012-01-04T00:32:00.287 回答
1

TERM=dumb我过去常常在运行我的命令之前通过设置来做这样的事情。这几乎删除了除制表符、CR 和 LF 之外的所有控制字符。我不知道这是否适合您的情况,但值得一试。问题是您也不会在终端上看到颜色编码,因为它是一个哑终端。

您也可以尝试其中一个viscat(尤其是-v参数),看看这些是否对您有用。您只需像这样将它们放入您的管道中:

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

顺便说一句,几乎所有的终端程序都有一个捕获输入的选项,并且大多数都会为您清理它。你在什么平台上,你使用什么类型的终端程序?

于 2012-01-04T02:25:27.927 回答
0

您可以使用 ANSIFilter 来去除或转换带有 ANSI 转义序列的控制台输出。

http://www.andre-simon.de/zip/download.html#ansifilter

于 2012-01-04T02:09:44.577 回答
0

您可以尝试使用 -n 选项进行读取。它读取 n 个字符而不是等待换行。您可以将其设置为一个。这会增加代码运行的迭代次数,但它不会等待换行符。

来自男人:

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

注意:我没有测试过这个

于 2012-01-04T02:02:23.957 回答
0

可能不是screen -Lscript命令是可行的选项而不是这个 exec 循环?

于 2012-01-04T02:52:26.753 回答