2013-05-30 2 views
1

cmd1 | cmd2Сделать левую сторону трубы закончить, когда правая сторона заканчивается

Как я могу заставить команду отправки трубы прекратить работу, когда принимающая команда заканчивается?

cmd1 обрабатывает данные из файла, а его выходные данные передаются по каналу в cmd2.

cmd2 получает вывод cmd1 и выполняет некоторую обработку, которая выводится в файл. Он имеет возможность прекратить работу после того, как записано определенное количество байтов.

Проблема, с которой я сталкиваюсь, заключается в том, что cmd1 продолжает выполняться до тех пор, пока не обработает все данные в обрабатываемом файле, хотя cmd2 завершен.

Это может занять много времени и замедлить мой сценарий оболочки.


Конкретная объяснение того, что я делаю:

A «Суперагент» сетевой пробник устройство захвата трафика и хранить его в файлах на кольцевом буфере 6 часов. Это необработанные файлы захвата в том или ином формате. Собственная команда может быть использована для создания файлов pcap на основе временного диапазона. Это cmd1 сверху и называется «buildpcap»

6 часов трафика могут генерировать очень большой (200GB +) файл.

Я хочу ограничить общий pcap до 10 ГБ и разделить его на части размером 1 ГБ.

Я не могу ограничить вывод размера файла и не разбивать на несколько файлов с помощью buildpcap, но я могу выводить на stdout, а не файл, и передавать его команде, которая может; в этом случае дамппак wirehark, который является cmd2 сверху.

Я хочу, чтобы dumpcap генерировал 10 x 1G файлов, а затем завершался. Он делает это, но buildpcap продолжает работать на signficant количество времени

Фактические команды я использую следующие:

buildpcap --feed 3 --start-datetimed $ начать --end-DATETIME $ end --stdout | dumpcap -i - -w ./tmp.pcap -a файлы: 10 -b размер файла: 10000000

Надеюсь, это имеет смысл.

+0

Не могли бы вы в ближайшее время объяснить, что делают ваши cmd1 и 2? если вы попробуете 'yes | awk 'NR == 100 {exit}'', когда cmd2 (awk) заканчивается, команда 'yes' также заканчивается. – Kent

ответ

2

Это будет очень зависеть от того, кто/что означает cmd1, и насколько он был реализован. Например, если я делаю

find/-type f | less 

и из второго окна «pkill less» мой поиск завершается.

Edit:

Принимая комментарий к этому ответу и интегрировать его с ответом:

В этом случае я думаю, вы будете нуждаться в «сторожевой» сценарий, который отслеживает состояние процесса в Cmd2 и убивает cmd1, когда cmd2 завершается. Что-то вроде

watch -n 5 'pgrep cmd2 || pkill cmd1' 

должно делать. Он будет проверять cmd2 каждые секунды и убивать cmd1, если 2 ушел.

+0

buildpcap (проприетарная команда на сетевом зонде - cmd1) и dumpcap (from wirehark - cmd2). Я не думаю, что сборка хорошо написана. Некоторые из вариантов работают плохо, поэтому моя догадка заключается в том, что он не реализован. Какие параметры существуют, когда cmd1 плохо реализован? -Thx –

+1

В этом случае, я думаю, вам понадобится «сторожевой скрипт», который контролирует статус процесса cmd2 и убивает cmd1, когда cmd2 завершается. Что-то вроде ** watch -n 5 'pgrep cmd2 || pkill cmd1 '**. Он будет проверять cmd2 каждые секунды и убивать cmd1, если 2 ушел. – tink

+0

@tink Почему бы не превратить это в ответ? – Lorkenpeist

1

Если cmd1 пытается записать в трубопровод после выхода cmd2, он получит сигнал SIGPIPE. Ответ по умолчанию - выход (хотя возможно, что cmd1 был написан для обработки сигнала по-разному).

Однако, если cmd1 занят другими делами и не пытается писать в конвейер, он не будет уведомлен о выходе cmd2. Вот один обходной путь:

mkfifo cmd1-to-cmd2 
cmd1 > cmd1-to-cmd2 & cmd1PID=$! 
cmd2 < cmd1-to-cmd2; kill $cmd1PID 

Во-первых, вы создаете ФИФО (первый вошел, первый вышел) файл (также известный как именованный канал). Затем запустите cmd1 в фоновом режиме, перенаправляя его вывод на fifo. Помните его идентификатор процесса. Запустите cmd2, перенаправляя его ввод от fifo. Вместо трубопровода cmd1 непосредственно на cmd2 вы сделали это косвенно через именованный файл (следовательно, альтернативное имя fifo). Как только cmd2 выйдет, команда kill будет выполнена для остановки cmd1.

Если вам нужно, вы можете запустить cmd2 и следующее kill в фоновом режиме.

{ cmd2 < cmd1-to-cmd2; kill $cmd1PID; } & 
Смежные вопросы