Bash: Split stdout from multiple concurrent comman

2020-06-04 03:45发布

I am running multiple commands in a bash script using single ampersands like so:

commandA & commandB & commandC

They each have their own stdout output but they are all mixed together and flood the console in an incoherent mess.

I'm wondering if there is an easy way to pipe their outputs into their own columns... using the column command or something similar. ie. something like:

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

New to this kind of thing, but from initial digging it seems something like pr might be the ticket? or the column command...?

标签: linux bash shell
3条回答
我欲成王,谁敢阻挡
2楼-- · 2020-06-04 04:22

Regrettably answering my own question.

None of the supplied solutions were exactly what I was looking for. So I developed my own command line utility: multiview. Maybe others will benefit?

It works by piping processes' stdout/stderr to a command interface and then by launching a "viewer" to see their outputs in columns:

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

This will display a neatly organized column view of their outputs. You can name each process as well by adding a string after the -s flag:

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

There are a few other options, but thats the gist of it.

Hope this helps!

查看更多
Deceive 欺骗
3楼-- · 2020-06-04 04:22

pr is a solution, but not a perfect one. Consider this, which uses process substitution (<(command) syntax):

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

This produces a marching column of the following:

12                                  34
12                                  34
12                                  34
12                                  34

Though this trivially provides the output you want, the columns do not advance individually—they advance together when all files have provided the same output. This is tricky, because in theory the first column should produce twice as much output as the second one.

You may want to investigate invoking tmux or screen in a tiled mode to allow the columns to scroll separately. A terminal multiplexer will provide the necessary machinery to buffer output and scroll it independently, which is important when showing output side-by-side without allowing excessive output from commandB to scroll commandA and commandC off-screen. Remember that scrolling each column separately will require a lot of screen redrawing, and the only way to avoid screen redraws is to have all three columns produce output simultaneously.

As a last-ditch solution, consider 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
查看更多
劫难
4楼-- · 2020-06-04 04:39

Script print out three vertical rows and a timer each row containing the output from a single script. Comment on anything you dont understand and ill add answers to my answer as needed

Hope this helps :)

#!/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
查看更多
登录 后发表回答