Скрипт мониторинга принадлежности процесса в OpenVZ-контейнере из CT0
Скриптик на память, назначение которого было мониторить принадлежность php-процессов, запущенных через fast_cgi внутри контейнера в OpenVZ, при этом сам скрипт запускается из нулевого контейнера и в случае, если совсем уж все плохо - рестартит контейнер.
Основная проблема в том, что PID'ы процессов внутри контейнера мапятся на другие PID'ы "снаружи", поэтому для контроля процессов создается таблица соответствия pid'ов.
Цель скрипта - снимать "потерявшиеся" процессы, возникшие в результате краша процесса Апача (в том случае, когда процесс или целое дерево процессов становится потомками init'a внутри контейнера)
Для проверяемых процессов просматривается имя родительского процесса. Единственный процесс, родитель которого init - процесс Апача, виртуальный (внутренний) PID которого находится в /var/run/apache2.pid, все остальные являются для него дочерними. Соответственно, если это не так - процесс убивается.
#!/bin/bash
# ID контейнера
ctid='107'
# Log
logname='/root/c107check.log'
# Если контейнер выключен - не пытаться работать с процессами
if [ "$(/usr/sbin/vzlist -H $ctid -o status)" != 'running' ]
then
exit
else
# PID корневого Апача "изнутри" контейнера
ravp="$(cat /vz/root/$ctid/var/run/apache2.pid)"
# Создаем таблицу процессов контейнера
# PID_реальный PID_родителя_в_контейнере PID_виртуальный команда
data="$(/root/bin/ovzps $ctid -o pid,command --no-header |
while read pid cmd
do
echo $pid $(awk '/^VPid/{vp=$2}; /^PPid/{pp=$2}; END {print pp, vp}' /proc/$pid/status) $cmd
done)"
# Реальный PID init'a в контейнере
initps="$(awk '/ init /{print $1}' <<< "$data")"
# Реальный PID корневого процесса Апача
rarp="$(awk '/'" $initps $ravp "'/{print $1}' <<< "${data}")"
# Создаем список процессов, для которых родительский процесс - init контейнера, исключая корневой процесс Апача
lostprocess="$(
echo "$data" | grep -E "php5-cgi|apache2|ispcp-apache-logger" |
grep -v " $initps $ravp" | awk '/'" $initps "'/{print $1}'
)"
# Если список таких процессов не пустой - убиваем их
if [ ! -z "${lostprocess}" ]
then
echo $(date +%Y.%m.%d" "%H:%M:%S) ${lostprocess} >> "$logname"
kill -9 ${lostprocess}
fi
# Проверяем существование корневого процесса Апача. Если после апокалипсиса никто не выжил - перезапускаем контейнер
kill -0 "$rarp" || { /usr/sbin/vzctl restart $ctid ; echo $(date +%Y.%m.%d" "%H:%M:%S) container restarted >> "$logname" ; }
fi
Скрипт ссылается на /root/bin/ovzps, код которого ниже:
#!/bin/bash
ctid=${1:-0}
shift
ps $* -p $(grep -l "^envID:[[:space:]]*$ctid\$" /proc/[0-9]*/status |
sed -e 's=/proc/\([0-9]*\)/.*=\1=')