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 |
|