Domanda

Here is the script for checking status of windows services and if they are in stop state, it will start the service. I can able to get the status of service, but can't able to start services. please help and let me know what I need to do.

#!/usr/local/bin/perl

use Win32::Service;
use strict;

sub checkService();
sub getDate();
sub getTime();
sub logEvent();

my @timeInfo = localtime(time);
my $serviceName = "TapiSrv";
my $currentDate = getDate();
my $currentTime = getTime();
my %status;
my %status_code = (1 => 'not running',
               2 => 'start pending',
               3 => 'stop pending',
               4 => 'running',
               5 => 'resume pending',
               6 => 'pause pending',
               7 => 'paused');

checkService();

########
# SUBS
########


sub checkService() {
my $startCounter = 0;

Win32::Service::GetStatus('', $serviceName,  \%status);

if($status{"CurrentState"} eq '4') {
    # Log the event
    &logEvent("$currentTime:  $serviceName is running\n");
} elsif($status{"CurrentState"} eq '1') {

    Win32::Service::StartService('', $serviceName);
    }       
    while($startCounter < 3) {
        sleep(5);

        Win32::Service::GetStatus('', $serviceName,  \%status);

        if($status{"CurrentState"} eq '2') {
            $startCounter++;
        } else {
            $startCounter = 3;
        }
    }

    if($startCounter == 3) {
        &logEvent("$currentTime:  Unable to start $serviceName in $startCounter attempts\n");
    } else {
        &logEvent("$currentTime:  Started $serviceName in $startCounter attempts\n");
    }
}

sub getDate() {
my $year = $timeInfo[5] + 1900;
my $month = $timeInfo[4] + 1;
my $day = $timeInfo[3];
return sprintf("%04d-%02d-%02d", $year, $month, $day);
} 

sub getTime() {
my $hour = $timeInfo[2];
my $min = $timeInfo[1];
my $sec = $timeInfo[0];
return sprintf("%02d:%02d:%02d", $hour, $min, $sec);
}

sub logEvent() {
# Log the event
open(OUT, ">> C:/servicestatus/$currentDate.txt");
print OUT "$_[0]";
close(OUT);
}
È stato utile?

Soluzione

Based upon some comments below (including some nice points by @Ron Bergin), I'm revising this post to show code that works for me (Windows 8.1, ActivePerl 5.16).

#!/usr/local/bin/perl

use strict;
use warnings;

use POSIX;
use Win32::Service;

my $currentDate = getDate();
my %status;
my %status_code = (
  Stopped => 1,
  StartPending => 2,
  StopPending => 3,
  Running => 4,
  ResumePending => 5,
  PausePending => 6,
  Paused => 7
);

checkService("Apple Mobile Device");

########
# SUBS
########

sub checkService {
  my $serviceName = shift || die "No arg passed";
  my $startCounter = 1;
  Win32::Service::GetStatus('', $serviceName, \%status);
  if ($status{"CurrentState"} eq $status_code{Running}) {
    logEvent("$serviceName is running\n");
  }
  elsif ($status{"CurrentState"} eq $status_code{'Stopped'}) {
    my $maxAttempts = 3;
    while ($startCounter <= $maxAttempts) {
      logEvent("Attempting to start $serviceName");
      Win32::Service::StartService('', $serviceName);
      sleep(5);
      Win32::Service::GetStatus('', $serviceName, \%status);
      if ($status{"CurrentState"} eq $status_code{Running}) {
        logEvent("Started $serviceName in $startCounter attempts\n");
        last;
      }
      $startCounter++;
    }

    if ($startCounter eq $maxAttempts) {
      logEvent("Unable to start $serviceName in $startCounter attempts\n");
    }
  }
}

sub getDate {
  my @timeInfo    = localtime(time);
  my $year  = $timeInfo[5] + 1900;
  my $month = $timeInfo[4] + 1;
  my $day   = $timeInfo[3];
  return sprintf("%04d-%02d-%02d", $year, $month, $day);
}

sub logEvent {
  my $msg = strftime("%H:%M:%S", localtime) . ": $_[0]\n";
  print "$msg";
  open(OUT, ">> C:/servicestatus/$currentDate.txt");
  print OUT "$msg";
  close(OUT);
}

Running this NOT as an admin, gives output like this:

14:11:30: Attempting to start Apple Mobile Device
14:11:35: Attempting to start Apple Mobile Device
14:11:40: Attempting to start Apple Mobile Device

Running as an admin looks like this:

14:14:29: Attempting to start Apple Mobile Device
14:14:34: Started Apple Mobile Device in 1 attempts

Altri suggerimenti

One major problem I have with this Win32::Service module is that it returns undef on failure BUT doesn't set $! so finding out why it failed is more work. I have not done any testing in retrieving that error, but it's probably a call to one of the functions in the Win32 module.

#!/usr/local/bin/perl

use 5.010;
use strict;
use warnings;
use POSIX qw(strftime);
use Win32::Service qw(StartService GetStatus GetServices);

my $service = shift || 'Apple Mobile Device';
check_service($service);
exit;

###############################################################################

sub check_service {
    my $service = shift;
    my %status_code = (
        Stopped       => 1,
        StartPending  => 2,
        StopPending   => 3,
        Running       => 4,
        ResumePending => 5,
        PausePending  => 6,
        Paused        => 7
    );
    my (%status, %services);

    GetServices('', \%services) or do {
        log_event('Failed to retieve list of services');
        exit;
    };
    %services = reverse %services;

    if (! exists $services{$service}) {
        log_event("'$service' is not a configured Windows service");
        exit;
    }

    if (GetStatus('', $service, \%status)) {
        if ($status{"CurrentState"} eq $status_code{Running} ) {
            log_event("$service is running");
        }
        elsif ( $status{"CurrentState"} eq $status_code{'Stopped'} ) {
            ATTEMPT: for (1..3) {
                log_event("Attempting to start '$service'");
                if (StartService('', $service)) {
                    sleep 5;
                    GetStatus('', $service, \%status);
                    if ($status{"CurrentState"} eq $status_code{Running}) {
                        log_event("Started '$service'");
                        last ATTEMPT;
                    }
                }
                else {
                    die "StartService() function failed";
                }
            }
        }
    }
    else {
        log_event("failed to retrieve the status of service '$service'");
        exit;
    }
    return;
}

sub log_event {

# Using one of the better loging modules such as Log::Log4perl
# would be a much better and more robust logging mechanism

    my $msg = shift;
    my $timestamp = strftime("%H:%M:%S", localtime);
    my $filename  = strftime("C:/servicestatus/%Y-%m-%d.txt", localtime);

    open(my $fh, '>>', $filename) or die "failed to open '$filename' <$!>";
    say $fh "$timestamp: $msg";
    close $fh;
    return;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top