linux - Bash:如何干净地记录 ssh/bash 输出的处理行?

标签 linux bash logging ssh escaping

我用 tee 和 grep 编写了一个 linux bash 脚本来记录和时间戳我在各种 ssh session 中采取的操作。它有效,但记录的行有时会混合在一起并且充满控制字符。我怎样才能正确地转义控制和其他在原始 session 中不可见的字符并分别记录每一行?

我正在学习 bash 和 linux 界面,因此非常欢迎任何其他改进脚本的建议!

这是我的脚本(用作 ssh 命令的包装器):

#! /bin/bash
logfile=~/logs/ssh.log
desc="sshlog ${@}"
tab="\t"
format_line() {
    while IFS= read -r line; do
        echo -e "$(date +"%Y-%m-%d %H:%M:%S %z")${tab}${desc}${tab}${line}"
    done
}
echo "[START]" | format_line >> ${logfile}
# grep is used to filter out command line output while keeping commands
ssh "$@" | tee >(grep -e '\@.*\:.*\$' --color=never --line-buffered | format_line >> ${logfile})
echo "[END]" | format_line >> ${logfile}

这是日志文件中乱码输出的屏幕截图:

enter image description here

关于解决方案的注释:Tiago 的回答很好地处理了非打印字符。不幸的是,我刚刚意识到困惑是由退格键和使用向上和向下键完成命令引起的。也就是说,字符一出现就被管道传输到 grep,而不是逐行。我将不得不在 another question 中询问这个问题.

更新:figured out a way to (几乎总是)处理向上/向下完成、退格完成和控制字符。

最佳答案

您可以删除这些字符:

perl -lpe 's/[^[:print:]]//g'

未过滤:

perl -e 'for($i=0; $i<=255; $i++){print chr($i);}' | cat -A
^@^A^B^C^D^E^F^G^H^I$
^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?M-^@M-^AM-^BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^KM-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^VM-^WM-^XM-^YM-^ZM-^[M-^\M-^]M-^^M-^_M- M-!M-"M-#M-$M-%M-&M-'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3M-4M-5M-6M-7M-8M-9M-:M-;M-<M-=M->M-?M-@M-AM-BM-CM-DM-EM-FM-GM-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-UM-VM-WM-XM-YM-ZM-[M-\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-oM-pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^?

过滤:

perl -e 'for($i=0; $i<=255; $i++){print chr($i);}' | perl -lpe 's/[^[:print:]]//g'  | cat -A
$
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~$

解释:

  1. 我正在打印整个 ASCII 表:

    perl -e 'for($i=0; $i<=255; $i++){print chr($i);}'

  2. 我正在识别不可打印的字符:

    cat -A

  3. 我正在过滤不可打印的字符:

    perl -lpe 's/[^[:print:]]//g'

编辑:在我看来,您需要删除 ANSI 颜色字符:

例子:

 perl -MTerm::ANSIColor -e 'print colored("yellow on_magenta","yellow on_magenta"),"\n"'| sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" | perl -lpe 's/[^[:print:]]//g'

适应您的代码:

format_line() {
    while IFS= read -r line; do
        line=$(sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" <<< "$line")
        line=$(perl -lpe 's/[^[:print:]]//g' <<< "$line")
        echo -e "$(date +"%Y-%m-%d %H:%M:%S %z")${tab}${desc}${tab}${line}"
    done
}

我还编辑了您的 grep 命令:

ssh "$@" | tee >(grep -Po '(?<=\$).*' --color=never --line-buffered | format_line >> ${logfile})

在我的测试输出下面:

2014-06-26 10:11:10 +0100   sshlog tiago@localhost  [START]
2014-06-26 10:11:15 +0100   sshlog tiago@localhost  whoami
2014-06-26 10:11:16 +0100   sshlog tiago@localhost  exit
2014-06-26 10:11:16 +0100   sshlog tiago@localhost  [END]

关于linux - Bash:如何干净地记录 ssh/bash 输出的处理行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24418130/

相关文章:

linux - 如何通过换行符或字符读取输入?

C# Azure Functions 和 Application Insights - LogError 未显示异常

java - 具有不同数据类型的日志消息

linux - 如何查看有关新加载的外部 Linux 内核模块的信息?

bash - 有没有一种简单的方法可以确定用户输入是否是 bash 中的整数?

linux - Linux 系统监视器如何获取进程统计信息

linux - 如何在捕获 pid 的同时将 ssh 远程命令分配给 bash 变量

javascript - Chrome 中的同步控制台日志记录

python - 是否可以输出和监视标准输入、标准输出和标准错误以外的流? (Python)

c - 套接字上带有 sendfile 的管道 C 损坏