twixed.ru huh… nothing interesting here

12Окт/110

Основные системные показатели на 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-вариант страницы статистики можно здесь.

Post to Twitter Post to Digg Post to Facebook Post to Google Buzz Send Gmail Post to LinkedIn

Комментарии (0) Пинги (0)

Пока нет комментариев.


Leave a comment

Нет обратных ссылок на эту запись.