[PHP]Controleren of servers online zijn of niet

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik wil in PHP een scripje maken wat een 20 tal servers controleert.
Ik wil alleen weten of ze online zijn of niet.

Het probleem is alleen dat deze servers niet gelijk zijn, dus op sommige servers staat een bepaalde poort open en op een andere weer dicht.
Zo draait op de ene machine weer geen webserver op de andere weer wel, zo ook met ftp.
Sommige zijn windows en andere linux (diverse versies)

Al met al lukt het me niet om een scripje te maken wat simpel zegt online of offline.

Ik ben bezig geweest met fsockopen maar dit werkt niet.
Ik had het volgende scripje gebruikt:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(while statement hier)
$poorten = array($serverpoort,$querypoort,21,22,10000,80);
 for($i=0;$i<count($poorten) AND !strstr($machineonline,'1');$i++) {
                                            $sock =  fsockopen($server_firstip, $poorten[$i], $nummer, $error, 10);
                                             $poort = $poorten[$i];
                                             echo "check $server_firstip, $poort, $nummer, $error<br>";
                                             if(!$sock) {
                                              $machineonline=0;
                                               fclose ($sock);
                                               } else {
                                                         $machineonline=1;
                                                         fclose ($sock);                                                                                                                                                                                                                                                                                                 
}
}
(einde while)


$server_firstip wordt uit een database gehaald net zoals de waardes $serverpoort,$querypoort

Maar als ik dit scripje run dan krijg ik bij alle servers het zelfde resultaat:
0 succesful en de waarde $machineonline=0;
Ik weet dat er van de 20 machines zeker 6 zijn die niet online zijn en de rest wel.

Is er geen eenvoudiger en betrouwbaardere manier om te controleren of een machine (ip adres, GEEN hostnamen!!!) online is via PHP, want met fsockopen wilt het helemaal niet lukken.

[ Voor 15% gewijzigd door Verwijderd op 10-10-2005 05:28 ]


Acties:
  • 0 Henk 'm!

  • HunterPro
  • Registratie: Juni 2001
  • Niet online
voor dergelijke taken is php niet echt gemaakt... je gaat namelijk op de timeout van een server lopen wachten op deze manier. Als je een paar timeouts hebt loop je tegen de max-execution-time van je script aan. Dat kan ook wel weer opgelost worden, maar je blijft dingen aanpassen totdat het geheel samenwerkt. Verandert het aantal servers, kun je weer én in je scripts, én in je php-config gaan frutten. Een gebruikelijkere manier om dit te doen is gebruik maken van een cronjob (linux) of de taakplanner (win32) om een scriptje uit te voeren dat bijv elke 5 minuten betreffende servers pingt / pollt / whatever en het resultaat in een bestandje gooit danwel in bijv een database. Met je scriptje (in php) kun je dan heel eenvoudig en redelijk up-to-date die gegevens ophalen, verwerken, en de juiste conclusies daaruit trekken.

[ Voor 17% gewijzigd door HunterPro op 10-10-2005 06:19 ]


Acties:
  • 0 Henk 'm!

  • krvabo
  • Registratie: Januari 2003
  • Laatst online: 19-09 22:02

krvabo

MATERIALISE!

HunterPro schreef op maandag 10 oktober 2005 @ 06:17:
voor dergelijke taken is php niet echt gemaakt... je gaat namelijk op de timeout van een server lopen wachten op deze manier.
Zoals je kan zien zet de TS de timeout op 10 seconden, dus dat klopt niet helemaal
Als je een paar timeouts hebt loop je tegen de max-execution-time van je script aan. Dat kan ook wel weer opgelost worden, maar je blijft dingen aanpassen totdat het geheel samenwerkt. Verandert het aantal servers, kun je weer én in je scripts, én in je php-config gaan frutten.
Dat kan je natuurlijk ook in je script zetten.
pseudo:
PHP:
1
set_time_limit($maxtijdperserver * $numservers);
Al weet ik niet zeker of deze code voor 'headers' moet komen of niet.
Een gebruikelijkere manier om dit te doen is gebruik maken van een cronjob (linux) of de taakplanner (win32) om een scriptje uit te voeren dat bijv elke 5 minuten betreffende servers pingt / pollt / whatever en het resultaat in een bestandje gooit danwel in bijv een database. Met je scriptje (in php) kun je dan heel eenvoudig en redelijk up-to-date die gegevens ophalen, verwerken, en de juiste conclusies daaruit trekken.
Dat vind ik wel een goed idee :)

Ik gebruik zelf dit scriptje, misschien dat je er iets aan hebt (al verschilt het niet veel van de jouwe geloof ik :/ )
PHP:
1
2
3
4
5
6
7
8
9
10
function online($ip, $port) {
    $fp = @fsockopen($ip, $port, &$errno, &$errstr, 1);
    if (!$fp) { 
        $status = false;
    } else { 
        $status = true;
        fclose($fp);
    }
    return $status;
}

Dit kan je dan in je loop gewoon steeds aanroepen. Kan je ook niet gelijk in je database erbij zetten welke port je kan checken? Dat scheelt je weer 4 of 5 loze sockets :P

Pong is probably the best designed shooter in the world.
It's the only one that is made so that if you camp, you die.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Die timeout stond eerst op 1, hiermee heb ik ook al zitten spelen, geen effect.

@krvabo
Dat is het probleem, er zijn geen vaste poorten die ik telkens kan gebruiken.
Dus deze maand staat poort XXX wel open en de andere maand weer niet.
Het zijn voornamelijk gameservers die ik moet controleren, ik had ook al gedacht om bij windows de RDM poort te controleren en bij Linux de ssh poort, maar ook dat werkt niet.

Ik moet het dus doen met de informatie die ik heb en met die informatie het proberen werkend te krijgen, het vreemde is als ik mijn scrippie op alleen 1 server toepas dan werkt het wel prima maar zodra hij ze allemaal moet gaan controleren dat het mis gaat, dan klopt er niks meer van.

De bedoeling is dat dit scripje draait en het resultaat in een database gooit en dat de informatie (alive) vanaf dan uit de database wordt gehaald en niet meer wordt gequeryd op de server.
Dit stukje code is een onderdeel van een groter script, de rest van het script queried ook de stats van de games zelf die op de servers draaien en dumpt deze ook in een database.

Echter men wil ook weten of de servers zelf online zijn of niet, voor de games heb ik het al werkend het gaat me nu puur om de machines.
Ik wilde dit script (als het goed werkte) via een cronjob elke 10 minuten ofzo laten draaien (gaat vooral om de rest van het script) zodat de gegevens redelijk actueel zijn.
Een gebruikelijkere manier om dit te doen is gebruik maken van een cronjob (linux) of de taakplanner (win32) om een scriptje uit te voeren dat bijv elke 5 minuten betreffende servers pingt / pollt / whatever en het resultaat in een bestandje gooit danwel in bijv een database
Dit is dus eigenlijk ook de bedoeling, echter ik zou niet weten hoe ik dat voor elkaar moet krijgen.
Zelf gebruik ik alleen maar PHP en de webserver waarop dit komt te staan is een windows server.
Dan zou ik een tooltje moeten hebben wat op windows werkt, gratis is en dat dus in een mysql database voor mij deze gegevens kan dumpen.
En ik moet eerlijk zijn: ik heb niet eens een idee waarop ik moet zoeken......
(google: programma voor windows dat servers pingt?!?!?! ;) )

[ Voor 22% gewijzigd door Verwijderd op 10-10-2005 14:00 ]


Acties:
  • 0 Henk 'm!

Verwijderd

@krvabo: Dat kan een stuk korter hoor:
PHP:
1
2
3
function online($ip,$port) {
  return ($sh = fsockopen($ip,$port,&$erno,&$erst,1) AND isset($sh) AND fclose($sh))?true:false;    
}

;)

