Жгут тестирования, использующий серверный процесс

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

Я написал сценарий bash, который, кажется, работает, но не совсем идеален.

if [ -z `pgrep -x server-process` ]; then
  mkdir ./data
  server-process ./data &
  sleep 1; # Wait for server to print output,
           # reporting initialization details etc.
fi

# Set up environment variables...

run-test-suite $@

if jobs %1 2>/dev/null; then
  kill %1
  rm -R ./data;
fi

В частности:

  • Есть ли более надежный способ сделать это?
  • Есть ли какие-то крайние случаи, которые я пропустил?
  • Есть ли лучший способ подождать server-processисходный результат, а не sleep 1 (который в любом случае часто бывает недостаточно длинным)? server-process не закрывает канал — он все равно может сообщать об ошибках — я не возражаю, если они чередуются с выходными данными набора тестов. Я просто хочу подождать, пока сервер не распечатает исходную информацию о конфигурации.

2 ответа
2

Захват вывода pgrep и проверка того, что он пуст, не кажется лучшим способом использовать эту утилиту, учитывая, что она возвращает истинное значение, когда находит один или несколько процессов:

if ! pgrep -x server-process >/dev/null 2>&1
then
  mkdir ./data
  server-process ./data &
  sleep 1; # Wait for server to print output,
           # reporting initialization details etc.
fi

Использование спецификаций вакансий с %1 удобство для интерактивных оболочек. Мы можем написать более надежный код, используя $!:

server_pid=0

if
then
    server-process ./data &
    server_pid=$!
fi

Это имеет то преимущество, что портативный — т.е. мы можем использовать /bin/sh как переводчик, а не требовать /bin/bash.

Фактически, вместо того, чтобы запоминать pid и условно использовать его в конце скрипта, мы можем сразу зарегистрировать действие, которое нужно предпринять:

if
then
    server-process ./data &
    trap "kill $!; rm -r ./data" EXIT
fi

Если нет веской причины для создания каталога данных внутри текущего рабочего каталога, вероятно, лучше использовать mktemp чтобы создать нам красивый пустой начальный каталог.


Собираем все вместе:

#!/bin/sh

set -eu

if ! pgrep -x server-process >/dev/null 2>&1
then
    data_dir=$(mktemp -d)
    server-process "$data_dir" &
    trap "kill $!; rm -r '$data_dir'" EXIT
    sleep 1; # Wait for server to initialise
fi

run-test-suite "$@"

Не зная подробностей server-process Я могу только догадываться, но, возможно, есть лучшая альтернатива произвольному sleep. Возможно, существует файл, чье появление в $data_dir может указывать на то, что сервер можно использовать? Или сокет, который начинает отвечать?

    Добро пожаловать в Code Review, Ари.

    Хорошо

    • отступ
    • полезные комментарии

    Основные предложения

    • Что касается вашего серверного процесса: было бы неплохо, если бы у него был соответствующий сценарий «init» для его запуска. В systemd-land все изменилось, и вы должны следовать этому стилю, если ваша система основана на systemd. В любом случае, правильная настройка init / systemd упростит жизнь вашим администраторам и разработчикам.
    • Если вы находитесь в systemd-land, тогда ваш systemctl start позаботится об ожидании начала процесса. Если вы находитесь в зоне инициализации, вам нужно будет найти другой способ проверить, что процесс запущен. Есть ли сообщение журнала, которого вы можете дождаться, или сокет, который вы можете проверить? Если вы просто ждете вывода, перенаправьте его в файл и дождитесь, пока он что-нибудь будет содержать. Как-нибудь найдите что-нибудь для проверки и зацикливайтесь, пока это не произойдет.
    • Как только у вас будет чистый способ его запуска, вы можете удалить фоновый фон на своем серверном процессе и засыпание после него. Команда запуска (в любом стиле) не должна завершаться, пока ваш процесс не будет запущен.
    • Ваш сценарий запуска также должен обрабатывать остановку, поэтому вам не нужно больше проверять, работает ли он. Просто запустите свой скрипт с аргументом stop (или запустите systemctl), и он исчезнет. Если он умер раньше, вы можете получить сообщение. Но тогда вы можете удалить дерево данных.

    Маленькие гниды

    • Не нужно заканчивать строки точкой с запятой. Оболочка принимает каждую строку как команду, если в конце строки нет обратной косой черты. Используя точку с запятой, поставьте then в той же строке, что и if хорошо. Это один из часто встречающихся примеров помещения нескольких команд в одну строку.
    • Используйте двойные квадратные скобки для условных выражений, чтобы избежать сюрпризов.
    • Попробуйте shellcheck. В нем будут некоторые предложения, которые я не учел.
    • Поместите каталог в переменную, а затем обратитесь к этим переменным вместо ./data.

      Добавить комментарий

      Ваш адрес email не будет опубликован. Обязательные поля помечены *