Zjištění dynamických veličin serveru pomocí PHP

Z ZděchovNET
Přejít na: navigace, hledání

Na webových stránkách Free WoWWorld of Warcraft serverů je užitečné zobrazit různé dynamické údaje o běhu. Ty lze s často jednoduše získat přímo pomocí jazyku PHP.

Linux

Většina informací o systému je dostupná a snadno přístupná ve virtuálním souborovém systému připojeném do adresáře /proc.

Zatížení procesoru

Tato funkce zjišťuje společné zatížení všech jader procesoru v procentech.

function CpuUsage()
{  
  global $cpuIDLEprev, $cpuSYSTprev, $cpuUSERprev;
  // get processor usage seconds for pct stats ###
  $File = fopen('/proc/stat', 'r');
  $Row = fgets($File);
  fclose($File);
  $Parts = explode(' ', $Row);
  $cpuUSER = $Parts[2] + $Parts[3];
  $cpuSYST = $Parts[4];
  $cpuIDLE = $Parts[5];
  $cpuUSERdiff = ($cpuUSER - $cpuUSERprev);
  $cpuSYSTdiff = ($cpuSYST - $cpuSYSTprev);
  $cpuIDLEdiff = ($cpuIDLE - $cpuIDLEprev);
  $cpuIDLEdiffTOTAL = (($cpuUSERdiff + $cpuSYSTdiff) + $cpuIDLEdiff);
  if ($cpuIDLEdiffTOTAL > 0)
  {
    $cpuUSERcent = ($cpuUSERdiff / $cpuIDLEdiffTOTAL) * 100;
    $cpuSYSTcent = ($cpuSYSTdiff / $cpuIDLEdiffTOTAL) * 100;
    $cpuIDLEcent = ($cpuIDLEdiff / $cpuIDLEdiffTOTAL * 100);
  } else
  {
    $cpuUSERcent = 0;
    $cpuSYSTcent = 0;
    $cpuIDLEcent = 0;
  }
  $cpuUSERprev = $cpuUSER;
  $cpuSYSTprev = $cpuSYST;
  $cpuIDLEprev = $cpuIDLE;
  return(100 - round($cpuIDLEcent * 100) / 100); // Truncate to two decimals
}

Využití paměti

Zjišťuje celkové využití paměti včetně stránkované paměti v odkládacím oddílu swap. Funkci je možné také upravit, aby četla pouze obsazení fyzické paměti. Výsledek je vrácen v bajtech.

function MemoryUsage()
{
  $Output = array();
  exec('free -b', $Output);
  $Row = $Output[2];
  while(strpos($Row, '  ') !== false) $Row = str_replace('  ', ' ', $Row);
  $RowParts = explode(' ', $Row);
  $Row = $Output[3];
  while(strpos($Row, '  ') !== false) $Row = str_replace('  ', ' ', $Row);
  $RowParts2 = explode(' ', $Row);
  return($RowParts[2] + $RowParts2[2]);  
}

Zatížení disku

Tato funkce zjišťuje zatížení pevného disku v procentech. Funkce využívá programu iostat obsaženého v balíčku sysstat. Parametrem funkce je označení sledovaného disku (sda, sdb, sdc, atd.).

function DiskUtilization($Disk = 'sda')
{
  $Output = array();
  exec('iostat -d '.$Disk.' -x -m 2 2', $Output);   // 2 second measure delay
  $Row = $Output[6];
  while(strpos($Row, '  ') !== false) $Row = str_replace('  ', ' ', $Row);  // Remove redundant spaces
  $Parts = explode(' ', $Row);
  $Value = str_replace(',', '.', $Parts[11]);
  return($Value);
}

Zatížení sítě

Vrácená hodnota je pole dostupných síťových rozhraní. Každá položka obsahuje dále údaje Down, Up, DownAverage, UpAvegage. Hodnoty jsou v bajtech za sekundu.

