An easy way to start the embedded PHP web server with the multi-thread option enabled or simulated when necessary.
In all of my coding projects, I like to follow these principles:
While also trying to avoid this:
Which then imply a lot of research to make sure I would not reinvent the wheel when it is not necessary π
But for this use case, I was also too much lazy to always having to think about adding PHP_CLI_SERVER_WORKERS=$(nproc)
before running php -S
and then unlock the recently added multi-threading feature π€
I've also tried to improve the lack of connection concurrency in the older PHP
versions (< 7.4
) but it was pretty hacky and didn't worked very well... Then I've found something interesting on StackOverflow that has solved this issue but needed some minor improvement like simply tuning the sleep
value.
In order to simulate the connection concurrency / multi-threading feature in older PHP
versions ONLY, it will be required to install the ucspi-tcp
package before running the script simple-php-webserver.sh
.
Skip this step if you are currently running or planning to install
PHP
version >=7.4
.
# For Ubuntu based distrib
sudo apt install ucspi-tcp
# For RPM based distrib
sudo yum install ucspi-tcp
# For modern RPM based distrib
sudo dnf install ucspi-tcp
You can replace by or add the
ucspi-tcp-ipv6
package if you want to also handleIPv6
connections for oldPHP
versions.
And for running the web server without any other dependencies:
# For Ubuntu based distrib
sudo apt install php-cli
# For RPM based distrib
sudo yum install php-cli
# For modern RPM based distrib
sudo dnf install php-cli
It should automatically install few other required dependencies but still stays a very minimal
PHP
stack installed.
The script simple-php-webserver.sh
will first detect the currently installed PHP
version then according to the test result, decide to use the embedded web server or rely on tcpserver
throught the proxy-to-php-server.sh
script to simulate the multi-threading feature and unlock the multi connections concurrency power that is lacking in older PHP
versions.
So in the end, instead of always typing:
- Linux
# For single file
PHP_CLI_SERVER_WORKERS=$(nproc) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} index.php
# For directory
PHP_CLI_SERVER_WORKERS=$(nproc) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} -t .
- MacOS
# For single file
PHP_CLI_SERVER_WORKERS=$(sysctl -n hw.ncpu) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} index.php
# For directory
PHP_CLI_SERVER_WORKERS=$(sysctl -n hw.ncpu) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} -t .
Thanks a lot to @staatzstreich for the MacOS example π
I just have to type:
./simple-php-webserver.sh
And I don't have to worry about the lack of connection concurrency anymore π
The magic thing here is the use of nproc
to detect how many available CPU cores to decide how many server workers should be created internally in PHP
.
This way, I don't have to set an arbitrary value and risk to overload the host.
The script simple-php-webserver.sh
can be easily improved to let's say better handling the default PHP
file to read or support a router.php
file for example.
I'll probably try take the time to improve it later π
Feel free to comment this gist if you want to improve it π
simple-php-webserver.sh
:
#!/bin/bash
# Increasing local web server performances as possible
# https://stackoverflow.com/questions/39842170/load-balancing-php-built-in-server/47103758#47103758
# https://www.php.net/manual/en/features.commandline.webserver.php
# Config
LISTEN_INTERFACE="localhost"
LISTEN_PORT=8000
ENTRY_POINT=$1
# Detect server type to use
PHP_SRV_TYPE=$(php -r "if (version_compare(phpversion(), '7.4', '<')) { echo 'tcpserver'; } else { echo 'embedded'; }")
# Run detected server type
if [[ $PHP_SRV_TYPE == 'embedded' ]]; then
if [[ -d $ENTRY_POINT ]]; then
PHP_CLI_SERVER_WORKERS=$(nproc) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} -t $ENTRY_POINT
else
PHP_CLI_SERVER_WORKERS=$(nproc) php -S ${LISTEN_INTERFACE}:${LISTEN_PORT} $ENTRY_POINT
fi
else
tcpserver -v -1 0 ${LISTEN_PORT} ./proxy-to-php-server.sh $ENTRY_POINT
fi
proxy-to-php-server.sh
:
#!/bin/bash -x
# Increasing local web server performances as possible
# https://stackoverflow.com/questions/39842170/load-balancing-php-built-in-server/47103758#47103758
# get a random port -- this could be improved
port=$(shuf -i 2048-65000 -n 1)
# start the PHP server in the background
if [[ -d "$(realpath ${1:?Missing path to serve})" ]]; then
php -S localhost:"${port}" -t "$(realpath ${1:?Missing path to serve})" &
else
php -S localhost:"${port}" "$(realpath ${1:?Missing path to serve})" &
fi
pid=$!
# try to adjust delay to improve performances
sleep 0.2
# proxy standard in to nc on that port
nc localhost "${port}"
# kill the server we started
kill "${pid}"
Make them executable with chmod -v +x simple-php-webserver.sh proxy-to-php-server.sh
.
Hey π
thanks for sharingπ
Did not know that before ...
On MacOS an PHP installed with Homebrew it works like so: