Основные системные показатели на PHP
В этой статье я поделюсь своими способами извлечения и отображения на сайте системных показателей, как то: текущая загрузка процессора, потребление системной памяти и свапа, и количество занятого пространства на НЖМД.
Рассматриваться будет работа на Ubuntu Server. Под другие nix-системы тоже должно работать, но, возможно, с доработками. Windows серверы не рассматриваются вовсе.
Все решения сделаны "в лоб", без изысков и фанатичной минимализации/оптимизации. Я использовал jQuery для того, чтобы получить json посредством Ajax, и вывести его на страницу. Примеры простые, и могут быть переделаны под любой другой способ передачи/вывода. Итак...
1. Загрузка CPU
Начнем с самого сложного. Сложного потому, что мне не сразу удалось найти способ получения информации о загрузке процессора, а впоследствии, и не сразу найти способ ее обрабатывать. Первой мыслью была "использовать exec("top -n 1")", однако top не писал в стандартный вывод, а сохранение его (вывод) в файл на диск через '>', приводило к появлению огромного количества 'мусора', что сильно затрудняло последующий парсинг. В итоге, все свелось к чтению нужных файлов в виртуальной файловой системе, подключенной в /proc. Файл, в котором хранится информация о текущем использовании процессора называется /proc/stat. По сути, это не файл, а точка доступа к структурам данных ядра, но нам это знать не обязательно, потому что нам будет достаточно прочитать содержимое, а сделать это можно, как и в случае с простым файлом, через file(). Теперь можно привести кусочек кода, который эту информацию достает. После него я объясню, что было сделано, и зачем.
$file=file("/proc/stat"); $tmp=explode(" ",$file[0]); $cpu_user_old=$this->session->userdata("cpu_user"); $cpu_nice_old=$this->session->userdata("cpu_nice"); $cpu_sys_old=$this->session->userdata("cpu_sys"); $cpu_idle_old=$this->session->userdata("cpu_idle"); $cpu_io_old=$this->session->userdata("cpu_io"); $cpu_user=$tmp[2]; $cpu_nice=$tmp[3]; $cpu_sys=$tmp[4]; $cpu_idle=$tmp[5]; $cpu_io=$tmp[6]; $diff_used=($cpu_user-$cpu_user_old)+($cpu_nice-$cpu_nice_old)+($cpu_sys-$cpu_sys_old)+($cpu_io-$cpu_io_old); $diff_total=($cpu_user-$cpu_user_old)+($cpu_nice-$cpu_nice_old)+($cpu_sys-$cpu_sys_old)+($cpu_io-$cpu_io_old)+($cpu_idle-$cpu_idle_old); $cpu=$diff_used/$diff_total*100; $this->session->set_userdata(array("cpu_user"=>$cpu_user,"cpu_nice"=>$cpu_nice,"cpu_sys"=>$cpu_sys,"cpu_idle"=>$cpu_idle,"cpu_io"=>$cpu_io));
Объяснение начнем с содержимого файла:
> cat /proc/stat cpu 2255 34 2290 22625563 6290 127 456 0 0 cpu0 1132 34 1441 11311718 3675 127 438 0 0 cpu1 1123 0 849 11313845 2614 0 18 0 0 intr 114930548 113199788 3 0 5 263 0 4 [... еще куча цифр ...] ...
В первой строчке /proc/stat содержится информация о количестве потраченного процессором времени (усредненное для всех ядер/потоков) на выполнение (по порядку): процессов пользователя, высокоприоритетных процессов пользователя, системных процессов, простоя, ожидания ввода/вывода, аппаратных и программных прерываний. В следующих строках, начинающихся на 'cpu', приведены те же данные для каждого ядра/потока в отдельности. В нашем случае вся интересующая информация содержится в первой строке, поэтому дальше разбирать файл не будем.
В приведенном кусочке кода так же есть сохранение этих данных в сессию CodeIgniter. Это сделано для того, чтобы определять разницу (дельту) между текущими и предыдущими значениями показателей. Загрузка процессора представляет собой отношение времени, затраченного на процессы, к общему затраченному времени, включающему простой. Естественно, чем реже будут происходить эти запросы, тем сильнее будет усреднено значение загрузки процессора за это время.
2. Оперативная память
Информацию о количестве свободной оперативной памяти можно найти в файле /proc/meminfo:
> cat /proc/meminfo MemTotal: 2052604 kB MemFree: 246012 kB Buffers: 792332 kB Cached: 584716 kB ...
Отсюда мы будем брать две первые строчки, и извлекать из них цифры:
$file=file("/proc/meminfo"); $memory["total"]=substr($file[0],strpos($file[0]," "),strrpos($file[0]," ")-strpos($file[0]," ")); $memory["free"]=substr($file[1],strpos($file[1]," "),strrpos($file[1]," ")-strpos($file[1]," "));
Этот и последующие кусочки кода будут куда проще первого, и обширные пояснения им не потребуются. Здесь, например, все очевидно - мы просто "вырезаем" число, расположенное между двумя пробелами, для первой и второй строчки соответственно.
3. Swap file
Тут еще проще - берем строчку из /proc/swaps:
> cat /proc/swaps Filename Type Size Used Priority /dev/sda1 partition 7811064 2732 -1 ...
В нем перечислены все подключенные своп-файлы, их типы, объемы и занятое место. Нам просто надо "выдернуть" нужные цифры из нужных строк. В моем случае своп один, и строчку я обрабатываю одну:
$file=file("/proc/swaps"); $tmp=explode("\t",substr($file[1],strpos($file[1],"partition"))); $swap["total"]=$tmp[1]; $swap["free"]=$tmp[1]-$tmp[2];
Здесь пояснения тоже не нужны.
4. Жесткие диски
В моем примере будет приведен код, который извлекает информацию о количестве свободного места на дисках, точки монтирования которых находятся в /mnt. Ухищрения типа чтения и парсинга файлов из /proc здесь использовать не будут - для этой цели достаточно стандартных disk_free_space() и disk_total_space():
$drives=array(); if($dir=opendir("/mnt")){ while(false !== ($file = readdir($dir))) { $arr=array(); if(($file!=".")&&($file!="..")){ $arr["path"]="/mnt/".$file; $arr["free"]=disk_free_space("/mnt/".$file); $arr["total"]=disk_total_space("/mnt/".$file); $drives[]=$arr; } } }
5. Uptime
В качестве небольшого бонуса получим и продолжительность работы системы с последнего запуска:
$uptime=exec("uptime"); $uptime=explode(",",substr($uptime,strpos($uptime,"up")+3)); $time=explode(":",$uptime[1]); $uptime=$uptime[0]." ".$time[0]." hours ".$time[1]." minutes";
Совсем банальный подход - вызов exec(), и форматирование результата.
Вывод
Мы смогли получить всю интересующую нас информацию - о заполненности жестких дисков, о загрузке процессора, о состоянии памяти и свопа и даже о продолжительности работы сервера. Как выводить эту информацию, каждый может придумать сам, в зависимости от требований. Я же поделюсь способом, который использую сам...
Сперва я собираю полученные данные в ассоциативный массив и вывожу его как json:
$result["cpu"]=$cpu; $result["memory"]=$memory; $result["swap"]=$swap; $result["uptime"]=$uptime; json_encode($result);
На выходе получается следующее:
{"uptime":"34 days 5 hours 45 minutes","cpu":1.7361111111111,"memory":{"total":"2052604","free":"191424"},"swap":{"total":"7811064","free":7808332}}
И, уже в браузере, я работаю с результатом при помощи jQuery:
var json=$.parseJSON(data); $("#systemInfo").html("CPU: "+json.cpu+"<br />Memory free "+json.memory.free+" / "+json.memory.total);
Это один из простейших примеров. Более красивый вариант можно посмотреть тут.
Вот, собственно, и весь фокус. Если у вас есть дополнения или поправки, оставляйте их в комментариях.
Скачать standalone-вариант страницы статистики можно здесь.
Нет обратных ссылок на эту запись.

