用于启动/停止Windows服务的Perl脚本

时间:2014-05-14 15:15:03

标签: windows perl

这是用于检查Windows服务状态的脚本,如果它们处于停止状态,它将启动该服务。我能够获得服务状态,但无法启动服务。 请帮忙,让我知道我需要做什么。

#!/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);
}

2 个答案:

答案 0 :(得分:2)

基于下面的一些评论(包括@Ron Bergin的一些不错的观点),我正在修改这篇文章,以显示适合我的代码(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);
}

以管理员身份运行此NOT,输出如下:

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

以管理员身份运行如下:

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

答案 1 :(得分:1)

我对这个Win32 :: Service模块的一个主要问题是它在失败时返回undef 但是没有设置$!因此找出失败的原因是更多的工作。我没有在检索该错误方面做过任何测试,但它可能是对Win32模块中某个函数的调用。

#!/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;
}