扩展名php_win32service安装了服务,但是服务没有启动(挂起)


Extension php_win32service installs the service, but the service won't start up (hangs)

我正在尝试在Windows Server 2008 SP1机器上安装PHP web应用程序。我们已经在Windows Server 2003上正常运行了这个应用程序,但是现在无法让使用php_win32service PHP扩展构建的Windows服务正确启动。

以下是PHP代码的相关部分。下面是执行安装和卸载的部分:

if ($argv[1] == 'install') {
    win32_create_service(array(
        'service' => $service_name,
        'display' => $service_name,
        'params' => '"'. __FILE__ . '"' . ' run'));
        exit;
} 
else if ($argv[1] == 'uninstall') {
    win32_delete_service($service_name);
    exit;
} 
else if ($argv[1] != 'run') {
   die("Invalid arguments");
}
win32_start_service_ctrl_dispatcher($service_name);

下面是主循环:

while (1) {
    switch (win32_get_last_control_message()) {
       case WIN32_SERVICE_CONTROL_INTERROGATE: win32_set_service_status(WIN32_SERVICE_RUNNING); break; // Respond with status
       case WIN32_SERVICE_CONTROL_STOP: win32_set_service_status(WIN32_SERVICE_STOPPED);  exit; // Terminate script
    }         
    processQueue();
    usleep(500000);
}

安装和卸载工作,只要我运行cmd管理员。如果我在用于登录服务器的帐户下启动cmd,则不会创建win32_create_service服务。我也可以从命令行中使用run参数运行脚本,它运行正确,但是当我尝试启动服务时,它只是与Starting消息一起挂起,并且永远不会进入Started状态。

我认为这个问题与机器上LocalSystem帐户的权限有关,但我不知道需要什么权限才能正常工作。我也不知道如何调试这一点,并找出WIN32_SERVICE_CONTROL_INTERROGATE发生了什么错误/问题,特别是因为我没有在此服务器上更改安全设置的权利。我需要对安全设置进行任何更改,我都需要与网络管理员进行通信,以便他可以执行更改。有人可以提供任何帮助调试或解决这个问题吗?

更新:

这个问题似乎只发生在64位版本的PHP中。似乎php_win32service的64位编译在尝试启动服务时遇到了某种问题。我删除了64位版本的PHP和'php_win32service',并用32位版本替换它们。

您是否尝试过使用NetworkService帐户?另一种方法是创建自己的服务帐户。您是否在服务器外部进行通信?也许防火墙?

p。网络服务帐户有默认密码(系统已知)

请注意,此帐户没有密码,因此您在此调用中提供的任何密码信息都将被忽略。

http://msdn.microsoft.com/nl-nl/library/windows/desktop/ms684272 (v = vs.85) . aspx

更新答案:

我现在确信,当您将PHP更新或降级到另一个版本,但未能为新安装的PHP版本删除和重新创建使用php_win32service的服务时,会出现此问题。这是在我的旧答案中作为旁白提到的,但是在另一个服务器上遇到同样的事情并通过删除和重新创建服务条目来解决它之后,我相信这是这个问题的真正原因,这不是PHP中的错误。

老回答:

当我试图在Windows Server 2008机器上从5.3更新PHP5.6时,我又遇到了这个问题。从我所做的测试中我得出的结论是,php_win32service.dll扩展正确地适用于PHP 5.3,但不适用于5.4以上。从5.4中似乎有一个bug,即函数win32_get_last_control_message总是返回0而不是有效状态。

我终于从这里的一个帖子中得到了一个线索:http://enlinea.creaelicita.cl/guia/function.win32-set-service-status.html

那么,如果你有这样的代码:

while (1) {
    switch (win32_get_last_control_message()) {
        case WIN32_SERVICE_CONTROL_INTERROGATE: win32_set_service_status(WIN32_SERVICE_RUNNING); break; // Respond with status
        case WIN32_SERVICE_CONTROL_STOP: win32_set_service_status(WIN32_SERVICE_STOPPED); exit; // Terminate script
    }    
    usleep(3000000);
    // Main script goes here
    processQueue();
}
然后

win32_set_service_status(WIN32_SERVICE_RUNNING);

将永远不会被调用,因为win32_get_last_control_message永远不会得到4 (WIN32_SERVICE_CONTROL_INTERROGATE)的值。

我使用的一个解决方案是在switch语句中添加一个默认的case来设置服务状态。这样的:

 switch (win32_get_last_control_message()) {
        case WIN32_SERVICE_CONTROL_INTERROGATE: win32_set_service_status(WIN32_SERVICE_RUNNING); break; // Respond with status
        case WIN32_SERVICE_CONTROL_STOP: win32_set_service_status(WIN32_SERVICE_STOPPED); exit; // Terminate script
        default: win32_set_service_status(WIN32_SERVICE_RUNNING);
 } 

作为题外话,我还发现,如果我升级到PHP 5.4并且在尝试启动服务条目之前没有重新创建服务条目,则会发生此问题。因此,除了应用上述解决方案外,请记住首先卸载有问题的windows服务,然后从PHP脚本重新安装它。