Verder raad ik aan om dit via meerdere services te proberen, er zijn altijd een paar poorten open.
Ik begin altijd met een ICMP packet te versturen via PHP, daarna een NetBIOS (143?) connectie en daarna probeer ik een aantal vaste poorten uit die open kunnen staan.

Normaal poll ik iedere 5 minuten vanaf iedere server naar een database, alleen de tijd (is voldoende). Langer dan 5 minuten geen reactie? Automatisch een mailtje versturen :)

Ik raad aan om te zoeken naar de protocols: ICMP, SNMP en ARP.

Btw, dit zit/zat ook in PHPMyServer, komt met de volgende release weer terug.

[ Voor 13% gewijzigd door Verwijderd op 10-10-2005 15:15 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dat zijn allemaal dezelfde manieren als wat ik al deed, zoals ik al vermelde dit werkt dus voor geen meter helaas, servers geven bv reply terug (alive) terwijl ie gewoon down is
Ook krijg ik reacties retour dat ie down is terwijl ie wel alavie is.

Zolang je maar 1 server checked is dit geen probleem maar zodra je er meer achter elkaar wilt doen bv via een while statement werkt dit niet goed meer, dan krijg je allemaal van die vage reply's retour

Acties:
  • 0 Henk 'm!

  • Stewie!
  • Registratie: September 2001
  • Laatst online: 15:50

Stewie!

Keen must die!

Verwijderd schreef op maandag 10 oktober 2005 @ 16:21:
Dat zijn allemaal dezelfde manieren als wat ik al deed, zoals ik al vermelde dit werkt dus voor geen meter helaas, servers geven bv reply terug (alive) terwijl ie gewoon down is
Ook krijg ik reacties retour dat ie down is terwijl ie wel alavie is.

Zolang je maar 1 server checked is dit geen probleem maar zodra je er meer achter elkaar wilt doen bv via een while statement werkt dit niet goed meer, dan krijg je allemaal van die vage reply's retour
En dan heb je niet een foutje in je code waardoor er niet de server gepolled wordt die je wilt hebben?

Acties:
  • 0 Henk 'm!

  • Mawlana
  • Registratie: Juli 2002
  • Laatst online: 19:37
Het gaat mis in de for-loop. Volgens mij worden alle poorten gecontroleerd, ook al staat de eerste poort al open. Als de laatste poort niet open staat, dan is de server volgens jouw code 'down'. Je moet de for-loop laten beëindigen zodra het een openstaande poort heeft gevonden.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
$commonPorts = array(80,21,22,1000);

function checkOnline($server_ip, $server_ports = array())
{
    global $commonPorts;
    $ports  = array_merge($commonPorts, $server_ports);
    $server_online  = false;
    for($i = 0; $i < count($ports); $i++)
    {
        $fp = @fsockopen($server_ip, $ports[$i], $errno, $errstr, 10);
        if($fp) // server is online
        {
            $server_online  = true;
            fclose($fp);
            break;
        }
    }
    return $server_online;
}

// voorbeeld
$vb_server  = '213.239.154.35'; // www.tweakers.net
$vb_ports   = array(99,23);     // indien deze array leeg is, worden alleen de poorten vermeld in $commonPorts gecheckt
echo checkOnline($vb_server, $vb_ports);
?>

Acties:
  • 0 Henk 'm!

  • Glashelder
  • Registratie: September 2002
  • Niet online

Glashelder

Anti Android

Ik gebruik hiervoor op de zaak IPSwitch WhatsUp Professional. Dit programma kan alles van Windows uitlezen via SNMP, maar je kan het ook simpel een server om de minuut laten pingen. Ik heb het zo ingesteld dat ik een SMS ontvang als er wat mis gaat :)

Het mooie aan dit programma is ook dat het afhankelijkheden kent. M.a.w., als Server1, Server2 en Server3 achter Switch1 staan en Switch1 is ook niet meer te bereiken dan krijg je slechts één bericht met de conclusie dat Switch1 down is. Heel handig want anders krijg je 4 SMSjes dat er 3 servers down zijn en een switch :)

