6

I am trying to start PHP as a service, I run this command:

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

But the problem I am having, is when I open the services manager, and try to start the service I get this error:

Windows could not start the PHPSERVER service on Local Computer.

Error 1053: The service did not respond to the start or control request in a timely fashion.

Is there any way I can fix this, so it does work?

6
  • Did you run this script as administrator?
    – Dave
    Commented Aug 5, 2013 at 14:56
  • This can also be caused due to an infection (virus) so make sure your system is clean.
    – Dave
    Commented Aug 5, 2013 at 15:00
  • @DaveRook Yes I did Commented Aug 5, 2013 at 15:00
  • PHP Server or Apache server? Do you have Skype installed?
    – Dave
    Commented Aug 5, 2013 at 15:06
  • It is Nginx, and no I don't have Skype Commented Aug 5, 2013 at 16:31

2 Answers 2

2

Well, starting PHP like that simply won't work. "php-cgi.exe" is not a native windows service, hence you get Error 1053 when you try to start it. This post explains the situation in greater detail.

But I suspect that what you want to do is start Nginx as a service, pulling PHP along with it, right? You will need a third party "service wrapper", as described here.

1

The error you have is because the SCM (Windows service manager) tries to communicate with the service, to know it's state ("I'm starting", "I have started", "I'm running"…) or send orders ("please pause", "please stop")

You have to manage those exchanges, which can be done with the PECL win32service extension.

I first read about it here: https://stackoverflow.com/a/8703371/913967

My answer is for Windows only. On Linux, you would instead intercept OS signals like SIGINT and SIGTERM.

Important

As this is a Windows extension, you should always check if the functions are available for your current env. For exemple, with:

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

To init the service

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

To stop the service

At the end of your program, just before the exit() or whatever, indicate that the service is down:

win32_set_service_status(WIN32_SERVICE_STOP);

To intercept SCM messages and do what they ask for

You must periodically listen for messages, to know if you must do something. This is done by:

$scmAction = win32_get_last_control_message();

This can be added in an infinite loop or whatever (activated by a timer...)

You can then process the given order, and notify the SCM when it is done (so that the SCM knows you did what he asked) For example:

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

Install your script as a service

This can be done using the win32service extension, or manually with sc.exe

Using the win32service extension

Can be interesting if you want to manage installation/removal of your service in PHP. For example, if you want to implement some command line argument like:

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

To add a service (adjust names and script address)

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

Note that we do NOT define a path for php.exe here... so this one has to be found in your Windows PATH env. variable. Or specify the absolute address if you know it and you are sure it will not change on your system.

To remove the service:

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

Using sc.exe

For usage help: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create

Note: you must have admin rights when executing those commands.

To install the service

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

(As before, I didn't set the path for php.exe here. Add it if it is not in your PATH env. variable.

To remove the service

sc delete myservice

Test the service

Have to be done with admin rights

Start the service:

net start myservice

or:

sc start myservice

Stop the service:

net stop myservice

or:

sc stop myservice

Query service state:

sc query myservice

Ask to pause / resume:

sc pause myservice
sc continue myservice

(Do a sc query again after to know the state)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .