Script για παρακολούθηση φόρτου server - είναι αξιόπιστο και σωστό;

Σε αυτή την περιοχή μπορείτε να βρείτε ή να αναζητήσετε πληροφορίες σχετικές με την PHP

Συντονιστές: WebDev Moderators, Super-Moderators, PHP Moderators

Απάντηση
Άβαταρ μέλους
philos
Δημοσιεύσεις: 260
Εγγραφή: 30 Αύγ 2007 23:32

Script για παρακολούθηση φόρτου server - είναι αξιόπιστο και σωστό;

Δημοσίευση από philos » 21 Μάιος 2017 23:44

Ύστερα από έρευνα στο διαδίκτυο, κατέληξα να συνθέσω το ακόλουθο script.
Όταν ο χρήστης πατάει το κουμπί MONITORING SERVER, τότε αρχίζε μία setInterval που δείχνει "ζωντανά" με AJAX την κατάσταση των πόρων του server.

Η ερωτήσεις μου:
1. Οι πιο ειδικοί πως το βλέπετε το script; Δίχνει όντως σωστά αποτελέσματα;
2. Δοκίμασα να το τρέξω σε localhost (XAMPP - Windows 10) και φαίνονται σωστά τα αποτελέσματα, όμως όταν το έβαλα στο site (VPS, Linux), το CPU load παίρνει μονίμως τιμές 0,κάτι ή 0,0κάτι. Έτσι, για την περίπτωση που δεν είναι Windows το OS, έβαλα πολλαπλασιασμό επί 100. Ελπίζω να είναι όντως αυτή η σωστή τιμή που προκύπτει.
3. Στο Linux/VPS η RAM φαίνεται μονίμως στο 90% κάτι, που δεν είμαι τόσο σίγουρος ότι είναι σωστό γιατί και δεν στέκει και στο Webmin βλέπω "REAL RAM" στο 35%. Τι λάθος υπάρχει στον υπολογισμός της RAM για την περίπτωση του Linux;
4. Το να χτυπάει το serverload.php πολλές φορές, καταναλώνει από μόνο του πολλούς πορούς; Στα πόσα δευτερόλεπτα λέτε να το βάλω για να έχει νόημα; Σίγουρα η μικρότερη τιμή είναι η πιο "live", όμως εντάξει δε μπορώ να το βάλω και 500ms. :-) Μόνο εγώ ως διαχειριστής θα το βλέπω και δεν θα τρέχει αυτόματα onload, γι αυτό έβαλα κουμπί.

Ορίστε το script:
PHP

Κώδικας: Επιλογή όλων

function get_server_load() {
    $load = '';
    if (stristr(PHP_OS, 'win')) {
        $cmd = 'wmic cpu get loadpercentage /all';
        @exec($cmd, $output);
        if ($output) {
            foreach($output as $line) {
                if ($line && preg_match('/^[0-9]+$/', $line)) {
                    $load = $line;
                    break;
                }
            }
        }

    } else {
        $sys_load = sys_getloadavg();
        $load = $sys_load[0];
    }
    return $load;
}

function getServerMemoryUsage($getPercentage=true)
{
        $memoryTotal = null;
        $memoryFree = null;

        if (stristr(PHP_OS, "win")) {
            // Get total physical memory (this is in bytes)
            $cmd = "wmic ComputerSystem get TotalPhysicalMemory";
            @exec($cmd, $outputTotalPhysicalMemory);

            // Get free physical memory (this is in kibibytes!)
            $cmd = "wmic OS get FreePhysicalMemory";
            @exec($cmd, $outputFreePhysicalMemory);

            if ($outputTotalPhysicalMemory && $outputFreePhysicalMemory) {
                // Find total value
                foreach ($outputTotalPhysicalMemory as $line) {
                    if ($line && preg_match("/^[0-9]+\$/", $line)) {
                        $memoryTotal = $line;
                        break;
                    }
                }

                // Find free value
                foreach ($outputFreePhysicalMemory as $line) {
                    if ($line && preg_match("/^[0-9]+\$/", $line)) {
                        $memoryFree = $line;
                        $memoryFree *= 1024;  // convert from kibibytes to bytes
                        break;
                    }
                }
            }
        }
        else
        {
            if (is_readable("/proc/meminfo"))
            {
                $stats = @file_get_contents("/proc/meminfo");

                if ($stats !== false) {
                    // Separate lines
                    $stats = str_replace(array("\r\n", "\n\r", "\r"), "\n", $stats);
                    $stats = explode("\n", $stats);

                    // Separate values and find correct lines for total and free mem
                    foreach ($stats as $statLine) {
                        $statLineData = explode(":", trim($statLine));

                        //
                        // Extract size (TODO: It seems that (at least) the two values for total and free memory have the unit "kB" always. Is this correct?
                        //

                        // Total memory
                        if (count($statLineData) == 2 && trim($statLineData[0]) == "MemTotal") {
                            $memoryTotal = trim($statLineData[1]);
                            $memoryTotal = explode(" ", $memoryTotal);
                            $memoryTotal = $memoryTotal[0];
                            $memoryTotal *= 1024;  // convert from kibibytes to bytes
                        }

                        // Free memory
                        if (count($statLineData) == 2 && trim($statLineData[0]) == "MemFree") {
                            $memoryFree = trim($statLineData[1]);
                            $memoryFree = explode(" ", $memoryFree);
                            $memoryFree = $memoryFree[0];
                            $memoryFree *= 1024;  // convert from kibibytes to bytes
                        }
                    }
                }
            }
        }

        if (is_null($memoryTotal) || is_null($memoryFree)) {
            return null;
        } else {
            if ($getPercentage) {
                return (100 - ($memoryFree * 100 / $memoryTotal));
            } else {
                return array(
                    "total" => $memoryTotal,
                    "free" => $memoryFree,
                );
            }
        }
}

function getNiceFileSize($bytes, $binaryPrefix=true) {
        if ($binaryPrefix) {
            $unit=array('B','KB','MB','GB','TB','PB');
            if ($bytes==0) return '0 ' . $unit[0];
            return @round($bytes/pow(1024,($i=floor(log($bytes,1024)))),2) .' '. (isset($unit[$i]) ? $unit[$i] : 'B');
        } else {
            $unit=array('B','KB','MB','GB','TB','PB');
            if ($bytes==0) return '0 ' . $unit[0];
            return @round($bytes/pow(1000,($i=floor(log($bytes,1000)))),2) .' '. (isset($unit[$i]) ? $unit[$i] : 'B');
        }
}
	
$memUsage = getServerMemoryUsage(false);

$output = array();
$output['cpu_load'] = get_server_load();
$output['memory_total'] = $memUsage['total'];
$output['memory_free'] = $memUsage['free'];
$output['memory_usage'] = $memUsage['total'] - $memUsage['free'];
exit(json_encode($output));
HTML

Κώδικας: Επιλογή όλων

<script>
function enable_server_monitoring()
{
	$('#monitor_server_info').show();
	$('#monitor_server_button').hide();
	setInterval(function(){ sc_show_server_load(); }, 5000);
}
function sc_show_server_load()
{
		$.ajax({
			url : "serverload.php",
			type: "GET",
			data: {
				//
			},
			dataType: "json",
			error: function(xhr, textStatus, errorThrown){
					//
			},
			success: function(data, textStatus, jqXHR){
					if (!data) { return false; }
					for (b in data) {
						if (b == 'cpu_load')
						{
							var cpu_load_percentage = data[b];
						}
						else if (b == 'memory_total')
						{
							var memory_total = data[b];
						}
						else if (b == 'memory_free')
						{
							var memory_free = data[b];
						}
						else if (b == 'memory_usage')
						{
							var memory_usage = data[b];
						}
					}	

					// do progress bars
					$( "#progressbar_cpu_usage" ).width(((cpu_load_percentage*195)/100));	
					$('#cpu_usage_per').html(cpu_load_percentage + '%');
					
					// memory usage
					var memory_usage_percentage = (memory_usage*100/memory_total);
					$('#memory_usage_per').html(Math.round(memory_usage_percentage* 100)/100 + '%');
					$( "#progressbar_memory_usage" ).width((memory_usage_percentage*195)/100);
			  }					
		});	
}

</script>
<input type="button" class="button" onclick="enable_server_monitoring()" value="MONITORING SERVER" id="monitor_server_button" />
<div style="display:none;" id="monitor_server_info">
	<div><div id="progressbar_cpu_usage" style="background-color:red; height:20px; width:0px;"></div>CPU: <span style="display:inline-block;" id="cpu_usage_per"></span></div>
	<div><div id="progressbar_memory_usage" style="background-color:green; height:20px; width:0px;"></div>MEMORY: <span style="display:inline-block;" id="memory_usage_per"></span></div>
</div>

Άβαταρ μέλους
philos
Δημοσιεύσεις: 260
Εγγραφή: 30 Αύγ 2007 23:32

Re: Script για παρακολούθηση φόρτου server - είναι αξιόπιστο και σωστό;

Δημοσίευση από philos » 22 Μάιος 2017 02:11

Και κάτι άλλο παιδιά: σε Windows μου δείχνει ακριβώς σε τι φάση είναι ο επεξεργαστής την ώρα που κάνει refresh.
Στον server με Linux που γίνεται:
$sys_load = sys_getloadavg();
$load = $sys_load[0];

Μάλλον επιστρέφει όντως μια average τιμή. Το παρατήρησα επειδή αν τρέξω κάτι "έντονο" η ένδειξη % για τη CPU ανεβαίνει και μετά ανά κάθε refresh πέφτει σιγά σιγά, αντί για "απότομα", όπως - ίσως; - θα έπρεπε και συμβαίνει σε περιβάλλον Windows.
hmm;

Ξέρω ότι μπορώ να μπαίνω στο panel του server και να βλέπω αυτές τις πληροφορίες, ωστόσο επειδή θέλει διαδικασία κι εγώ σπάνιότατα ασχολούμαι να μπω, θέλω να έχω αυτό το "gadget" στο βασικό site να κοιτάω που και που...

Άβαταρ μέλους
Cha0s
SysAdmin
Δημοσιεύσεις: 10242
Εγγραφή: 28 Ιούλ 2001 03:00

Re: Script για παρακολούθηση φόρτου server - είναι αξιόπιστο και σωστό;

Δημοσίευση από Cha0s » 22 Μάιος 2017 20:10

Για την RAM έχε υπόψιν αυτό http://www.linuxatemyram.com/
Το linux χρησιμοποιεί σχεδόν όλη την ram για caches και την αποδεσμεύει αμέσως αν κάποιο application την χρειαστεί.
Αντί για το MemFree τράβα το MemAvailable από το /proc/meminfo

Για την CPU, το Load Average που χρησιμοποιείς δεν είναι το realtime CPU usage αλλά το average load που έχει κατά μέσο όρο το μηχάνημα.
http://blog.scoutapp.com/articles/2009/ ... d-averages
Όταν λέμε load αναφέρεται συνολικά στον φόρτο του μηχανήματος όχι μόνο στην CPU.
Πολύ χοντρικά load 1.00 σημαίνει ότι ο ένας πυρήνας είναι στο 100% usage. Αν έχεις 8 πύρηνο μηχάνημα τότε load 8.00 σημαίνει 100% cpu usage (σε όλα τα cores).
Επίσης υπάρχουν 3 τιμές load average. Είναι μέσοι όροι για 1 λεπτό, 5 λεπτά και 15 λεπτά αντίστοιχα. Γιαυτό το έβλεπες να ανεβαίνει και να πέφτει σιγά σιγά.

Ωστόσο το load avg καθορίζεται και από τα wait times είτε λόγω disk IO είτε λόγω network IO (πιο σπάνια).
Οπότε αν έχεις ένα αργό-μέτριο δίσκο, μπορεί να σου εμφανίζει πχ κατά την διάρκεια των backups 3.00 load χωρίς να σημαίνει πως χρησιμοποιεί εκείνη την ώρα 100% cpu σε 3 cores. Η αναμονή από το read/write στον δίσκο συνεισφέρει στο load average.

Η αναλογία με τις λωρίδες και την κίνηση που δείχνει στο παραπάνω link ισχύει ουσιαστικά και για την CPU και για τον δίσκο όταν υπολογίζει το load average.

Άβαταρ μέλους
Cha0s
SysAdmin
Δημοσιεύσεις: 10242
Εγγραφή: 28 Ιούλ 2001 03:00

Re: Script για παρακολούθηση φόρτου server - είναι αξιόπιστο και σωστό;

Δημοσίευση από Cha0s » 22 Μάιος 2017 20:26

Αν θες να τραβήξεις το συνολικό CPU usage σε πραγματικό χρόνο (όχι load average) υποθέτω μπορείς να το κάνεις μέσω της εντολής top.
Την βάζεις να τρέξει μία φορά και κάνεις parse το output.
πχ:

Κώδικας: Επιλογή όλων

top -b -n 1 -d 1
Και παίρνεις κάτι σαν το παρακάτω:

Κώδικας: Επιλογή όλων

bananapi:~# top -b -n 1 -d 1 
top - 20:18:19 up 22 days, 13:32,  1 user,  load average: 0.15, 0.09, 0.03
Tasks:  99 total,   1 running,  98 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.5 us,  0.5 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:   1025448 total,   587464 used,   437984 free,    35952 buffers
KiB Swap:        0 total,        0 used,        0 free.   384872 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1973 snmp      20   0   10588   5688   2888 S   5.8  0.6 149:45.75 snmpd
10882 root      20   0    4568   2060   1788 R   5.8  0.2   0:00.04 top
    1 root      20   0    2380   1228   1092 S   0.0  0.1   0:56.20 init
    2 root      20   0       0      0      0 S   0.0  0.0   0:01.26 kthreadd
    3 root      20   0       0      0      0 S   0.0  0.0   1:40.17 ksoftirqd/0
    5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
    7 root      20   0       0      0      0 S   0.0  0.0  11:25.01 rcu_sched
    8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh
    9 root      rt   0       0      0      0 S   0.0  0.0   0:10.28 migration/0
   10 root      rt   0       0      0      0 S   0.0  0.0   0:10.00 migration/1
   11 root      20   0       0      0      0 S   0.0  0.0   0:39.55 ksoftirqd/1
   13 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/1:0H
   14 root      20   0       0      0      0 S   0.0  0.0   0:00.02 kdevtmpfs
   15 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 netns
   16 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 perf
   17 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 writeback
   18 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 crypto
   19 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 bioset
   20 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kblockd
   21 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 ata_sff
.........................
..............
........
Σε νοιάζει η γραμμή:

Κώδικας: Επιλογή όλων

%Cpu(s):  0.5 us,  0.5 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
Μπορείς να κάνεις extract τα id (idle) και wa (wait) και μία απλή αφαίρεση να βρεις το cpu usage εκείνη την δεδομένη στιγμή.
CPU usage = 100 - ( idle - wait )

Άβαταρ μέλους
philos
Δημοσιεύσεις: 260
Εγγραφή: 30 Αύγ 2007 23:32

Re: Script για παρακολούθηση φόρτου server - είναι αξιόπιστο και σωστό;

Δημοσίευση από philos » 23 Μάιος 2017 01:46

Λοιπόν, εμένα η σχετική γραμμή είχε τη μορφή:

Κώδικας: Επιλογή όλων

Cpu(s): 6.9%us, 0.7%sy, 0.6%ni, 91.4%id, 0.3%wa, 0.0%hi, 0.0%si, 0.0%st
Τρέχω λοιπόν το ακόλουθο script, όμως υπάρχει ένα πρόβλημα: όσες φορές κι αν έτρεξα το php αρχείο με τον ακόλουθο κώδικα στον browser, πάντα μου επιστρέφει τις ίδιες τιμές. Δηλαδή δεν φαίνεται να ανανεώνονται οι αριθμοί ανά τρέξιμο του php.
Γιατί αυτό; :idea:

