重要的

重要的

我正在尝试启动 PHP 作为服务,我运行以下命令:

C:\Windows\system32>sc create PHPSERVER binpath= "C:\php\php-cgi.exe -b 127.0.0.1:9000" start= auto
[SC] CreateService SUCCESS

但我遇到的问题是,当我打开服务管理器并尝试启动服务时出现此错误:

Windows 无法在本地计算机上启动 PHPSERVER 服务。

错误 1053:服务未及时响应启动或控制请求。

有什么方法可以修复此问题,使其正常工作?

答案1

嗯,这样启动 PHP 根本行不通。“php-cgi.exe”不是原生 Windows 服务,因此当您尝试启动它时会出现错误 1053。这个帖子更详细地解释了情况。

但我怀疑你想要做的是启动 Nginx 作为服务,并拉动 PHP,对吗?你需要一个第三方“服务包装器”,如这里所述

答案2

您遇到的错误是因为 SCM(Windows 服务管理器)尝试与服务通信,以了解其状态(“我正在启动”、“我已经启动”、“我正在运行”…)或发送命令(“请暂停”、“请停止”)

您必须管理这些交换,这可以通过 PECL 来完成鍵盤扩大。

我第一次在这里读到它:https://stackoverflow.com/a/8703371/913967

我的答案仅适用于 Windows。在 Linux 上,你可以拦截 SIGINT 和 SIGTERM 等 OS 信号。

重要的

由于这是 Windows 扩展,因此您应始终检查这些功能是否适用于您当前的环境。例如,使用:

if ( function_exists('win32_start_service_ctrl_dispatcher') ) {
    // OK, I'm on Windows I can execute win32_xxx functions
}

初始化服务

// Start the dialog with the SCM
win32_start_service_ctrl_dispatcher('myservice');

// If our program takes a long time before being ready,
// we can tell the SCM that we are starting (unnecessary if it's fast)
win32_set_service_status(WIN32_SERVICE_START_PENDING);

// OK, we are ready
win32_set_service_status(WIN32_SERVICE_RUNNING);

停止服务

在程序的末尾,就在exit()或其他内容之前,表明服务已关闭:

win32_set_service_status(WIN32_SERVICE_STOP);

拦截 SCM 消息并按其要求执行

您必须定期收听消息,以了解是否必须执行某些操作。这是通过以下方式完成的:

$scmAction = win32_get_last_control_message();

这可以添加到无限循环或其他任何循环中(由计时器激活......)

然后,您可以处理给定的订单,并在完成时通知 SCM(以便 SCM 知道您按照他的要求做了)例如:

switch ($scmAction) {
    // Asked to stop
    case WIN32_SERVICE_CONTROL_SHUTDOWN:
    case WIN32_SERVICE_CONTROL_STOP:
        win32_set_service_status(WIN32_SERVICE_STOP_PENDING);
        // ...
        // do your stuff here to stop your service
        // ...
        win32_set_service_status(WIN32_SERVICE_STOPPED);
        break;

    // Asked to pause
    case \WIN32_SERVICE_CONTROL_PAUSE:
        // ...
        // do your stuff here to pause your service
        // (for example: keep your infinite loop, but do not process things in it)
        // ...
        \win32_set_service_status(\WIN32_SERVICE_PAUSED);
        break;

    // Asked to continue (after a pause)
    case \WIN32_SERVICE_CONTROL_CONTINUE:
        // ...
        // do your stuff here to reactivate your service
        // ...
        \win32_set_service_status(\WIN32_SERVICE_RUNNING);
        break;

    // Asked for our current state
    case \WIN32_SERVICE_CONTROL_INTERROGATE:
            $state = $paused ? WIN32_SERVICE_PAUSED : WIN32_SERVICE_RUNNING;
            \win32_set_service_status($state);
}

将脚本安装为服务

这可以使用 win32service 扩展来完成,或者手动使用sc.exe

使用 win32service 扩展

如果您想在 PHP 中管理服务的安装/删除,这可能会很有趣。例如,如果您想实现一些命令行参数,例如:

php my_script.php --install
php my_script.php --remove

添加服务 (调整名字和脚本地址)

$result = win32_create_service([
    'service'       => 'myservice',
    'display'       => 'My PHP Service',
    'path'          => 'php.exe',
    'params'        =>  __DIR__.'\\my-service.php',
]);
if ($result != WIN32_NO_ERROR) {
    // Something went wrong
    // For the error explanation, compare $result with the error codes constants
    // in https://www.php.net/manual/en/win32service.constants.errors.php
}

请注意,我们没有在php.exe此处定义路径...因此必须在 WindowsPATH环境变量中找到此路径。或者,如果您知道绝对地址并且确定它不会在您的系统上更改,请指定绝对地址。

要删除服务:

$result = win32_delete_service('myservice');
if ($result != WIN32_NO_ERROR) {
        // Same as above
}

使用 sc.exe

使用帮助:https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create

注意:执行这些命令时您必须具有管理员权限。

安装服务

sc create myservice type= own start= auto binpath= "php.exe -f C:\Path\to\my\php-script.php" displayname= "My PHP Service"

(和以前一样,我没有在这里设置路径php.exe。如果它不在您的PATH环境变量中,请添加它。

删除服务

sc delete myservice

测试服务

必须使用管理员权限

启动服务:

net start myservice

或者:

sc start myservice

停止服务:

net stop myservice

或者:

sc stop myservice

查询服务状态:

sc query myservice

请求暂停/恢复:

sc pause myservice
sc continue myservice

sc query之后再做一次以了解状态)

相关内容