Как атомарно печатать строки из нескольких фоновых процессов в скрипте bash? - PullRequest
5 голосов
/ 06 июля 2011

В написанной мной функции 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 ]

3 голосов
/ 06 июля 2011

Я бы перенаправлял каждый ssh прогон в свой собственный файл и впоследствии объединял их. Я также не использовал бы цикл wait; wait сам по себе будет ждать всех фоновых процессов, или вы можете сказать wait ${pids[*]}, если вы действительно хотите только ssh процессов.

2 голосов
/ 06 июля 2011

Я наконец наткнулся на решение, которое работает без создания файлов.По-видимому, если я назначу вывод 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
}
1 голос
/ 06 июля 2011

используйте некоторую программу для локальной компоновки строк перед их печатью, например:

ssh $x 'some-high-latency-command-with-200-lines-of-data-output' | perl -pe1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...