Монитор процессов IIS для отображения процессов IIS w3wp.exe с их процессами PHP (php-cgi.exe)

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

Мне удалось сделать это без больших проблем, используя эти две команды:

using (var srvman = new ServerManager())
{
    workerProcesses = srvman.WorkerProcesses;
}

а также

processes = Process.GetProcesses().Where(processItem => processItem.ProcessName.Contains("w3wp") || processItem.ProcessName.Contains("php-cgi"))

Первый возвращает запущенные пулы приложений с идентификаторами процессов, а второй возвращает информацию о процессах из системы (так что здесь я получаю данные об использовании ЦП и памяти). Объединение этих двух сведений дает мне почти то, что я хочу. Единственным исключением являются приложения PHP, работающие в IIS.

Для приложений PHP создаются процессы php-cgi.exe, которые мне нужно сопоставить с рабочим процессом пула приложений IIS. У вас есть идеи, как связать php-cgi.exe процессы с их w3wp.exe родителями?

Вот пример вывода, который я хотел бы произвести:

1x w3wp.exe for site.com is using 15MB memory
4x php-cgi.exe is using 4x 15MB = 60MB memory

Я планирую суммировать эту информацию (что в этом сценарии будет составлять 75 МБ использования памяти для site.com).


person GrZeCh    schedule 12.01.2015    source источник
comment
Я отредактировал ваш пост, чтобы удалить теги из заголовка, чего избегают в StackExchange. См. раздел meta.stackexchange. ком/вопросы/19190/   -  person Mitch    schedule 12.01.2015
comment
Ok. Я буду помнить это.   -  person GrZeCh    schedule 12.01.2015


Ответы (1)


Вы можете получить PID родительского процесса, используя немного P/Invoke как описано Саймоном Мурье. Это недорогая операция и свяжет список всех php-cgi процессов с их создателями.

using (var srvman = new ServerManager())
{
    var procs = from worker in srvman.WorkerProcesses
                let workerProcess = Process.GetProcessById(worker.ProcessId)
                join cgi in Process.GetProcessesByName("php-cgi")
                    on workerProcess.Id equals ParentProcessUtilities.GetParentProcess(cgi.Handle).Id
                    into childProcesses
                select new
                {
                    Worker = worker,
                    WorkerProcess = workerProcess,
                    Children = childProcesses,
                    TotalMemoryUse = workerProcess.PrivateMemorySize64
                        + childProcesses.Sum(p => p.PrivateMemorySize64)
                };

    foreach (var proc in procs)
    {
        Console.WriteLine("Worker {0}:{1} using {2} total bytes", proc.Worker.AppPoolName,
            proc.Worker.ProcessId, proc.TotalMemoryUse);

        foreach (var child in proc.Children)
        {
            Console.WriteLine("\tphp-cgi process {0} using {1} bytes", child.Id, child.PrivateMemorySize64);
        }
    }
}

Выход

C:\drop> phpProcessTest.exe
Worker DefaultAppPool:4396 using 61530112 total bytes
    php-cgi process 3540 using 7024640 bytes
    php-cgi process 3144 using 6389760 bytes
person Mitch    schedule 12.01.2015
comment
Вот это да. Это было быстро. Я проверю это сегодня. Можете ли вы также помочь мне с мониторингом использования ЦП (текущего) с интервалом X (по умолчанию 60) секунд для w3wp и их вспомогательных процессов php-cgi? Мне было интересно, если в сценарии, где мы проверяем загрузку ЦП с интервалом в 60 секунд, 60 секунд — это 100% загрузка ЦП, а разница между TotalProcessorTime в 0 и 60 секунд — это реальное использование ЦП приложением в это время. - person GrZeCh; 12.01.2015
comment
Это работает, но похоже, что это слишком ресурсоемко. Я постараюсь сделать его светлее, если это возможно. Имейте в виду, что я пытаюсь запустить его в системе, где запущено около 600 процессов w3wp, и запросы ко всем из них используют ресурсы ЦП. - person GrZeCh; 12.01.2015
comment
Я думаю, что использование одной переменной списка процессов (public static Process[]processes = null;) обновляло каждую проверку и доступ к ней из всех частей кода, что решило высокий уровень использования. Я получаю доступ к этой переменной из предоставленного вами LINQ, а также из класса ParentProcessUtilities. - person GrZeCh; 12.01.2015
comment
@GrZeCh, Re: ЦП, который даст вам загрузку ЦП, но он не будет соответствовать тому, который вы видите в диспетчере задач, поскольку период выборки намного дольше. Не неправильный, просто другой. - person Mitch; 12.01.2015