Возвращаемое значение фонового процесса

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

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

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


person Anirudh    schedule 18.07.2011    source источник


Ответы (3)


Вы можете вложить фоновый процесс в скрипт. Например, если процесс, который вы хотите перевести в фоновый режим, называется foo:

#!/bin/sh

foo

if [ $? ]
then 
    # do something here if process failed
fi

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

person Community    schedule 19.07.2011

Вы можете использовать ловушки оболочки для вызова функции при выходе дочернего процесса путем перехвата SIGCHLD. Если запущен только один фоновый процесс, то можно wait для него в обработчике sigchld и там получить статус. Если запущено несколько фоновых дочерних элементов, все становится немного сложнее; вот пример кода (проверено только с bash):

set -m # enable job control
prtchld() {  
  joblist=$(jobs -l | tr "\n" "^")
  while read -a jl -d "^"; do
    if [ ${jl[2]} == "Exit" ] ; then 
      job=${jl[1]} 
      status=${jl[3]}  
      task=${jl[*]:4}
      break  
    fi  
  done <<< $joblist
  wait $job 
  echo job $task exited: $status
}
trap prtchld SIGCHLD

(sleep 5 ; exit 5) &
(sleep 1 ; exit 7) &

echo stuff is running

wait
person evil otto    schedule 19.07.2011

Мне больше нравится первый для моей цели, я предполагаю, что в «сделайте что-нибудь здесь, если процесс не удался» я могу убить скрипт, который вызвал этот скрипт-оболочку для foo, используя его имя.

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

Я запускаю процесс в фоновом режиме, как обычно, в основном скрипте, затем использую $! чтобы получить его pid (поскольку $! возвращает последний bg pid), заснуть на 2 секунды и выполнить команду ps -e | grep pid, чтобы проверить, продолжается ли процесс, основываясь на возвращаемом значении (ps -e | grep pid). Это хорошо работает для меня, потому что, если мой фоновый процесс прерывается, он делает это немедленно (поскольку адрес используется).

person Anirudh    schedule 20.07.2011