Το script:

Κώδικας: Επιλογή όλων

function get_string_between($string, $start, $end)
{
    $string = ' ' . $string;
    $ini = strpos($string, $start);
    if ($ini == 0) return '';
    $ini += strlen($start);
    $len = strpos($string, $end, $ini) - $ini;
    return substr($string, $ini, $len);
}

$output = null;
exec('top -b -n 1 -d 1', $output);

$idle = get_string_between($output[2], '%ni, ', '%id, ');
$wait = get_string_between($output[2], '%id, ', '%wa, ');

$cpu_usage = 100 - ($idle - $wait);
var_dump($cpu_usage); 

Άβαταρ μέλους
philos
Δημοσιεύσεις: 260
Εγγραφή: 30 Αύγ 2007 23:32

Re: Script για παρακολούθηση φόρτου server - είναι αξιόπιστο και σωστό;

Δημοσίευση από philos » 23 Μάιος 2017 01:59

Δοκίμασα κι αυτό που ανάφερες για τη RAM. Δυστυχώς δεν φαίνεται να επιστρέφεται κάποια τιμή MemAvailable.
Συγκεκριμένα, επιστρέφονται - για παράδειγμα σε ένα run που έκανα - τα εξής:

Κώδικας: Επιλογή όλων

array(2) { [0]=> string(8) "MemTotal" [1]=> string(18) " 4044336 kB" } array(2) { [0]=> string(7) "MemFree" [1]=> string(19) " 419876 kB" } array(2) { [0]=> string(7) "Buffers" [1]=> string(19) " 241692 kB" } array(2) { [0]=> string(6) "Cached" [1]=> string(20) " 1900192 kB" } array(2) { [0]=> string(10) "SwapCached" [1]=> string(16) " 52960 kB" } array(2) { [0]=> string(6) "Active" [1]=> string(20) " 1536772 kB" } array(2) { [0]=> string(8) "Inactive" [1]=> string(18) " 1832668 kB" } array(2) { [0]=> string(12) "Active(anon)" [1]=> string(14) " 606292 kB" } array(2) { [0]=> string(14) "Inactive(anon)" [1]=> string(12) " 622688 kB" } array(2) { [0]=> string(12) "Active(file)" [1]=> string(14) " 930480 kB" } array(2) { [0]=> string(14) "Inactive(file)" [1]=> string(12) " 1209980 kB" } array(2) { [0]=> string(11) "Unevictable" [1]=> string(15) " 0 kB" } array(2) { [0]=> string(7) "Mlocked" [1]=> string(19) " 0 kB" } array(2) { [0]=> string(9) "SwapTotal" [1]=> string(17) " 4190204 kB" } array(2) { [0]=> string(8) "SwapFree" [1]=> string(18) " 3996088 kB" } array(2) { [0]=> string(5) "Dirty" [1]=> string(21) " 128 kB" } array(2) { [0]=> string(9) "Writeback" [1]=> string(17) " 0 kB" } array(2) { [0]=> string(9) "AnonPages" [1]=> string(17) " 1178096 kB" } array(2) { [0]=> string(6) "Mapped" [1]=> string(20) " 35308 kB" } array(2) { [0]=> string(5) "Shmem" [1]=> string(21) " 1424 kB" } array(2) { [0]=> string(4) "Slab" [1]=> string(22) " 181504 kB" } array(2) { [0]=> string(12) "SReclaimable" [1]=> string(14) " 152336 kB" } array(2) { [0]=> string(10) "SUnreclaim" [1]=> string(16) " 29168 kB" } array(2) { [0]=> string(11) "KernelStack" [1]=> string(15) " 2072 kB" } array(2) { [0]=> string(10) "PageTables" [1]=> string(16) " 19264 kB" } array(2) { [0]=> string(12) "NFS_Unstable" [1]=> string(14) " 0 kB" } array(2) { [0]=> string(6) "Bounce" [1]=> string(20) " 0 kB" } array(2) { [0]=> string(12) "WritebackTmp" [1]=> string(14) " 0 kB" } array(2) { [0]=> string(11) "CommitLimit" [1]=> string(15) " 6212372 kB" } array(2) { [0]=> string(12) "Committed_AS" [1]=> string(14) " 2085144 kB" } array(2) { [0]=> string(12) "VmallocTotal" [1]=> string(17) " 34359738367 kB" } array(2) { [0]=> string(11) "VmallocUsed" [1]=> string(15) " 154028 kB" } array(2) { [0]=> string(12) "VmallocChunk" [1]=> string(17) " 34359572504 kB" } array(2) { [0]=> string(17) "HardwareCorrupted" [1]=> string(9) " 0 kB" } array(2) { [0]=> string(13) "AnonHugePages" [1]=> string(13) " 780288 kB" } array(2) { [0]=> string(15) "HugePages_Total" [1]=> string(8) " 0" } array(2) { [0]=> string(14) "HugePages_Free" [1]=> string(9) " 0" } array(2) { [0]=> string(14) "HugePages_Rsvd" [1]=> string(9) " 0" } array(2) { [0]=> string(14) "HugePages_Surp" [1]=> string(9) " 0" } array(2) { [0]=> string(12) "Hugepagesize" [1]=> string(14) " 2048 kB" } array(2) { [0]=> string(11) "DirectMap4k" [1]=> string(15) " 65408 kB" } array(2) { [0]=> string(11) "DirectMap2M" [1]=> string(15) " 4128768 kB" } array(1) { [0]=> string(0) "" }
Ευχαριστώ εκ των προτέρων για τη μέχρι τώρα βοήθεια. :D

