in reply to Re^3: Perl script as windows service
in thread Perl script as windows service

Please excuse me as I am new to perl and still struggling to grasp some ideas and need your help. I tried running the above example it doesn't give any error and ran fine but everytime I try to run it from the commandline it executes the following:
else { die "Nothing to do\n"; }
and no service is created. Is there any parameter needs to pass while running the script. And what exactly is the following for:
my %opt; GetOptions ( \%opt, "run", "install", "remove", "start", "stop", "restart", "pause", "resume|continue", );
What exactly is GetOptions for. I tried to modify thie above scripty and put the following code in the else part:
else { #die "Nothing to do\n"; &removeService(); &installService(); my $cmd = 'net start $serviceConfig{name}'; my $results = `$cmd`; if($!) { &debug("Net Start returned error: $@\n" . $results); die "ERROR"; } #don't know what is this for my %context = { last_state => SERVICE_STOPPED, count => 0, start_time => time(), }; Win32::Daemon::StartService( \%context, 3000 ); exit(); }
now I run the script and service gets created and can start,stop,resume etc.. the service under services. I don't if it's the right way. Any comments will be really appeciated. Thanks

Replies are listed 'Best First'.
Re^5: Perl script as windows service
by m-rau (Scribe) on Mar 10, 2005 at 12:21 UTC
    Please see my comments below.
    001 | #!/usr/bin/perl 002 | 003 | $| = 1; 004 | 005 | use strict; 006 | use Getopt::Long; 007 | 008 | use Win32; 009 | use Win32::Daemon; 010 | 011 | my %opt; 012 | GetOptions ( 013 | \%opt, 014 | "run", 015 | "install", 016 | "remove", 017 | "start", 018 | "stop", 019 | "restart", 020 | "pause", 021 | "resume|continue", 022 | ); See Getopt::Long module, start with `perldoc Getopt::Long` Use the options with `perl service.pl --install` `perl service.pl --start` Then, be happy with your service. Boring, hee? So, stop and remove the service with `perl service.pl --stop` `perl service.pl --remove` That's what this GetOptions thing is about. 023 | 024 | my @currDir = split /\//, $0; 025 | my $script = $0; 026 | my $scriptPath = "."; 027 | 028 | if (scalar @currDir > 1) 029 | { 030 | $script = pop @currDir; 031 | $scriptPath = join "/", @currDir; 032 | chdir( $scriptPath ); 033 | } The above staff is used to chdir to the script's directory. This can be derived from $0 if started with something like `perl c:/path/to/my/servce/servce.pl` servce.pl is poped away from c:/path/to/my/servce/servce.pl and @currDir == ( 'c:', 'path', 'to', 'my', 'servce' ) is joined with a "/" to $scriptPath. 034 | 035 | my %serviceConfig = ( 036 | 037 | name => 'mytest', 038 | display => 'mytest', 039 | description => 'this is my test description', 040 | machine => '', 041 | path => $^X, 042 | parameters => ( sprintf '"e:/dia/temp/service.pl" --run +', 043 | $scriptPath, 044 | $script ), 045 | start_type => SERVICE_AUTO_START, 046 | ); 047 | We talked about this. 048 | Win32::Daemon::RegisterCallbacks( 049 | { 050 | start => \&startService, 051 | stop => \&stopService, 052 | pause => \&pauseService, 053 | continue => \&continueService, 054 | running => \&runService, 055 | } 056 | ); 057 | 058 | # ============================================================== +================ 059 | # main 060 | # ============================================================== +================ What follows is the processing of the GetOptions results. 061 | 062 | if( $opt { install } ) 063 | { 064 | &installService(); 065 | exit(); 066 | } 067 | elsif( $opt { remove } ) 068 | { 069 | &removeService(); 070 | exit(); 071 | } 072 | elsif( $opt { status } ) 073 | { 074 | &serviceStatus(); 075 | exit(); 076 | } 077 | elsif( $opt { run } ) 078 | { 079 | my %context = { 080 | last_state => SERVICE_STOPPED, 081 | count => 0, 082 | start_time => time(), 083 | }; 084 | Win32::Daemon::StartService( \%context, 5000 ); 085 | } 086 | elsif( $opt { start } ) 087 | { 088 | my $cmd = sprintf 'net start %s', $serviceConfig { name }; 089 | system( $cmd ); 090 | exit(); 091 | } 092 | elsif( $opt { stop } ) 093 | { 094 | my $cmd = sprintf 'net stop %s', $serviceConfig { name }; 095 | system( $cmd ); 096 | exit(); 097 | } 098 | elsif( $opt { pause } ) 099 | { 100 | my $cmd = sprintf 'net pause %s', $serviceConfig { name }; 101 | system( $cmd ); 102 | exit(); 103 | } 104 | elsif( $opt { resume } ) 105 | { 106 | my $cmd = sprintf 'net continue %s', $serviceConfig { name } +; 107 | system( $cmd ); 108 | exit(); 109 | } 110 | elsif( $opt { restart } ) 111 | { 112 | my $cmd = sprintf 'net stop %s', $serviceConfig { name }; 113 | system( $cmd ); 114 | $cmd = sprintf 'net start %s', $serviceConfig { name }; 115 | system( $cmd ); 116 | exit(); 117 | } 118 | else 119 | { 120 | die "Nothing to do\n"; 121 | } What follows are the modularized routines triggered by the above GetOptions cases. 122 | 123 | # ============================================================== +================ 124 | # SERVICE SETUP 125 | # ============================================================== +================ 126 | 127 | sub installService 128 | { 129 | # installs the win32 service daemon 130 | # --------------------------------- 131 | if( Win32::Daemon::CreateService( \%serviceConfig ) ) 132 | { 133 | &debug( 'The service [%s] was successfully installed', $ +serviceConfig { display } ); 134 | } 135 | else 136 | { 137 | &debug( 'Failed to install the service [%s]: %s', 138 | $serviceConfig { display }, 139 | GetError() ); 140 | } 141 | } 142 | 143 | # ============================================================== +================ 144 | 145 | sub removeService 146 | { 147 | # removes the win32 service daemon 148 | # -------------------------------- 149 | if( Win32::Daemon::DeleteService( $serviceConfig { name } ) +) 150 | { 151 | &debug( 'The service [%s] was successfully removed', $se +rviceConfig { display } ); 152 | } 153 | else 154 | { 155 | &debug( 'Failed to remove the service [%s]: %s', 156 | $serviceConfig { display }, 157 | GetError() ); 158 | } 159 | } 160 | 161 | # ============================================================== +================ 162 | # CALLBACK ROUTINES 163 | # ============================================================== +================ 164 | 165 | sub startService 166 | { 167 | # start the win32 service daemon 168 | # ------------------------------ 169 | my ($event, $context) = @_; 170 | 171 | $context -> { last_state } = SERVICE_RUNNING; 172 | Win32::Daemon::State( SERVICE_START_PENDING, 30000 ); 173 | 174 | &debug( 'Starting the service' ); 175 | 176 | # let's go 177 | Win32::Daemon::State( SERVICE_RUNNING ); 178 | } 179 | 180 | # ============================================================== +================ 181 | 182 | sub stopService 183 | { 184 | # stop the win32 service daemon 185 | # ----------------------------- 186 | my ($event, $context) = @_; 187 | $context -> { last_state } = SERVICE_STOPPED; 188 | Win32::Daemon::State( SERVICE_STOP_PENDING, 30000 ); 189 | 190 | &debug( 'Stopping the service' ); 191 | 192 | Win32::Daemon::State( SERVICE_STOPPED ); 193 | Win32::Daemon::StopService(); 194 | } 195 | 196 | # ============================================================== +================ 197 | 198 | sub pauseService 199 | { 200 | # let the win32 service daemon make a pause 201 | # ----------------------------------------- 202 | my ($event, $context) = @_; 203 | &debug( 'Pausing the service' ); 204 | $context -> { last_state } = SERVICE_PAUSED; 205 | Win32::Daemon::State( SERVICE_PAUSED ); 206 | } 207 | 208 | # ============================================================== +================ 209 | 210 | sub continueService 211 | { 212 | # let the win32 service daemon exit a pause 213 | # ----------------------------------------- 214 | my ($event, $context) = @_; 215 | &debug( 'Resuming the service' ); 216 | $context -> { last_state } = SERVICE_RUNNING; 217 | Win32::Daemon::State( SERVICE_RUNNING ); 218 | } 219 | 220 | # ============================================================== +================ 221 | 222 | sub runService 223 | { 224 | # this is the callback of by the win32 service daemon 225 | # --------------------------------------------------- 226 | my ($event, $context) = @_; 227 | 228 | if ( Win32::Daemon::State() == SERVICE_RUNNING ) 229 | { 230 | # count the number of calls (I do not know why) 231 | $context -> { count }++; 232 | } 233 | } 234 | 235 | sub debug 236 | { 237 | my ($fmt, @data) = @_; 238 | my $message = sprintf $fmt, @data; 239 | open( FILE, ">>e:/dia/temp/service.log" ); 240 | print FILE "$message\n"; 241 | close( FILE ); 242 | if (-t STDOUT && -t STDIN) 243 | { 244 | print "$message\n"; 245 | } 246 | 247 | } 248 | 249 | # ============================================================== +================ 250 | 251 | sub GetError 252 | { 253 | # returns win32 daemon errors 254 | # --------------------------- 255 | return( Win32::FormatMessage( Win32::Daemon::GetLastError() +) ); 256 | } 257 | 258 | # ============================================================== +================ 259 | 260 | __END__ 261 |