1

我正在尝试在 Windows Server 2008 SP1 机器上设置 PHP Web 应用程序。我们让这个应用程序在 Windows Server 2003 上正确运行,但现在无法PHP正确启动使用 php_win32service 扩展构建的 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状态。

I think this issue has something to do with the rights of the LocalSystem account on the machine, but I do not know what rights are needed to get this to work properly. I also do not know how I can debug this and find out what error/issue is occurring with the WIN32_SERVICE_CONTROL_INTERROGATE, especially as I do not have rights on this server to make changes to security settings. Any changes that I need made to security settings I need to communicate to the network administrator so that he can perform the changes. Can anyone offer any help with debugging or resolving this issue?

UPDATE:

This issue only seems to occur in the 64-bit version of PHP. It seems that the 64-bit compile of php_win32service runs into some sort of problem when trying to start the service. I removed the 64-bit versions of PHP and 'php_win32service' and replaced them with the 32-bit versions. The service then started correctly.

4

2 回答 2

1

Have you tried with NetworkService account? Other way is creating own service account. Do you communicate outside the server? Maybe firewall?

Ps. the network service account has a default password (system known)

Note that this account does not have a password, so any password information that you provide in this call is ignored.

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

于 2013-03-21T13:43:37.767 回答
0

Updated Answer:

I am now convinced that this issue arises when you update or downgrade PHP to a different version, but fail to remove and recreate the services using the php_win32service for the newly installed version of PHP. This was mentioned as an aside in my old answer, but after encountering the same thing on another server and resolving it by removing and recreating the service entries, I am convinced that this is the true cause of this issue and that is not a bug in PHP.

Old Answer:

I encountered this issue again when I tried to update PHP on a Windows Server 2008 machine from 5.3 to 5.6. From the testing that I have done I have concluded that php_win32service.dll extension works correctly for PHP 5.3, but not from 5.4 upwards. From 5.4 there seems to be a bug whereby the function win32_get_last_control_message always returns 0 rather than a valid status.

I finally got a clue to what was going on from a post made over here: http://enlinea.creaelicita.cl/guia/function.win32-set-service-status.html

So, if you have code such as this:

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();
}

then

win32_set_service_status(WIN32_SERVICE_RUNNING);

will never get called, because win32_get_last_control_message never gets the value of 4 (WIN32_SERVICE_CONTROL_INTERROGATE).

A workaround which I use is to add a default case to the switch statement that sets the service status. Like this:

 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);
 } 

As an aside, I also found that this issue occurred if I upgraded to PHP 5.4 and did not recreate the service entries before trying to start them. So besides applying the above workaround, remember to first uninstall the windows service in question and reinstall it from your PHP script.

于 2016-01-14T14:13:53.790 回答