2014-10-20 2 views
3

У меня есть центральный сервер, где я периодически запускаю скрипт (из cron), который проверяет удаленные серверы. Проверка выполняется последовательно, так что сначала один сервер, затем другой ....Запуск процесса из сценария bash не удалось

Этот скрипт (с центрального сервера) запускает другой скрипт (позволяет называть его update.sh) на удаленной машине, и что скрипт (на удаленной машине) делает что-то вроде этого:

processID=`pgrep "processName"` 
kill $processID 
startProcess.sh 

процесс был убит, а затем в сценарии startProcess.sh начал так:

pidof "processName" 

if [ ! $? -eq 0 ]; then 
    nohup "processName" "processArgs" >> "processLog" & 
    pidof "processName" 
    if [! $? -eq 0]; then 
     echo "Error: failed to start process" 
... 

update.sh, startprocess.sh и двоичном процесса, который начинается это на NFS монтируется с центрального сервера ,

Теперь, что происходит иногда, заключается в том, что процесс, который я пытаюсь запустить в startprocess.sh, не запускается, и я получаю ошибку. Странная часть состоит в том, что она случайна, когда-то процесс на одной машине запускается, а другое время на этой же машине не запускается. Я проверяю около 300 серверов, и ошибки всегда случайны.

Другое дело, что удаленные серверы расположены в 3 разных географических местоположениях (2 в Америке и 1 в Европе), центральный сервер находится в Европе. Из того, что я обнаружил до сих пор, является то, что серверы в Америке имеют гораздо больше ошибок, чем в Европе.

Сначала я подумал, что ошибка должна иметь какое-то отношение к убийству, поэтому я добавил сон между kill и startprocess.sh, но это не имело никакого значения.

Кроме того, кажется, что процесс от startprocess.sh не запускается вообще, или что-то с ним происходит прямо при его начала, потому что нет выхода в лог-файл и там должен быть выход в журнальный файл.

Итак, я прошу помощи

ли кто-нибудь имел такого рода проблемы, или знает, что может быть не так?

Спасибо за любую помощь

+1

Я подозреваю, что вы можете сделать лучше на [Server Fault] (http://serverfault.com/), чем на переполнение стека. Ваши симптомы звучат как трансатлантические связи, вероятно, медленнее, и операции NFS с большей вероятностью могут закончиться. Если программное обеспечение автоматизировано, возможно, что соответствующие каталоги недоступны, когда команды выходят из строя, но доступны, когда команды преуспевают; Я видел такие проблемы в предыдущей жизни. Там также есть «если у вас достаточно машин, что-то всегда терпит неудачу». Работает с тысячами машин, а не сотнями молотков, которые дома. –

ответ

4

(Извините, но мой первоначальный ответ был довольно неправильно ... Вот исправление)

Использование $?, чтобы получить статус завершения фонового процесса в startProcess.sh приводит к неправильному результату. Человек состояния:

Special Parameters 
?  Expands to the status of the most recently executed foreground 
     pipeline. 

Как Вы упомянули в своем комментарии правильный способ получения статуса выхода фонового процесса является использованием wait построен в Но для этого должен обрабатывать сигнал SIGCHLD..

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

Вот скрипт loop.sh для работы в качестве фонового процесса:

#!/bin/bash 
[ "$1" == -x ] && exit 1; 
cnt=${1:-500} 
while ((++c<=cnt)); do echo "SLEEPING [$$]: $c/$cnt"; sleep 5; done 

Если аргумент является -x, то он выходит с состоянием выхода 1 для имитации ошибки. Если arg равно num, то ждет num * 5 секунд печати SLEEPING [<PID>] <counter>/<max_counter> на стандартный вывод.

Второй сценарий запуска. Он начинается 3 loop.sh скриптов в фоновом режиме и выводит их состояние выхода:

#!/bin/bash 

handle_chld() { 
    local tmp=() 
    for i in ${!pids[@]}; do 
     if [ ! -d /proc/${pids[i]} ]; then 
      wait ${pids[i]} 
      echo "Stopped ${pids[i]}; exit code: $?" 
      unset pids[i] 
     fi 
    done 
} 

set -o monitor 
trap "handle_chld" CHLD 

# Start background processes 
./loop.sh 3 & 
pids+=($!) 
./loop.sh 2 & 
pids+=($!) 
./loop.sh -x & 
pids+=($!) 

# Wait until all background processes are stopped 
while [ ${#pids[@]} -gt 0 ]; do echo "WAITING FOR: ${pids[@]}"; sleep 2; done 
echo STOPPED 

Функция handle_chld будет обрабатывать SIGCHLD сигналы. Параметр настройки monitor позволяет для неинтерактивного скрипта получать SIGCHLD. Затем ловушка устанавливается для сигнала SIGCHLD.

Затем запускаются фоновые процессы. Все их PID запоминаются в массиве pids. Если SIGCHLD получен, он проверяется среди/proc/каталогов, дочерний процесс которых был остановлен (отсутствует) (его также можно было проверить, используя kill -0 <PID>). После ожидания статус выхода фонового процесса сохраняется в известной псевдо-переменной $?.

Главный сценарий ждет, пока все pids перестанут (иначе он не сможет получить статус выхода своих детей), и он остановится.

Пример вывода:

WAITING FOR: 13102 13103 13104 
SLEEPING [13103]: 1/2 
SLEEPING [13102]: 1/3 
Stopped 13104; exit code: 1 
WAITING FOR: 13102 13103 
WAITING FOR: 13102 13103 
SLEEPING [13103]: 2/2 
SLEEPING [13102]: 2/3 
WAITING FOR: 13102 13103 
WAITING FOR: 13102 13103 
SLEEPING [13102]: 3/3 
Stopped 13103; exit code: 0 
WAITING FOR: 13102 
WAITING FOR: 13102 
WAITING FOR: 13102 
Stopped 13102; exit code: 0 
STOPPED 

Можно видеть, что коды выхода сообщается правильно.

Надеюсь, это может помочь!

+0

Спасибо за вашу помощь, я сделал то, что вы написали, я также добавил, что ждать этого процесса «wait $ PID», если код возврата «ps -p $ PID», если не нуль, - что-то случилось с этим процессом. Когда я получу код возврата, я снова опубликую здесь – Jan

+0

@Jan: Не могли бы вы решить проблему? Что такое возвращаемый код ошибки? – TrueY

+0

@Jan: Не могли бы вы решить проблему? Что такое возвращаемый код ошибки? – TrueY

Смежные вопросы