Do not do it this way, run lighttpd strictly as a daemon. The daemon xinetd is mean to start services that are not actually running all the time. When xinetd sees traffic it "spins up" a particular service to meet the need, but otherwise the processes are not running.
By the way, you cannot share a TCP port between 2 daemons/services. Only one service can bind to a particular TCP port, essentially owning it for the duration of the time that it's running.
Doing it anyway
If you're absolutely sure you want to run it like this then take a look at this tutorial that shows exactly this scenario on a Raspberry Pi. The tutorial is titled: Starting mysqld and httpd on demand with xinetd.
This script was created, /etc/xinetd.init.d/lighttpd:
#!/bin/bash
# inspired on this article
# https://www.linuxnet.ch/automatic-tunnels-with-xinetd-and-netcat/
# script is called from xinetd
# script starts and stops service using /etc/init.d scripts
SERVICE=/etc/init.d/lighttpd # script used to start/stop service
PORT=81 # port where end service should listen
PID_FILE=/var/run/lighttpd.pid # pid file generated by init script
REAPER_PID_FILE="/var/run/lighttpd_reaper.pid" # pid file generated by this script
REAPER_SLEEP=180 # The reaper sleeps in seconds and checks for idle conns
LOG=/var/log/syslog # where to log messages
# this function checks if we already have reaper
check_reaper(){
if [ -s $REAPER_PID_FILE ]
then
reaper_pid=`cat $REAPER_PID_FILE 2>/dev/null`
ps -p $reaper_pid &> /dev/null
if [ $? -ne 0 ]
then
start_reaper & # If we don't have a reaper we start one
echo $! > $REAPER_PID_FILE
fi
else
start_reaper &
echo $! > $REAPER_PID_FILE
fi
}
# this function starts a reaper, which is a background process that will kill the end service if its inactive
start_reaper(){
while [ -f $PID_FILE ]
do
sleep $REAPER_SLEEP # We wait
touched=`stat --printf %W $REAPER_PID_FILE 2>/dev/null` # We check when the reaper PID was last touched
now=`date +%s 2>/dev/null`
let idle=$now-$touched
if [ $idle -gt $REAPER_SLEEP ] # If reaper pid has not been touched in more than a sleep cycle we stop the service
then
echo `date`" REAPER STOPPING SERVICE AFTER BEING $idle" >> $LOG
$SERVICE stop >> $LOG # This is the stop service instruction
rm $REAPER_PID_FILE
exit 0
fi
done
}
# This is where we start our service
start_service(){
sleep 1 # Added a delay to trouble shoot as browsers kickstart several connections, we need to allow the PID file to be created this can be improved.
if [ -s $PID_FILE ] # We check if the PID file for the end service exist to avoid calling the start script when the service has already been started
then
return
else
echo `date`" STARTING $SERVICE" >> $LOG
$SERVICE start &>> $LOG #this is the start service instruction
return
fi
}
# We probe and wait for the service to come on line
wait_for_service(){
nc -w30 -z 127.0.0.1 $PORT &>/dev/null # probe end port with a timeout of 30 seconds
if [[ $? -ne 0 ]]
then
echo `date`" XINET SERVICE START ON $PORT TIMED OUT" >> $LOG
fi
}
# This is were all the magic happens netcat passes traffic back and forth
transmit(){
nc -w30 127.0.0.1 $PORT 2>/dev/null # netcat is awesome, timeout flag of 30 seconds can be adjusted
}
# this is the main program that is called every time
main()
{
nc -z 127.0.0.1 $PORT &>/dev/null # We probe the end service
if [[ $? -ne 0 ]] # If its not responding
then
start_service # We start service
wait_for_service # We wait for service to became online
fi
check_reaper # We always check we have a reaper
touch $REAPER_PID_FILE # We log activity by touching the reaper PID file
transmit # We transmit data
exit 0
}
main
And the following xinetd service was created:
service http
{
disable = no
socket_type = stream
protocol = tcp
port = 80
server = /etc/xinetd.init.d/lighttpd
user = root
wait = no
}