14

Фон:

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

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

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

Вопрос:

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

5 ответов5

13

Если ваша программа завершит работу в 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 в комментариях.

7

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

compbio | grep -m 1 "Text to match"

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

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

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

5

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

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
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 команда ожидаемости не поставляется с каждой ОС по умолчанию. Возможно, вам придется установить его.

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).

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

Hugo,

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