Убейте программу после того, как она выведет заданную строку, из сценария оболочки

Фон:

Я пишу тестовый скрипт для части программного обеспечения для вычислительной биологии. Программное обеспечение, которое я тестирую, может занять несколько дней или даже недель, поэтому у него есть встроенная функция восстановления, в случае сбоев системы или сбоев питания.

Я пытаюсь выяснить, как проверить систему восстановления. В частности, я не могу найти способ «сбой» программы контролируемым образом. Я подумывал о том, чтобы как-то выбрать инструкцию SIGKILL для запуска через некоторое время. Это, вероятно, не идеально, так как тестовый случай не гарантирует, что каждый раз он будет работать с одинаковой скоростью (он работает в общей среде), поэтому сравнение журналов с желаемым выходом будет затруднено.

Это программное обеспечение выводит строку для каждой секции анализа, которую она завершает.

Вопрос:

Мне было интересно, был ли хороший /элегантный способ (в сценарии оболочки) захватить вывод из программы, а затем убить программу, когда данная строка /# строк выводится программой?

9 голосов | спросил Paul 20 MarpmTue, 20 Mar 2012 23:39:09 +04002012-03-20T23:39:09+04:0011 2012, 23:39:09

5 ответов


3

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

command="prog -foo -whatever"
log="prog.log"
match="this is the what i want to match"

$command > "$log" 2>&1 &
pid=$!

while sleep 60
do
    if fgrep --quiet "$match" "$log"
    then
        kill $pid
        exit 0
    fi
done
ответил Kyle Jones 21 MaramWed, 21 Mar 2012 00:27:15 +04002012-03-21T00:27:15+04:0012 2012, 00:27:15
11

Если ваша программа завершится на SIGPIPE (это действие по умолчанию), этого должно быть достаточно, чтобы передать вывод в считыватель, который выйдет при чтении этой строки.

Итак, это может быть так же просто, как

$ program | sed -e '/Suitable text from the line/q'

Если вы хотите отключить вывод по умолчанию, используйте

$ program | sed -n -e '/Suitable text from the line/q'

Аналогично, если вы хотите остановиться после определенного количества строк, можно использовать голову вместо sed, например.

$ program | head -n$NUMBER_OF_LINES_TO_STOP_AFTER

Точное время, в которое происходит убийство , зависит от поведения буферизации терминала, как говорит stardt в комментариях.

ответил dmckee 21 MaramWed, 21 Mar 2012 01:41:32 +04002012-03-21T01:41:32+04:0001 2012, 01:41:32
6

В качестве альтернативы ответу dmckee команда grep с помощью -m (см., например, эта страница руководства ) также можно использовать:

compbio | grep -m 1 "Text to match"

, чтобы остановить, когда найдено 1 строка, соответствующая тексту, или

compbio | grep -v -m 10 "Text to match"

, чтобы ждать 10 строк, которые не соответствуют данному тексту.

ответил stardt 21 MaramWed, 21 Mar 2012 03:22:29 +04002012-03-21T03:22:29+04:0003 2012, 03:22:29
2

Вы можете использовать expect(1) , чтобы просмотреть исполняемый файл программы, а затем выполнить предопределенные действия над некоторыми шаблонами.

#!/usr/bin/env expect

spawn your-program -foo -bar 
expect "I want this text" { close }

Или однострочный для вложения в другой скрипт:

expect -c "spawn your-program -foo -bar; expect \"I want this text\" { close }"

Обратите внимание, что команда expect не входит в каждую ОС по умолчанию. Возможно, вам потребуется его установить.

ответил Jamesits 7 J000000Thursday16 2016, 03:33:11
1

Вы можете использовать оператор while:

Вам нужно подключить выходные данные вашего программного обеспечения (или его журналов), а затем для каждой новой строки выполнить условный тест, а затем запустить kill -KILL. Например (я тестировал с /var /log /messages в качестве файла журнала):

tail -f /var/log/messages | while read line; do test "$line" = "THE LINE YOU WANT TO MATCH" && kill PIDTOKILL; done

Или напрямую с программным обеспечением:

./biosoftware | while read line; do test "$line" = "THE LINE YOU WANT TO MATCH" && kill PIDTOKILL; done

Вам нужно изменить место пути /имя журнала, строку для соответствия и PID для уничтожения (вы также можете использовать killall).

Удачи вам в вашем программном обеспечении,

Уго,

ответил pistache 21 MaramWed, 21 Mar 2012 00:22:40 +04002012-03-21T00:22:40+04:0012 2012, 00:22:40

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132