Άβαταρ μέλους
Cha0s
SysAdmin
Δημοσιεύσεις: 10242
Εγγραφή: 28 Ιούλ 2001 03:00

Re: Script για παρακολούθηση φόρτου server - είναι αξιόπιστο και σωστό;

Δημοσίευση από Cha0s » 23 Μάιος 2017 14:30

Πρόχειρα που τσέκαρα σε ένα bananian βλέπω τα παρακάτω:

Κώδικας: Επιλογή όλων

bananapi:~# cat /proc/meminfo 
MemTotal:        1025448 kB
MemFree:          436784 kB
MemAvailable:     889872 kB
Buffers:           35952 kB
Cached:           385976 kB
SwapCached:            0 kB
Active:           257604 kB
Inactive:         256716 kB
Active(anon):      92468 kB
Inactive(anon):     5696 kB
Active(file):     165136 kB
Inactive(file):   251020 kB
Unevictable:          68 kB
Mlocked:              68 kB
HighTotal:        260520 kB
HighFree:         135036 kB
LowTotal:         764928 kB
LowFree:          301748 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                28 kB
Writeback:             0 kB
AnonPages:         92528 kB
Mapped:            45032 kB
Shmem:              5776 kB
Slab:              60972 kB
SReclaimable:      51956 kB
SUnreclaim:         9016 kB
KernelStack:        1120 kB
PageTables:         1484 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      512724 kB
Committed_AS:     613876 kB
VmallocTotal:     245760 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
CmaTotal:          16384 kB
CmaFree:           15480 kB
Αλλά σε μηχανήματα με παλιότερους kernel βλέπω πως δεν υπάρχει όντως το MemAvailable.

Οπότε μπορείς να πάρεις το MemFree και να προσθέσεις σε αυτό τα Buffers & Cached και θα πρέπει να έρθεις πολύ κοντά στο πραγματικό νούμερο.

Απάντηση

Επιστροφή στο “PHP Προγραμματισμός”

Μέλη σε σύνδεση

Μέλη σε αυτήν τη Δ. Συζήτηση: Δεν υπάρχουν εγγεγραμμένα μέλη και 2 επισκέπτες