Dit programma kan ook services voor je herstarten op de server als er een service down gaat. Je kan het zo gek niet bedenken of dit programma kan het monitoren.

Je zou kunnen kijken naar een freeware variant hiervan, zal vast ook wel bestaan. Zie net da het 1500 dollar kost :+
Het programma moet data wegschrijven in een database, dat is belangrijk.
Deze data moet ik kunnen benaderen en elders in een script kunnen gebruiken.
De gebruiker moet op een stats pagina bv kunnen zien of zijn dienst online is maar ook of de hele machine up is of niet.
Wordt standaard opgeslagen in een SQL database...

[ Voor 16% gewijzigd door Glashelder op 11-10-2005 01:04 ]

PV 4915wp op oost, 2680 wp op west, 1900 wp op zuid. pvoutput - AUX 8 kW bi bloc


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@glashelder
Het programma moet data wegschrijven in een database, dat is belangrijk.
Deze data moet ik kunnen benaderen en elders in een script kunnen gebruiken.
De gebruiker moet op een stats pagina bv kunnen zien of zijn dienst online is maar ook of de hele machine up is of niet.

@sylvester:
De break zat er ook al in, echter omdat ie toen nog niet goed werkte heb ik deze om nu onduidelijke reden weer weg gehaald.
Met de break functie doet ie het helaas ook niet goed.

Acties:
  • 0 Henk 'm!

  • Mawlana
  • Registratie: Juli 2002
  • Laatst online: 19:37
De voorbeeldcode die ik geplaatst heb, werkt gewoon. Probeer het maar eens. :)
Als je meerdere servers moet controleren:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
// hier komt $commonPorts
// hier komt function checkOnline()

$servers['234.232.234.232'] = array(923,23);
$servers['67.34.43.236']    = array(74,48);
$servers['75.56.34.23']     = array();

while(list($ip, $ports) = each($servers))
{
    $status[$ip]    = checkOnline($ip, $ports);
}
var_dump($status);
?>

^^ ongetest

Acties:
  • 0 Henk 'm!

Verwijderd

1) Moet je error reporting eens op e_all zetten, je defined $status nergens dus daar valt hij dan over.
2) while, list en earch? wat is er mis met foreach?
PHP:
1
2
foreach($servers as $ip => $ports)
  $status[$ip] = checkOnline($ip,$ports);

Acties:
  • 0 Henk 'm!

  • SinergyX
  • Registratie: November 2001
  • Laatst online: 19:18

SinergyX

____(>^^(>0o)>____

ik heb zelf lange tijd zo'n server check script gehad, om die time-out te omzeilen als het script moesten wachten op reply heb ik het script in een apart bestand gezet die uiteindelijk een groene of een rode image als header zou uitvoeren.

via een <image src=testserver.php?server=1> kon ik zo elke server checken, zou hij dus op een time-out wachten zie je gewoon nog geen image. Ik had dan als default achtergrond van de <td> waar de <image instond een offline image.

Nog 1 keertje.. het is SinergyX, niet SynergyX
Im as excited to be here as a 42 gnome warlock who rolled on a green pair of cloth boots but was given a epic staff of uber awsome noob pwning by accident.


Acties:
  • 0 Henk 'm!

  • 4VAlien
  • Registratie: November 2000
  • Laatst online: 24-06 09:47

4VAlien

Intarweb!

<dubbelpost, kan een admin dit even opvegen? dank u!>

[ Voor 93% gewijzigd door 4VAlien op 11-10-2005 02:07 ]


Acties:
  • 0 Henk 'm!

  • 4VAlien
  • Registratie: November 2000
  • Laatst online: 24-06 09:47

4VAlien

Intarweb!

Sinergy schreef op dinsdag 11 oktober 2005 @ 01:51:
ik heb zelf lange tijd zo'n server check script gehad, om die time-out te omzeilen als het script moesten wachten op reply heb ik het script in een apart bestand gezet die uiteindelijk een groene of een rode image als header zou uitvoeren.

via een <image src=testserver.php?server=1> kon ik zo elke server checken, zou hij dus op een time-out wachten zie je gewoon nog geen image. Ik had dan als default achtergrond van de <td> waar de <image instond een offline image.
Ik heb hetzelfde gedaan, en dit systeem werkt goed. Als je het niet in een web page wilt hebben dan kan je een php of bash script maken dat voor alle N servers een apart php process start (analoog aan de web browser die alle images opvraagt). Op die manier heb je een eenvoudige vorm van threading om timeouts te omzeilen.

Acties:
  • 0 Henk 'm!

  • Mawlana
  • Registratie: Juli 2002
  • Laatst online: 19:37
Verwijderd schreef op dinsdag 11 oktober 2005 @ 01:44:
1) Moet je error reporting eens op e_all zetten, je defined $status nergens dus daar valt hij dan over.
2) while, list en earch? wat is er mis met foreach?
1) Dit is maar een quick&dirthy-oplossing.
2) Het is maar waar je net de voorkeur voor geeft.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Nou ik heb het geprobeert.

