私はPerlを使用してWindowsサービスを作成しています。私はWin32::Daemon
この目的のために使用しています。
サービスを処理しているPerlスクリプト(開始および停止コールバックなどを受け入れる)は、system()
コマンドを使用して.batファイルを呼び出し、最終的には最終的なPerlプログラムを呼び出します。
問題は、サービスを停止すると、によって起動されたプロセスがsystem()
閉じられず、最終プロセス(によって生成されたプロセスによって起動された)も閉じられないことsystem()
です。
これは、プロセス間に「親子」関係がないようなものです(Windowsサービスを停止すると、通常、関連するすべてのプロセスが同時に閉じられます)。
編集:上記のコードを追加しました。サービスコールバックを登録してStartServiceを呼び出すメイン関数と、start、running、stopの3つのメインコールバックを表示しました。
sub main {
#registering service callbacks
Win32::Daemon::RegisterCallbacks( {
start => \&Callback_Start,
running => \&Callback_Running,
stop => \&Callback_Stop,
pause => \&Callback_Pause,
continue => \&Callback_Continue,
} );
my %Context = (
last_state => SERVICE_STOPPED,
start_time => time(),
);
Win32::Daemon::StartService( \%Context, 2000 );
# Here the service has stopped
close STDERR; close STDOUT;
}
#function called after the start one
sub Callback_Running
{
my( $Event, $Context ) = @_;
#Here I had to make an infinite loop to make the service "persistant". Otherwise it stops automatically (maybe there's something important I missed here?
if( SERVICE_RUNNING == Win32::Daemon::State() )
{
Win32::Daemon::State( SERVICE_RUNNING );
}
}
#function first called by StartService
sub Callback_Start
{
#above is stated the system() call where I trigger the .bat script
my( $Event, $Context ) = @_;
my $cmd = "START \"\" /Dc:\\path\\to\\script\\dir\\ \"script.bat\"";
print $cmd."\n";
system($cmd);
$Context->{last_state} = SERVICE_RUNNING;
Win32::Daemon::State( SERVICE_RUNNING );
}
sub Callback_Stop
{
my( $Event, $Context ) = @_;
#Things I should do to stop the service, like closing the generated processes (if I knew their pid)
$Context->{last_state} = SERVICE_STOPPED;
Win32::Daemon::State( SERVICE_STOPPED );
# We need to notify the Daemon that we want to stop callbacks and the service.
Win32::Daemon::StopService();
}