如何在bash脚本中以原子方式打印多个后台进程中的行?

时间:2011-07-06 00:42:18

标签: bash unix scripting

在bash函数中我写的是我通过ssh启动多个远程命令,让它们在不同的后台进程中运行。这些过程中的每一个都会产生许多行文本,这些行被合并在一起然后进行排序。我的问题是有时这些线混合在一起。即一行开始打印,在该行完成打印之前,另一行开始在同一行上打印。

我的问题是什么是使这个打印输出原子化的最简单的方法,以便各个线不会混合在一起(穿插整条线是好的 - 我只是希望列排成一行)?我有一个想法是保存每个并行后台进程的输出,然后按顺序合并它们,但是我无法使它工作(如果我知道如何正确地执行它,这个方法对我来说应该很好)。作为参考,这里是我正在尝试编写的脚本类型的概述:

foo() {
    (
        pids=()
        for x in "$@"
        do
            (
                ssh $x 'some-high-latency-command-with-200-lines-of-data-output'
            ) &
            pids+=( $! )
        done
        for x in "${pids[@]}"
        do
            wait $x
        done
    ) 2> /dev/null
}

3 个答案:

答案 0 :(得分:3)

我会将每个ssh运行重定向到自己的文件,然后将它们合并。我也不会使用wait循环; wait本身将等待所有后台处理流程,或者如果您真的只想要wait ${pids[*]}进程,则可以说ssh

答案 1 :(得分:2)

我最终偶然发现了一个似乎无法创建文件的解决方案。显然,如果我将ssh的输出分配给带有declare的变量,则会保留这些行,并且使用echo从此变量打印似乎是原子的。请参阅以下内容:

foo() {
    (
        pids=()
        for x in "$@"
        do
            (
                declare output=$(ssh $x 'some-command-with-multiline-output')
                echo "$output"
            ) &
            pids+=( $! )
        done
        wait ${pids[*]}
    ) 2> /dev/null
}

答案 2 :(得分:1)

使用某些程序在打印之前在本地重新组合行,例如:

ssh $x 'some-high-latency-command-with-200-lines-of-data-output' | perl -pe1