【问题标题】:Bash: Split stdout from multiple concurrent commands into columnsBash:将标准输出从多个并发命令拆分为列
【发布时间】:2023-03-04 14:05:01
【问题描述】:

我在 bash 脚本中使用单个 & 符号运行多个命令,如下所示:

commandA & commandB & commandC

它们每个都有自己的 stdout 输出,但它们都混合在一起,使控制台陷入混乱。

我想知道是否有一种简单的方法可以将他们的输出通过管道传输到他们自己的列中......使用column 命令或类似的东西。 IE。类似:

commandA | column -1 & commandB | column -2 & commandC | column -3

这种东西是新手,但从最初的挖掘来看,似乎像 pr 这样的东西可能是票?还是column 命令...?

【问题讨论】:

  • 这在Unix & Linux Stackexchange 网站上可能会更好。
  • 嗯,谢谢...我不知道它存在。我可以在两个网站上打开相同的问题吗?很难知道要使用哪个站点,因为 SO 也有很多 bash 用户/脚本编写者。
  • 你能把它们放在临时文件中吗?

标签: linux bash shell


【解决方案1】:

很遗憾地回答了我自己的问题。

所提供的解决方案都不是我想要的。所以我开发了自己的命令行实用程序:multiview。也许其他人会受益?

它通过将进程的 stdout/stderr 传递到命令界面,然后启动“查看器”以在列中查看它们的输出来工作:

fooProcess | multiview -s & \
barProcess | multiview -s & \
bazProcess | multiview -s & \
multiview

这将显示其输出的整齐排列的列视图。您也可以通过在-s 标志后添加一个字符串来命名每个进程:

fooProcess | multiview -s "foo" & \
barProcess | multiview -s "bar" & \
bazProcess | multiview -s "baz" & \
multiview

还有一些其他的选择,但这就是它的要点。

希望这会有所帮助!

【讨论】:

    【解决方案2】:

    pr 是一个解决方案,但不是一个完美的解决方案。考虑一下,它使用process substitution<(command) 语法):

    pr -m -t <(while true; do echo 12; sleep 1; done) \
             <(while true; do echo 34; sleep 2; done)
    

    这会产生以下行进列:

    12                                  34
    12                                  34
    12                                  34
    12                                  34
    

    虽然这很容易提供您想要的输出,但列不会单独前进 - 当所有文件都提供相同的输出时,它们会一起前进。这很棘手,因为理论上第一列的输出应该是第二列的两倍。

    您可能希望研究以平铺模式调用 tmuxscreen 以允许列单独滚动。终端多路复用器将提供必要的机制来缓冲输出并独立滚动它,这在并排显示输出时非常重要,而不允许来自 commandB 的过多输出将 commandA 和 commandC 滚动到屏幕外。请记住,单独滚动每一列将需要大量的屏幕重绘,而避免屏幕重绘的唯一方法是让所有三列同时产生输出。

    作为最后的解决方案,考虑piping each output to a command that indents each column by a different number of characters

    this is something that commandA outputs and is
        and here is something that commandB outputs
    interleaved with the other output, but visually
    you might have an easier time distinguishing one
            here is something that commandC outputs
        which is also interleaved with the others
    from the other
    

    【讨论】:

    • 嗯,我认为这些都不完美。 pr 并不能完全解决我的输出问题,很难找到正确的列大小并且对齐似乎不正确。进程的数量也可能有所不同。我正在尝试在一个地方查看来自多个进程的多个 console.logs。就像您说的那样,使用 pr 需要同步输出,因此输出最终看起来很奇怪。但它是有效的。我实际上开始在节点中编写自己的实用程序,该实用程序具有我想要的界面并显示在独立的列中。但我明白你关于重绘整个屏幕的意思。效率不高!!
    • 感谢您的出色回答!关于缩进的最后一点实际上非常有效,但是对于具有大量输出的多个进程来说太混乱了。我也觉得终端多路复用器实际上可能是正确的答案,但我几乎想知道编写自己的实用程序是否比弄清楚并依赖可能存在或不存在于用户的屏幕或 tmux 之类的实用程序更容易系统。
    【解决方案3】:

    脚本打印出三个垂直行和一个计时器,每行包含一个脚本的输出。 评论您不理解的任何内容,并根据需要在我的答案中添加答案

    希望这会有所帮助:)

    #!/bin/bash
    #Script by jidder
    
    count=0
    Elapsed=0
    control_c()
    {
        tput rmcup
        rm tail.tmp
        rm tail2.tmp
        rm tail3.tmp
        stty sane
    }
    
    
    Draw()
    {
           tput clear
           echo "SCRIPT 1                                                                                                                     Elapsed time =$Elapsed seconds"
            echo "------------------------------------------------------------------------------------------------------------------------------------------------------"
            tail -n10 tail.tmp
            tput cup 25 0
    
            echo "Script 2                                                                                                                                                   "
            echo "------------------------------------------------------------------------------------------------------------------------------------------------------"
            tail -n10 tail2.tmp
            tput cup 50 0
    
            echo "Script 3                                                                                                                                                   "
            echo "------------------------------------------------------------------------------------------------------------------------------------------------------"
            tail -n10 tail3.tmp
    }
    
    
    Timer()
    {
            if [[ $count -eq 10  ]]; then
                    Draw
                    ((Elapsed = Elapsed + 1))
                    count=0
            fi
    
    
    }
    main()
    {
        stty -icanon time 0 min 0
        tput smcup
        Draw
        count=0
        keypress=''
        MYSCRIPT1.sh > tail.tmp &
        MYSCRIPT2.sh > tail2.tmp &
        MYSCRIPT3.sh > tail3.tmp &
    
        while [ "$keypress" != "q" ]; do
                sleep 0.1
                read keypress
                (( count = count + 2 ))
                Timer
        done
    
        stty sane
        tput rmcup
        rm tail.tmp
        rm tail2.tmp
        rm tail3.tmp
        echo "Thanks for using this script."
        exit 0
    }
    
    main
    
    trap control_c SIGINT
    

    【讨论】:

    • 哇。这真太了不起了!我希望你写它不是为了这个问题。我绝对可以制作临时文件。我决定使用节点和 unix 套接字构建我自己的类似东西。感谢您提供如此详尽的答案!
    猜你喜欢
    • 2011-02-02
    • 1970-01-01
    • 2010-12-10
    • 2021-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多