function GetNetworkState()
{  
  global $LastNetworkState;
  
  if(!isset($LastNetworkState)) $LastNetworkState = array();
  $NetworkState = array('Time' => time());
  $Output = array();
  exec('cat /proc/net/dev', $Output);
  array_shift($Output); // Skip header
  array_shift($Output); // Skip header
  foreach($Output as $Item)
  { 
    while(strpos($Item, '  ') !== false) $Item = str_replace('  ', ' ', $Item);  // Rrmove multiple spaces
    $Item = explode(':', $Item);
    $Interface = trim($Item[0]);
    $Item = explode(' ', trim($Item[1]));
    $NetworkState[$Interface] = array('Down' => $Item[0], 'Up' => $Item[8]);
    if(array_key_exists($Interface, $LastNetworkState))
    {
      $Period = time() - $LastNetworkState['Time'];
      $NetworkState[$Interface]['DownAverage'] = round(($NetworkState[$Interface]['Down'] - $LastNetworkState[$Interface]['Down']) / $Period);
      $NetworkState[$Interface]['UpAverage'] = round(($NetworkState[$Interface]['Up'] - $LastNetworkState[$Interface]['Up']) / $Period);
    } else
    {
      $NetworkState[$Interface]['DownAverage'] = 0;
      $NetworkState[$Interface]['UpAverage'] = 0;
    }
    if($NetworkState[$Interface]['DownAverage'] < 0) $NetworkState[$Interface]['DownAverage'] = 0;
    if($NetworkState[$Interface]['UpAverage'] < 0) $NetworkState[$Interface]['UpAverage'] = 0;
  }
  $LastNetworkState = $NetworkState;
  return($NetworkState);
}

Pro zobrazení pak použijeme:

$NetworkState = GetNetworkState();
echo('Odchozí data: '.$NetworkState['eth0']['Up'].' B/s');

Počet připojení síťovým službám

Tato funkce sleduje počet navázaných připojení na určitý port. K tomuto účelu se využívá systémový výpis všech síťových spojeních a jeho filtrace podle žádaného portu s vyloučením lokálních spojení. Sledovat lze např. počtu lidí připojených na TeamSpeak, který využívá port 8767.

function NetworkServiceConnectionCount($Port)
{
  $HostIP = gethostbyname(trim(`hostname`));
  $Output = array();
  exec('cat /proc/net/nf_conntrack|grep "dst='.$HostIP.' "|grep "dport='.$Port.' "|grep "ASSURED"', $Output);
  return(count($Output));
}

Volné místo na disku

Tento údaj lze zjistit přímo pomocí PHP a funkce disk_free_space. Např.

echo(disk_free_space('/'));

Odezva sítě

Odezvu(anglicky latency) nejčastěji měříme vůči českému peeringovému centru NIX.CZ, které sdružuje v jednom bodě mnoho různých poskytovatelů. Na odezvě sítě a tedy době, za jak dlouho doputují data tam i zpět, přímo závisí plynulost reakcí ve hře. Z časového grafu latence je pak možné vypozorovat také stabilitu sítě a zatížení sítě. Funkce vrací výsledek v milisekundách.

function Ping()
{  
  exec('ping nix.cz -c 1 -W 1|grep time=', $Row);  // W - timeout in seconds, c - ping count
  $Parts = explode(' ', $Row[0]);
  if(count($Parts) > 6)
  {
    $Time = $Parts[7];
    $TimeParts = explode('=', $Time);
    return($TimeParts[1]);
  } else return(0);
}

Stav síťového portu

Funkce pro zjištění zda je na dané ip otevřený určitý port.

function ErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
{
}  

function CheckPortStatus($Ip, $Port, $Timeout = 0.5)
{
  set_error_handler('ErrorHandler'); // Disable failed connection warning
  //error_reporting(0);
  if($Fp1 = fsockopen($Ip, $Port, $ERROR_NO, $ERROR_STR, (float)$Timeout))
  {
    fclose($Fp1);
    return(TRUE);
  } else
  {
    //echo($ERROR_NO.','.$ERROR_STR);
    return(FALSE);
  }
  restore_error_handler();
}

Klasicky se používá k zobrazení stavu serveru:

