Как использовать сценарий оболочки, чтобы контролировать программу? - PullRequest
5 голосов
/ 22 июля 2010

Я искал вокруг, но не совсем нашел то, что я ищу. В двух словах, я создал bash-скрипт для запуска в бесконечном цикле while, спящего режима и проверки, запущен ли процесс. Единственная проблема - даже если процесс запущен, он говорит, что это не так, и открывает другой экземпляр.

Я знаю, что мне следует проверять по имени процесса, а не по идентификатору процесса, поскольку другой процесс может подключиться и получить идентификатор. Однако в моей системе все Perl-программы называются Perl5.10.0, и я намерен открыть несколько экземпляров одной и той же Perl-программы.

Следующее «если» всегда возвращает false, что я здесь не так делаю ???

while true; do

 if [ ps -p $pid ]; then
  echo "Program running fine"
  sleep 10

 else
  echo "Program being restarted\n"
  perl program_name.pl &
  sleep 5
  read -r pid < "${filename}_pid.txt"
 fi

done

Ответы [ 5 ]

9 голосов
/ 22 июля 2010

Избавьтесь от квадратных скобок. Должно быть:

if ps -p $pid; then

Квадратные скобки являются синтаксическим сахаром для команды test. Это совершенно другой зверь и совсем не вызывает ps:

if test ps -p $pid; then

На самом деле это выдает «-bash: [: -p: ожидается двоичный оператор», когда я его запускаю.

7 голосов
/ 22 июля 2010

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

Во-первых, вы должны выяснить, почему ваша программа в первую очередь умирает; этот скрипт не исправляет ошибку, он пытается ее скрыть.

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

добавлено в ответ на комментарий :

Конечно, есть технические трудности, но, как отмечено в ОП, в этой попытке решения все еще есть ошибка:

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

Так что теперь у вас есть скрипт отслеживания PID, а не процесс "няня". Хотя шансы невелики, сценарий в его нынешнем виде имеет окно длиной в десять секунд, в котором

  1. «отслеживаемый» процесс завершается неудачей
  2. Я запускаю свой недельный процесс emacs, который получает тот же PID
  3. сценарий няни продолжает блаженно не подозревая, что его зависимый не удалось

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

while true ; do
    if perl program_name.pl ; then
         echo "program_name terminated normally, restarting"
    else
         echo "oops program_name died again, restarting"
    fi
done

Что не только короче и проще, но и фактически блокирует условие, которое вас действительно интересует: состояние выполнения perl-программы. Исходный сценарий неоднократно проверяет неверное указание прокси-сервера о состоянии состояния выполнения (PID) и поэтому может ошибиться. И, поскольку вся цель этого скрипта няни состоит в том, чтобы обрабатывать ошибки, было бы плохо, если бы он был сам по себе дефектным.

3 голосов
/ 22 июля 2010

Я полностью согласен, что возиться с PID почти всегда плохая идея.Сценарий while true ; do ... done довольно хорош, однако для производственных систем есть пара супервизоров процессов, которые делают именно это и многое другое, например,

  • позволяют отправлять сигналы контролируемому процессу (не зная, что этоPID)
  • проверить, как долго сервис работал или нет
  • захватывает свои выходные данные и записывает его в файл журнала

Примерами таких супервизоров процессов являются daemontools или runit .Более подробное обсуждение и примеры см. В Сценарии инициализации, которые считаются вредными .Не беспокойтесь под заголовком: традиционные сценарии инициализации страдают от той же проблемы, что и вы (они запускают демон, сохраняют его PID в файле, а затем оставляют демон в покое).

1 голос
/ 25 июля 2010

Я согласен, что вы должны выяснить, почему ваша программа в первую очередь умирает.Тем не менее, постоянно работающий сценарий оболочки, вероятно, не очень хорошая идея.Что если этот контролирующий сценарий оболочки погибнет? (И да, избавьтесь от квадратных скобок вокруг ps -p $pid. Требуется статус выхода команды ps -p $pid. Квадратные скобки заменяют команду test.)

Существует два возможных решения:

  1. Используйте cron, чтобы запустить «контролирующий» сценарий оболочки, чтобы увидеть, работает ли процесс, который вы курируете, все еще, а если нет,перезапустите его.Контролируемый процесс может вывести свой PID в файл.Ваша контролирующая программа может затем отследить этот файл и получить PID для проверки.

  2. Если контролируемая вами программа предоставляет службу для определенного порта, сделайте ее службой inetd.Таким образом, он вообще не работает, пока к этому порту не поступит запрос.Если вы установите его правильно, он прекратит работу, когда он не нужен, и перезапустится, когда это необходимо.Занимает меньше ресурсов, и ОС будет обрабатывать все для вас.

0 голосов
/ 22 июля 2010

Для этого предназначен kill -0 $ pid.Возвращает успех, если существует процесс с pid $ pid.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...