Het werkt nog steeds niet goed, bij bv servers die 100% offline zijn (staan er 3 uit wegens een defect) geeft ie gewoon aan dat ze online zijn.

Bij de machines die ook echt online zijn geeft ie het wel goed aan, maar als een machine niet benaderbaar is (offline is, bv uit staat, niet pingt, defect, gecrashed etc) dan geeft ie ook aan dat ie online is, al met al werkt het dus niet.....

Dit script draait als cronjob, dus geen plaatjes, tekst etc.....
Het geeft een waarde 1 als ie online is en dat wordt in een DB geduwd en 0 als ie offline is.

Met een E_All geeft ie geen fouten weer.

[ Voor 13% gewijzigd door Verwijderd op 11-10-2005 03:42 ]


Acties:
  • 0 Henk 'm!

  • 4VAlien
  • Registratie: November 2000
  • Laatst online: 24-06 09:47

4VAlien

Intarweb!

Handel je nu ook alle foutcodes af? Heb je in de API opgezocht wat precies als retourwaarde gegeven wordt onder welke omstandigheden? Zit er misschien ergens een gaatje in je logica, bijvoorbeeld A==B (waar voor 0 en 1) waar het A && B moet zijn? Ik heb uit je antwoorden nog niet echt kunnen opmaken dat je alle uitzonderingen in de functies afhandelt. En kan je de fout beter localiseren? -Waar- komt de verkeerde waarde tevoorschijn als je een server probeert te bereiken die op dat moment geen route (want missend eindpunt) heeft?

PS: het gebruik van errno en errstr in fsockopen kan ook erg verhelderend werken, immers als je een connection refused krijgt weet je ook dat een bepaalde host online is, ook al krijg je geen geldige fd terug.

