shroh has asked for the wisdom of the Perl Monks concerning the following question:

Hi experts,

I need some ideas or a piece of code to check the time on a group of servers, Our application has 10 servers and one of them goes behind 20-30 seconds than the exact time and application times out. Need to monitor this by writing a perl script and send an automatic email when this happens.

Replies are listed 'Best First'.
Re: Time check on group of servers
by Corion (Patriarch) on May 09, 2016 at 19:26 UTC

    Why not keep the time synchronized by running ntp on them?

      This, or use some sort of state enforcement tool like Salt.
Re: Time check on group of servers
by FreeBeerReekingMonk (Deacon) on May 09, 2016 at 19:47 UTC
    Create your own time daemon?

    #!/usr/bin/env perl use IO::Socket::INET; # auto-flush on socket $| = 1; # creating a listening socket my $socket = new IO::Socket::INET ( LocalHost => '0.0.0.0', LocalPort => '5101', Proto => 'tcp', Listen => 10, Reuse => 1 ); die "cannot create socket $!\n" unless $socket; print "server waiting for client connection on port 5101\n"; while(1) { # waiting for a new client connection my $client_socket = $socket->accept(); # get information about a newly connected client my $client_address = $client_socket->peerhost(); my $client_port = $client_socket->peerport(); print "connection from $client_address:$client_port\n"; # read up to 16 characters from the connected client my $theirtime = 0; $client_socket->recv($theirtime, 16); print "received data: $theirtime\n"; $theirtime =~s/[^\d]//g; # untaint # write response data to the connected client my $their_drift = time - $theirtime ; $client_socket->send($their_drift); # notify client that response has been sent shutdown($client_socket, 1); } $socket->close(); __END__ Problem Your program has forked and you want to tell the other end that you're + done sending data. You've tried close on the socket, but the remote +end never gets an EOF or SIGPIPE. Solution Use shutdown: shutdown(SOCKET, 0); # I/we have stopped reading data shutdown(SOCKET, 1); # I/we have stopped writing data shutdown(SOCKET, 2); # I/we have stopped using this soc +ket

    can be tested with:

    (perl -e 'print time';sleep 2) | telnet 127.0.0.1 5101 2>/dev/null|tai +l -1

    try time+3 to simulate time drifting...

    Addendum: a small perl client:

    #!/usr/bin/env perl use IO::Socket::INET; # auto-flush on socket $| = 1; # create a connecting socket my $socket = new IO::Socket::INET ( PeerHost => 'localhost', PeerPort => '5101', Proto => 'tcp', ); die "cannot connect to the server $!\n" unless $socket; print "connected to the server\n"; # data to send to a server my $mytime = time; my $size = $socket->send($mytime); print "sent data of length $size\n"; # notify server that request has been sent shutdown($socket, 1); # receive a response of up to 256 characters from server my $response = ""; $socket->recv($response, 256); print "received response: $response\n"; $socket->close(); my $threshold=5; # seconds if(abs($response)>$threshold){ exit 1; }else{ exit 0; }

    edit: forgot g in the untaint...

      forgot the hashbang and the "Listen => 5" should be 10 to be able to service all the machines at once. Also: use strict and warnings... Depending on the the connection time, you might want to add fallbacks, like a retry to create a socket, counting the seconds it took to get the anwser, and maybe substract half of this time from your result. Even use Time::HiRes; to get better data... But your thresholds seem to be very tolerant, so keeping it as integers is a quick duktape/chewingum solution while you roll out your ntp thing..

      If you have systemd read this: systemd-timesyncd

      Set up 1 server that gets it's time from the internet, and all others should get their time from that server