Как перезапустить процесс в bash или убить его по команде?

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

Объединив несколько сообщений (которые я считаю лучшими практиками, например, не используйте файл PID), я получаю следующее:

#!/bin/bash

DESC="Foo Manager"
EXEC="python /myPath/bin/FooManager.pyc"

trap "BREAK=1;pkill -HUP -P $BASHPID;exit 0" SIGHUP SIGINT SIGTERM

until $EXEC
do
    echo "Server $DESC crashed with exit code $?.  Restarting..." >&2
    ((BREAK!=0)) && echo "Breaking" && exit 1
    sleep 1
done

Итак, теперь, если я запущу этот скрипт в одном файле xterm. А затем в другом xterm я отправляю скрипт примерно так:

kill -HUP <tracking_script_pid>  # Doesn't work.
kill -TERM <tracking_script_pid>  #Doesn't work.

Сценарий отслеживания не заканчивается или что-то еще. Если я запущу FooManager.pyc из командной строки, он умрет на SIGHUP и SIGTERM. В любом случае, что я мог сделать здесь неправильно, и, возможно, есть совершенно другой способ сделать это?

Благодарю.


person Bitdiot    schedule 22.12.2014    source источник
comment
Я полагаю, что это интересно как упражнение на bash, но если вы пытаетесь сделать это для чего-то реального, просто найдите бригадира: ddollar.github.io/Foreman   -  person Charlie Martin    schedule 22.12.2014


Ответы (1)


Из руководства:

Если Bash ожидает завершения команды и получает сигнал, для которого установлена ​​ловушка, ловушка не будет выполняться до тех пор, пока команда не завершится. Когда Bash ожидает асинхронную команду через wait встроенный, прием сигнала, для которого была установлена ​​ловушка, вызовет немедленный возврат встроенной функции wait со статусом выхода больше 128, сразу после чего ловушка будет выполнена.

Акцент мой.

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

Чтобы исправить это, вам нужно запустить свою программу как задание и дождаться его. Если ваша программа никогда не завершается с кодом возврата больше 128, вы можете упростить следующий код, но я не делаю такого предположения:

#!/bin/bash

desc="Foo Manager"
to_exec=( python "/myPath/bin/FooManager.pyc" )

trap 'trap_triggered=true' SIGHUP SIGINT SIGTERM

trap_triggered=false
while ! $trap_triggered; do
   "${to_exec[@]}" &
   job_pid=$!
   wait $job_pid
   job_ret=$?
   if [[ $job_ret = 0 ]]; then
      echo >&2 "Job ended gracefully with no errors... quitting..."
      break
   elif ! $trap_triggered; then
      echo >&2 "Server $desc crashed with exit code $job_ret. Restarting..."
   else
      printf >&2 "Received fatal signal... "
      if kill -0 $job_pid >&/dev/null; then
          printf >&2 "killing job $job_pid... "
          kill $job_pid
          wait $job_pid
      fi
      printf >&2 "quitting...\n"
   fi
done

Примечания.

  1. Я использовал имя переменной в нижнем регистре, поскольку верхний регистр считается плохой практикой: они могут конфликтовать с зарезервированными именами Bash или переменными среды.
  2. Я использовал не строку для хранения команды, а массив. Со строкой у вас будет много проблем, если вы хотите, чтобы забавные символы, такие как пробелы, передавались в качестве аргументов. С правильно цитируемым массивом у вас не будет никаких проблем. (Некоторые утверждают, что было бы даже лучше использовать функцию.)
person gniourf_gniourf    schedule 22.12.2014
comment
Спасибо за это. По большей части это работает, мне пришлось внести в него некоторые изменения, чтобы он действительно убивал FooManager.pyc, как только скрипт отслеживания получал перехваченный вызов. в любом случае большое спасибо!! - person Bitdiot; 23.12.2014
comment
Несколько других вопросов: есть ли способ отличить плохой выход из FooManager, который не вызывает ловушку? FooManager может дать сбой, и было бы неплохо иметь возможность сказать, когда это произойдет, а не получать сигнал для завершения сценария отслеживания. - person Bitdiot; 23.12.2014
comment
@Bitdiot в предыдущей версии я забыл убить задание. Пожалуйста, просмотрите мое редактирование: вы увидите, где и как это сделать. - person gniourf_gniourf; 23.12.2014
comment
Круто, это потрясающий человек, спасибо. Можете ли вы сказать мне, что делает kill -0? Исследуя эту проблему, я вижу все эти аргументы, которые есть у kill, но когда я делаю по ним man-страницу, ни один из них не описан. По крайней мере, я не могу найти. :) - person Bitdiot; 23.12.2014
comment
@Bitdiot см. здесь для объяснения kill -0. - person TTT; 23.12.2014