linux - Bash:如何为 ssh 命令实时过滤 tee 输出?

标签 linux bash ssh tee

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

只要输出没有被过滤,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 命令?

最佳答案

问题很可能是 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)

关于linux - Bash:如何为 ssh 命令实时过滤 tee 输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24375752/

相关文章:

linux - 将默认端口重定向到 linux/unix 中的特定端口

bash - 如何使 .bashrc 别名在 vim ':!some_command' shell 命令中可用?

linux - Bash:将字符串添加到文件末尾而不换行

ubuntu - 使用 Chef 开源服务器部署带有密码的私有(private) git 存储库

git - 添加了 Cygwin ssh key ,但 Git 权限被拒绝(公钥)

c++ - 运行时链接库全局变量是否在加载了 dlopen 的插件之间共享?

regex - Python读取带有开始和停止条件的文件

linux - 创建路径名来检查文件不存在/权限被拒绝错误

ruby-on-rails - ruby on rails ssh连接而不提供密码

linux - 我们可以在 Debian 上安装 Unity 吗?