0

I am coding a simple chat in 100% PHP, that uses WebSocket (with no external library, like in this article).

Obviously, this requires a constantly-running PHP script / daemon / event-loop (similar to how Node.JS works), that we start with:

php -q websockets.php

or nohup ..., or with a dedicated Systemd service (started with systemctl start myservice.service), or with service myservice start.

Question: let's say the person who installs this chat software has no access to command-line (or doesn't know about it enough to do it), how can we start the websockets.php daemon directly from a web page, and keep it constantly running?

The admin could click on a button in his admin panel and, through a XHR/AJAX request, this would trigger a server-side code startup.php. What would be necessary in this startup.php, in order to start and keep websockets.php running forever?

I know exec, but is it adapted in this case?

(More precisely, let's say this admin has no command-line/SSH access, and has only been able to upload the code via (S)FTP; then they can only use a web interface to start or stop the chat daemon server)

Basj
  • 41,386
  • 99
  • 383
  • 673
  • 1
    Very unlikely they could do it because you'd most likely need admin permission to start a daemon on Linux – ADyson Jan 31 '21 at 00:12
  • If your users only have access to an FTP server for uploading files to a web server, then they likely can’t run this kind of thing at all. – deceze Jan 31 '21 at 08:02
  • @ADyson Let's say they could not run a `service myservice start` or use `systemctl`, but that they *could* run `php -q eventloop.php` with user `www-data`, how would you trigger the start of this process from PHP? – Basj Jan 31 '21 at 08:34
  • You'd have to use exec or shell_exec. I don't have a lot of experience of that but I think https://stackoverflow.com/questions/3819398/php-exec-command-or-similar-to-not-wait-for-result will help you because clearly you'll want to fire and forget. Your main problem will be though that you won't be able to detect if the program fails, or if it needs restarting for any reason. (And that's assuming the host even lets you execute it to begin with). Bottom line, if you want to run your own processes, don't use cheap shared hosting, use a proper environment – ADyson Jan 31 '21 at 08:42
  • Thanks @ADyson, I think this is the answer to this question, if you want to post it. – Basj Jan 31 '21 at 09:13

2 Answers2

2

It's very unlikely they could do it successfully because you'd probably need admin permission to start a daemon on Linux.

You'd have to use exec() or shell_exec() to try and run the command from PHP. I don't have a lot of experience of that but I think php exec command (or similar) to not wait for result will help you because clearly you'll want to fire and forget.

Your main problem will be though that you won't be able to detect if the program fails, or if it needs restarting for any reason. (And that's assuming the host even lets you execute it to begin with).

The bottom line is, really, if you want to run your own processes, don't use cheap shared hosting, use a proper environment.

ADyson
  • 57,178
  • 14
  • 51
  • 63
1

In websockets.php I would create a conditional statement that checks whether the button was clicked (on/off settings from the database). Some pseudo-code:

// Retrieve $enabled value from the database
if($enabled) {
   $address = '0.0.0.0';
   $port = 12345;

   $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
   // ...
}

// If not enabled just don't do anything.

Then you can use supervisord and configure it like this in /etc/supervisor/conf.d:

[program:php-websockets]
command=php -q /home/bob/websockets.php
autostart=true
autorestart=true
user=bob
redirect_stderr=true
stdout_logfile=/home/bob/logs/worker.log

Make sure to update supervisor after making any changes in configuration.

supervisorctl reread
supervisorctl update

But if you don't have an access to command line at all then it's impossible to do it.

Artur Nawrot
  • 473
  • 1
  • 8
  • 19