[ Voor 18% gewijzigd door 4VAlien op 11-10-2005 06:09 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Nou dat heb ik gedaan
Hij connect volgens het script direct al op poort 21
Dit terwijl deze poort op sommige servers 100% dicht staat (geen ftp aanstaan), ook op de machines die uit staan connect ie volgens dit scripje op poort 21

Dit print ie bv bij 2 servers, de eerste is een server die uit staat de 2de is online:
ik geef commando:
PHP:
1
2
3
4
5
6
7
8
9
$fp    = fsockopen($server_ip, $ports[$i], $errno, $errstr, 10);
        if($fp)    // server is online
        {
            $poort = $ports[$i];
            echo "$server_ip <> $poort <> $errno <> $errstr<br>";
            $server_online = 1;
            fclose($fp);
            break;
        }

results:
83.xx.xxx.10 <> 21 <> 0 <>
83.xx.xxx.20 <> 21 <> 0 <>

etc etc alle server hetzelfde.
De eerste .10 staat 100% uit en .20 staat 100% aan

[ Voor 27% gewijzigd door Verwijderd op 11-10-2005 15:35 ]


Acties:
  • 0 Henk 'm!

  • Mawlana
  • Registratie: Juli 2002
  • Laatst online: 19:37
Zou je even de volledige code kunnen posten van het voorbeeldscript?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Geen probleem maar ik denk dat ik het gevonden heb.
Heb wat zitten sleutelen aan de code en nu lijtk ie goed te werken.

Ik heb er een (!$fp) erbij gezet en de poorten gefine tuned
Ik check alleen nog op 3 poorten, ssh rdm en een andere poort die de meeste van deze servers gebruiken.
Ook stuur ik vooraf nu de ssh of rdm poort mee, ik weet namelijk (stata in db) of het een linux of windows machine is voordat ik hem query.
Dus uiteindelijk checked ie nu nog maar op 2 poorten, 1 die ik mee stuur afhankelijk van OS (poort 22 als het linux is of 3389 als het windows is) en als 2de poort een poort die op de deze meeste servers ook gebruikt wordt, poort 10000.

Na diverse testen kloppen de resultaten nu wel.

[ Voor 7% gewijzigd door Verwijderd op 11-10-2005 16:16 ]


Acties:
  • 0 Henk 'm!

  • 4VAlien
  • Registratie: November 2000
  • Laatst online: 24-06 09:47

4VAlien

Intarweb!

van php.net:

If the call fails, it will return FALSE and if the optional errno and errstr arguments are present they will be set to indicate the actual system level error that occurred in the system-level connect() call. If the value returned in errno is 0 and the function returned FALSE, it is an indication that the error occurred before the connect() call. This is most likely due to a problem initializing the socket. Note that the errno and errstr arguments will always be passed by reference.

Je moet wel die FALSE goed afvangen.
dus if ($fd = fsockopen() !== FALSE) { online? }
else offline!

Het gebruik van !== etc is erg schimmig maar gezien de 'vage' resultaten lijkt het me wel een kandidaat voor dit probleem.

Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
4VAlien schreef op donderdag 13 oktober 2005 @ 04:39:
Het gebruik van !== etc is erg schimmig maar gezien de 'vage' resultaten lijkt het me wel een kandidaat voor dit probleem.
Het gebruik van !== en === zijn helemaal niet schimmig. Het enige wat deze operatoren doen is het afdwingen van type-gelijkheid van de linker en rechterzijde.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • software
  • Registratie: Mei 2003
  • Laatst online: 02-01 09:26
Misschien een voorstel om meer snelheidswinst te hebben: stuur eerst een aantal pings, en daarna (als je antwoord terug krijgt ga je werken met fsockopen.
Indien niet weet je al bijna zeker dat de server uit ligt.

Acties:
  • 0 Henk 'm!

Verwijderd

PHP en pingen? Yea right.

Zonder fsockopen of socket_connect functies kan je helemaal niets. Dan kan je pingen wat je wil, maar het lukt gewoon niet. Btw je moet voor de grap eens Ethereal installeren en dan een ping doen naar een bepaalde server (wel zorgen dat je verder geen netwerkconnecties hebt met iets). Dan zie je als het goed is exact welk pakketje langs komen en hoe je die met PHP na kan maken.

Acties:
  • 0 Henk 'm!

  • HunterPro
  • Registratie: Juni 2001
  • Niet online
ja, met fsockets een icmp packet bouwen? Ik vraag me sterk af of dat de way to go is. Hoe ga je de returnpacket afvangen? Bovendien pingen is niet pollen. Als je wilt weten of een service up is, zul je in een protocol van die service moeten pollen (danwel een request doen via een standaardprotocol aan die server als via web of snmp wat een scriptje triggert wat kijkt of alle services van die server up zijn en dat teruggeeft).

je kan natuurlijk het ultiem ranzige $frop = `ping $host`; parsen, maar of je daar blij van wordt...

[ Voor 11% gewijzigd door HunterPro op 13-10-2005 11:06 ]

Pagina: 1