if(CheckPortStatus('localhost', 8085) echo('Online'); else echo('Offline');

Ale pomocí tohoto údaje lze také sledovat dostupnost emulátoru v procentech, pokud stav TRUE prohlásíme za 100 % a FALSE za 0 % a tyto hodnoty v průběhu času budeme průměrovat.

Doba běhu serveru

Vrací dobu od startu počítače v sekundách.

function SystemUptime()
{
  $File = fopen('/proc/uptime', 'r');
  $Uptime = fgets($File);
  fclose($File);
  $UptimeParts = explode(' ', $Uptime);
  return($UptimeParts[0]);
}

Systémová teplota

K zjištění teploty ze systémových snímačů se používá balík lm_sensors. Konkrétně pak program sensors pro určení aktuálních teplot a program sensors_detect pro provedení detekce přítomných měřicích obvodů většinou připojených přes sběrnici I2C.

function ProcessorTemperature($Sensor)
{
  $Output = array();
  exec('/usr/bin/sensors', $Output);
  foreach($Output as $Line)
  {
    if(substr($Line, 0, strlen($Sensor)) == $Sensor)
    {
      $Line = substr($Line, strpos($Line, '+') + 1);
      $Line = substr($Line, 0, strpos($Line, '°'));
      return($Line);
    }
  }
  return(0);
}

Windows

Doplnit varianty systémových skriptů pro Windows.

Volné místo na disku

Tento údaj lze zjistit přímo pomocí PHP a funkce disk_free_space. Např.

echo(disk_free_space('C:\'));

Údaje z databáze

Nejprve je nutné inicializovat databázové spojení před třídu mysqli.

$Database = new mysqli("localhost", "user", "password", "database");

Tyto funkce jsou vytvořeny pro emulátor MaNGOS. Pro ostatní emulátory je potřeba provést patřičné úpravy pro výběr data z databáze.

Počet hráčů online

function WoWPlayersOnline()
{
  global $Database;

  $Database->select_db('characters');
  $DbResult = $Database->query('SELECT COUNT(*) FROM characters WHERE online=1');
  $Row = $DbResult->fetch_array();
  return($Row[0]);
}

Počet GMGame Master online

function WoWGMOnline()
{
  global $Database;

  $Database->select_db('realmd');
  $DbResult = $Database->query('SELECT COUNT(*) FROM account WHERE online=1 AND gmlevel > 0');
  $Row = $DbResult->fetch_array();
  return($Row[0]);
}

Počet účtů

function WoWAccountCount()
{
  global $Database;

  $Database->select_db('realmd');
  $DbResult = $Database->query('SELECT COUNT(*) FROM account');
  $Row = $DbResult->fetch_array();
  return($Row[0]);  
}

Počet guild

function WoWGuildCount()
{
  global $Database;
 
  $Database->select_db('characters');
  $DbResult = $Database->query('SELECT COUNT(*) FROM guild');
  $Row = $DbResult->fetch_array();
  return($Row[0]);
}

Počet postav

function WoWCharacterCount()
{
  global $Database;

  $Database->select_db('characters');
  $DbResult = $Database->query('SELECT COUNT(*) FROM `characters`');
  $Row = $DbResult->fetch_array();
  return($Row[0]);
}

Počet restartů

function WoWEmulatorRestartCount()
{
  global $Database;

  $Database->select_db('mangos');
  $DbResult = $Database->query('SELECT COUNT(*) FROM uptime');
  $Row = $DbResult->fetch_array();
  return($Row[0]);
}

Doba běhu emulátoru

Funkce vrací dobu běhu od posledního startu emulátoru.

function MangosUptime()
{
  global $Database;

  $Database->select_db('mangos');
  $DbResult = $Database->query('SELECT `starttime`, `uptime` FROM `uptime` ORDER BY `starttime` DESC LIMIT 1');
  $Row = $DbResult->fetch_array();
  return($Row['uptime']);
}

Pokud je potřeba zobrazit informaci v čitelné podobě pro člověka, lze použít navíc tuto funkci. Ta zobrazí samostatně počet dní a k tomu hodiny a minuty.

funcion HumanReadableMangosUptime()
{ 
  $Uptime = MangosUptime();
  $Days = floor($Uptime / 3600 / 24);
  if($Days == 0) $DaysText = '';
  else if($Days == 1) $DaysText = $Days.' den';
  else if(($Days > 1) and ($Days < 5)) $DaysText = $Days.' dny';
  else if(($Days > 5)) $DaysText = $Days.' dnů';
  $Seconds = $Uptime - 3600;  // Korekce jedné hodiny, může se lišit
  return($DaysText.' '.date('G:i', $Seconds));
}

Počet běžících eventů

Funkce vrací počet aktuálně běžících MaNGOS in-game eventů.

function RunningEventCount()
{
  global $Database;

  $Count = 0;
  $Database->select_db('mangos');
  $DbResult = $Database->query('SELECT *, UNIX_TIMESTAMP(start_time) as start FROM game_event WHERE end_time > NOW() AND start_time < NOW()');
  while($Row = $DbResult->fetch_array())
  { 
    $Start = (floor((time() - $Row['start']) / ($Row['occurence'] * 60))) * $Row['occurence'] * 60 + $Row['start'];
    $End = $Start + $Row['length'] * 60;
    if((time() > $Start) and (time() < $End)) $Count++;
  }
  return($Count);
}

Externí odkazy

  • MRTG - Zaznamenávání grafů stavů routerů. Vyžaduje Perl a Linux.
  • phpSysInfo - Skript pro zobrazení informací o serveru.