【问题标题】:How to limit output from a potentially too verbose command?如何限制可能过于冗长的命令的输出?
【发布时间】:2017-04-24 18:38:00
【问题描述】:

我正在寻找一个 bash sn-p 来限制可能变得过于冗长的 shell 命令的控制台输出量。

这样做的目的是在构建/CI 环境中使用,您确实希望限制控制台输出的数量,以防止 CI 服务器过载(甚至是客户端拖尾输出)。

全部要求:

  • 仅从命令输出的顶部(头部)开始最多显示 100 行
  • 从命令输出的底部(尾部)最多只显示 100 行
  • stdoutstderr 全部归档到command.log.gz 文件中
  • 控制台输出必须相对实时显示,最后输出结果的解决方案是不可接受的,因为我们需要能够看到它的执行进度。

目前的发现

  • unbuffer 可用于强制 stdout/stderr 无缓冲
  • |& tee 可用于将输出发送到归档器和尾部/头部
  • |& gzip --stdout >command.log.gz 可以存档控制台输出
  • head -n100tail -n100 可用于限制控制台输出,如果输出行数低于 200,它们至少会引入一些问题,例如不希望的结果。

【问题讨论】:

  • [ -f command.log.gz ] && gunzip command.log.gz; somecommand > tmp && (( $(wc -l <tmp) > 100 )) && { head -n100 tmp; tail -n100 tmp; } || cat tmp; cat tmp >> command.log; gzip command.log; rm tmp

标签: bash stdout


【解决方案1】:

据我了解,您需要在线限制输出(在生成时)。 这是一个我能想到的对你有用的函数。

limit_output() {
    FullLogFile="./output.log"  # Log file to keep the input content
    typeset -i MAX=15   # number or lines from head, from tail
    typeset -i LINES=0  # number of lines displayed

    # tee will save the copy of the input into a log file
    tee "$FullLogFile" | {
        # The pipe will cause this part to be executed in a subshell
        # The command keeps LINES from losing it's value before if
        while read -r Line; do
            if [[ $LINES -lt $MAX ]]; then
                LINES=LINES+1
                echo "$Line"    # Display first few lines on screen
            elif [[ $LINES -lt $(($MAX*2)) ]]; then
                LINES=LINES+1   # Count the lines for a little longer
                echo -n "."     # Reduce line output to single dot
            else
                echo -n "."     # Reduce line output to single dot
            fi
        done
        echo ""     # Finish with the dots
        # Tail last few lines, not found in head and not more then max
        if [[ $LINES -gt $MAX ]]; then
            tail -n $(($LINES-$MAX)) "$FullLogFile"
        fi
    }
}

在脚本中使用它,将其加载到当前 shell 或放入 .bash_profile 以在用户会话中加载。

使用示例:cat /var/log/messages | limit_output./configure | limit_output

该函数将读取标准输入,将其保存到日志文件中,显示前 MAX 行,然后在屏幕上将每一行缩小为一个点 (.),最后显示最后 MAX 行(如果输出则更少比 MAX*2 短)。

【讨论】:

    【解决方案2】:

    这是我当前的不完整解决方案,为方便起见,它演示了处理 10 行输出,并且(希望)将输出限制为前 2 行和后 2 行。

    #!/bin/bash
    
    seq 10 | tee >(gzip --stdout >output.log.gz) | tail -n2
    

    【讨论】:

      【解决方案3】:

      我用来实现此目的的一种方法是:

      ./configure | tee output.log | head -n 5; tail -n 2 output.log

      这是做什么的:

      1. 使用tee 将完整的输出写入名为output.log 的文件中
      2. 使用head -n 仅打印前 5 行
      3. 最后使用tail -n打印output.log的最后两行

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-16
        • 2011-02-24
        • 1970-01-01
        • 2017-03-11
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 2018-09-14
        相关资源
        最近更新 更多