bash и stdout - записывают части stdout в несколько файлов одновременно - PullRequest
0 голосов
/ 08 октября 2019

У меня есть длительный процесс, в котором я хотел бы записывать части его вывода в различные файлы, как это происходит.

Я думал, что мог бы написать что-то вроде этого:

  • вывод в стандартный вывод
  • захват всех выходных данных в файле /tmp/
  • запись всех строк, соответствующих 3, в файл /tmp/2
$ output_data_constantly | tee /tmp/1 | grep 3 > /tmp/2

но, похоже, не работает - ничего не выводится на стандартный вывод

Есть предложения?

output_data_constantly

#!/usr/bin/env bash
for i in {1..10000}; do
  echo $i ;
  sleep 0.25;
done

РЕДАКТИРОВАТЬ: обратите внимание, что я наMac, и моя версия Bash:

GNU bash, version 4.4.19(1)-release (x86_64-apple-darwin17.3.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Ответы [ 3 ]

1 голос
/ 08 октября 2019
$ output_data_constantly | tee /tmp/1 | grep 3 | tee /tmp/2

Вы не дали выходу возможность попасть на экран. Вставьте еще один тройник, чтобы отправлять выходные данные на /tmp/2 и stdout вместо всех на /tmp/2.

Также обратите внимание, что вы можете не получать выходные данные в «реальном времени», поскольку они могут буферизоваться вместепуть.

Пример:

$ (yes | nl | head -10000) | tee /tmp/1 | grep 3 | tee /tmp/2 | wc -l
    3439
$ wc -l /tmp/1 /tmp/2
   10000 /tmp/1
    3439 /tmp/2
   13439 total

Возможно, попробуйте буферизацию строки grep, если вы хотите вывод до того, как буфер заполнится. На моем компьютере это сделано с --line-buffered, но может отличаться на вашем.

0 голосов
/ 08 октября 2019

Вот еще один способ, который я нашел, чтобы сделать это, который, возможно, не идеален, но, кажется, работает для моего варианта использования. Может быть, это не сработает для долго выполняющихся процессов с большим количеством вывода?

#!/usr/bin/env bash
rm -f /tmp/2
rm -f /tmp/1

while IFS= read -r line; do 
  echo "$line" | grep 3 >> /tmp/2
  echo "$line" | tee -a /tmp/1
done < <(output_data_constantly)

Примечание: идея извлечена из ответа на этот похожий вопрос по stackoverflow

0 голосов
/ 08 октября 2019

grep потребляет вывод tee, поэтому tty ничего не остается. Это можно изменить, используя подстановку процесса, но все равно ничего не будет записано в /tmp/2 до тех пор, пока output_data_constantly не остановится. Вам нужно запустить grep в режиме буферизации строки, для этого вам потребуется GNU grep, например:

output_data_constantly | tee /tmp/1 >(grep --line-buffered 3 >/tmp/2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...