3

У меня есть большое количество больших файлов (сотни файлов, сотни МБ каждый), которые мне нужно передать через несколько программ для их фильтрации и преобразования. Я использую преимущества нескольких ядер ЦП, поэтому я запускаю несколько экземпляров одного и того же канала для каждого файла (может быть до ста ядер и может использовать ssh как часть канала в случае, если это имеет какое-то значение для ответ). Я хочу контролировать каждую трубу, и я использую pv для этого. Вот минимальный пример того, что у меня есть:

$ pv file-001.gz | gunzip | xz > file-001.xz
1.58GB 0:00:02 [ 713MB/s] [=================================>] 100%

В действительности, я также делаю несколько других вещей в конвейере, включая передачу данных на другие машины через ssh и передачу их через фильтры на этих машинах, но конвейер всегда заканчивался перенаправлением в новый файл на главном хосте. Кроме того, ни одна стадия в канале не требует полного набора данных; они могут работать построчно или по частям.

В настоящее время мне нужно отдельное окно терминала для каждого экземпляра канала. То, что я хотел бы сделать, это запустить n параллельных экземпляров канала в одном терминале / оболочке и получить выходные данные каждого экземпляра pv в отдельной строке. Что-то вроде этого:

1.48GB 0:00:54 [ 704MB/s] [===============================>  ]  97% ETA 00:00:06
1.58GB 0:01:00 [ 713MB/s] [=================================>] 100%
0.75GB 0:00:31 [ 709MB/s] [================>                 ]  50% ETA 00:00:29

Значение для n будет количеством строк, которые я могу разместить в окне терминала, скажем, 3-50 или около того. Точный формат отчета о ходе работы не важен, поскольку он включает скорость, процент выполнения, прошедшее время и приблизительное оставшееся время. Также не важно, что я использую pv , можно использовать какую-то другую программу, если я могу легко установить ее или просто обычную оболочку (желательно bash). Что важно, тем не менее, это то, что метод может обрабатывать случайные поломанные трубы в случае, если часть трубы по какой-то причине рушится. Я также хотел бы начинать новые задания каждый раз, когда задание завершается (успешно или нет), и все еще остаются необработанные файлы.

Есть идеи, как это сделать?

Обратите внимание, что я уже пробовал GNU Parallel, но его функции ssh, по-видимому, предполагают, что каждый входной файл сначала передается на удаленный хост, затем обрабатывается, а затем переносится обратно, чего я хочу избежать из-за большого объема данных и ограниченный объем пространства на каждом узле обработки.

2 ответа2

4

Вы смотрели на --pipe для GNU Parallel?

cat bigfiles* | pv | parallel --pipe -S server1,server2 'cat | process_pipe'

(кошка включена для акцента)

По умолчанию используется размер блока 1 МБ, который можно настроить с помощью --block.

- редактировать для 1-1 корреспонденции -

Исходя из вышеизложенного, вы можете получить 1-1 переписку следующим образом:

parallel --eta "cat {} | parallel --pipe -S server1,server2 'cat | process_pipe' > {}.out" ::: bigfiles*

(кошка включена для акцента)

Это не совсем оптимально, так как внутренняя параллель не будет знать о своих братьях и сестрах и, следовательно, может появиться больше на server1, чем server2. Одним из способов избежать этого является -j1 на внешней параллели, но это не будет оптимальным, если у внутреннего достаточно блоков только для первого сервера. Другими словами: чтобы идеально сбалансировать вашу рабочую нагрузку, вам, возможно, придется немного поиграться с этим - возможно, даже использовать - нагрузка 100% или аналогичная.

--- редактировать: справиться со сбоями ---

Если process_pipe возвращается с ошибкой, то следует повторить команду еще 2 раза:

parallel --retries 3 --eta "cat {} | parallel --pipe -S server1,server2 'cat | process_pipe' > {}.out" ::: bigfiles*
3

Есть идеи, как это сделать?

Нет.

У pv есть опции -c и -N, которые позволят вам делать то, что вы хотите

$ pv -cN source access.log | gzip | pv -cN gzip > access.log.gz
source:  760MB 0:00:15 [37.4MB/s] [=>     ] 19% ETA 0:01:02
  gzip: 34.5MB 0:00:15 [1.74MB/s] [  <=>  ]

но я не вижу, как применить эту функцию к нескольким конвейерам


Однако, если вы посмотрите на справочную страницу для PV, вы увидите это

          (tar cf - . \
           | pv -n -s $(du -sb . | awk '{print $1}') \
           | gzip -9 > out.tgz) 2>&1 \
          | dialog --gauge 'Progress' 7 70

Таким образом, вы можете расширить это для параллельного запуска ряда задач, если это возможно для просмотра прогресса в кластере небольших окон. Я бы попробовал Xdialog.

В настоящее время мне нужно отдельное окно терминала для каждого экземпляра канала

Моя главная мысль в том, что вам не нужно интерактивно открывать множество окон терминала, вы можете иметь один скрипт, открывающий множество диалоговых окон.


Всё ещё ищете ответ? Посмотрите другие вопросы с метками .