【问题标题】:Bash: how to filter tee output in realtime for ssh command?Bash:如何为 ssh 命令实时过滤 tee 输出?
【发布时间】:2014-06-23 22:43:53
【问题描述】:

我的目标是为我的 ssh 会话中使用的命令制作一个带时间戳的日志。

只要输出未被过滤,Tee 就会实时工作。当我 tail -F test.log 时,以下命令会实时追加输出:

#!/bin/bash
ssh "$@" | tee -a test.log

但是,当我尝试通过this question 中建议的方法修改 tee 的输出时,输出不再是实时的。例如:

#!/bin/bash
ssh "$@" | tee >(grep -e '.*\@.*\:.*\$.*' --color=never >> test.log)

奇怪的是,如果我用“yes”命令代替 ssh 命令,输出会被实时正确过滤。

实时处理很重要,因为我的脚本需要将当前时间戳附加到每一行并尽可能多地删除输出。到目前为止,这是我的脚本:

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

我该如何解决这个问题,为什么 ssh 命令对 tee 的作用与 yes 命令不同?

【问题讨论】:

    标签: linux bash ssh tee


    【解决方案1】:

    问题很可能是grep 正在缓冲它的输出——选择大块输入,过滤它们,然后输出结果——所以它平滑地处理yes 的输出(因为yes 快速生成了很多用于过滤和输出的输入),而您的 ssh 命令可能不会快速生成那么多输出。

    grep 的许多版本都提供了一种机制来调整这种缓冲。由于您使用的是 Linux,因此您可能会使用 GNU Grep,它为此提供了一个 --line-buffered 标志(请参阅 the "Other Options" section of the GNU Grep Manual),因此输出一次只缓冲一行:

    ssh "$@" | tee >(grep -e '.*\@.*\:.*\$.*' --color=never --line-buffered >> test.log)
    

    【讨论】:

    • 如果您使用 awk 而不是 grep 您将使用 fflush(); 。这个问题是相关的:stackoverflow.com/questions/21098382/…
    • @ruakh 我已经测试了你的 tee 输出重定向命令 一般来说:'some command' | tee >( 'some filtering' > 'output' ) 它使用 /bin/bash 工作。但是我在 /bin/sh 中使用它时遇到了语法错误,例如:语法错误:“(”意外。有什么建议吗?感谢您的支持 :)
    • @GrayFox:这里的进程替换(>(...) 功能)实际上是问题所在——我只是在此处包含它以在上下文中显示--line-buffered 选项——所以我认为它已经关闭-这个问题的主题,询问如何在不支持它的外壳中近似进程替换。幸运的是,您不需要问:这个问题已经链接到 stackoverflow.com/q/12205250/978917,其中有几个答案显示了基于 -process-substitution-based 的方法。
    猜你喜欢
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 2011-01-15
    • 1970-01-01
    • 2022-08-16
    相关资源
    最近更新 更多