2

I am trying to start a php script as a daemon in Debian. I also would like it to start on boot as well.

I have been starting using /path/to/php /path/to/script/Insert.php & without issue, and can shell_exec("nohup /path/to/php /path/to/script/Insert.php >/dev/null &") as well. I have tried using the below script, but it does not take the script into an operational state.

Am copying the file to /etc/init.d/ and using update-rc.d without issues. I can use service congen-insert startto 'start' the script, but it doesn't seem to actually run, and it doesn't start doing any work.

What am I missing, or where have I gone wrong with the scripts?

I know there are several ways to work around this, but I am really just trying to understand what I am doing incorrectly or why what I am doing is not working.

Any help or suggestions is extremely appreciated! If there is anything else you need or anything I have missed in my description, please let me know so I can correct it.

Thanks in advance.

Service script

#! /bin/sh
### BEGIN INIT INFO
# Provides:          congen-insert
# Required-Start:    $local_fs $network
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: congen-insert
# Description:       DB Insert Daemon
### END INIT INFO

NAME="congen-insert"
DESC=" DB Insert Daemon"
PIDFILE="/var/run/${NAME}.pid"
LOGFILE="/var/log/${NAME}.log"

DAEMON="/path/to/php"
DAEMON_OPTS="/path/to/script/Insert.php"

START_OPTS="--start --background --make-pidfile --pidfile ${PIDFILE} --exec ${DAEMON} ${DAEMON_OPTS}"
STOP_OPTS="--stop --pidfile ${PIDFILE}"

test -x $DAEMON || exit 0

set -e

case "$1" in
    start)
        echo -n "Starting ${DESC}: "
        start-stop-daemon $START_OPTS >> $LOGFILE
        echo "$NAME."
        ;;
    stop)
        echo -n "Stopping $DESC: "
        start-stop-daemon $STOP_OPTS
        echo "$NAME."
        rm -f $PIDFILE
        ;;
    restart|force-reload)
        echo -n "Restarting $DESC: "
        start-stop-daemon $STOP_OPTS
        sleep 1
        start-stop-daemon $START_OPTS >> $LOGFILE
        echo "$NAME."
        ;;
    status)
    echo -n "Sorry, this isn't implemented yet"
    ;;
    *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|restart|force-reload}" >&2
        exit 1
        ;;
esac

exit 0

Script I am trying to run:

const LoaderPath = __DIR__ . DIRECTORY_SEPARATOR . ".." .DIRECTORY_SEPARATOR . "includes.php";

require_once  LoaderPath;

use PhpAmqpLib\Channel\AMQPChannel;
use PhpAmqpLib\Message\AMQPMessage;
use requests\InsertRequest;

$connection = GetRabbitConnection();

$channel = $connection->channel();

$RedisClient = GetRedisClient();

DeclareQueues($connection, $RedisClient);

$MySQLHost = $RedisClient->get(MySQLHostKey);
$MySQLUser = $RedisClient->get(MySQLUserKey);
$MySQLPassword = $RedisClient->get(MySQLPasswordKey);
$MySQLDatabase = $RedisClient->get(MySQLDatabaseKey);

$InsertExchange = $RedisClient->get(Insert.":".Exchange);
$InsertQueue = $RedisClient->get(Insert.":".Queue);
$Prefetch = $RedisClient->get(Insert.":".Prefetch);

$RedisClient->disconnect();
$RedisClient = null;

$mysql= new mysqli($MySQLHost, $MySQLUser, $MySQLPassword, $MySQLDatabase);

$channel->basic_qos(0,$Prefetch,false);

$channel->basic_consume($InsertQueue, $InsertExchange, false, false, false, false, "callback");


echo "Consuming on Exchange $InsertExchange with Queue $InsertQueue\n";

while(true) {
    $channel->wait();
}

$channel->close();

function callback(AMQPMessage $message){
    global $mysql;
    echo "Message received", "\n";
    $InsertRequest = new InsertRequest($message->body);

    echo "Running Insert Statement\n";
    if (!$mysql->query($InsertRequest->SQL)){
        echo "Error: ".$mysql->error;
    }

    /** @type AMQPChannel $channel */
    $channel = $message->delivery_info['channel'];
    $channel->basic_ack($message->delivery_info['delivery_tag']);
    echo "Insert Complete\n";

}

2 Answers 2

3

The issue was in the redirection of the output. I also modified the php file with a header for bash so it does not show as multiple php processes in top, but shows the file name instead:

Revised Service Script:

#! /bin/sh

### BEGIN INIT INFO
# Provides:          congen-insert
# Required-Start:    $local_fs $network
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: congen-insert
# Description:       ConGen DB Insert Daemon
### END INIT INFO

NAME="congen-insert"
DESC="DB Insert Process for ConGen"
PIDFILE="/var/run/${NAME}.pid"
LOGFILE="/var/log/${NAME}.log"

DAEMON="/var/congen/php/controllers/congen-insert"
DAEMON_OPTS="> /dev/null 2>&1"

START_OPTS="--start --background --make-pidfile --pidfile ${PIDFILE} --exec ${DAEMON} ${DAEMON_OPTS}"
STOP_OPTS="--stop --pidfile ${PIDFILE}"

test -x $DAEMON || exit 0

set -e

case "$1" in
    start)
        echo -n "Starting ${DESC}: "
        start-stop-daemon $START_OPTS >> $LOGFILE
        echo "$NAME."
        ;;
    stop)
        echo -n "Stopping $DESC: "
        start-stop-daemon $STOP_OPTS
        echo "$NAME."
        rm -f $PIDFILE
        ;;
    restart|force-reload)
        echo -n "Restarting $DESC: "
        start-stop-daemon $STOP_OPTS
        sleep 1
        start-stop-daemon $START_OPTS >> $LOGFILE
        echo "$NAME."
        ;;
    status)
    echo -n "Sorry, this isn't implemented yet"
    ;;
    *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|restart|force-reload}" >&2
        exit 1
        ;;
esac

exit 0

Revised PHP Script to run:

#!/php52/php-5.6.6/bin/php
<?php
    const LoaderPath = __DIR__ . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "includes.php";

    require_once  LoaderPath;

    use PhpAmqpLib\Channel\AMQPChannel;
    use PhpAmqpLib\Message\AMQPMessage;
    use requests\InsertRequest;

    $connection = GetRabbitConnection();

    $channel = $connection->channel();

    $RedisClient = GetRedisClient();

    DeclareQueues($connection, $RedisClient);

    $InsertExchange = $RedisClient->get(Insert.":".Exchange);
    $InsertQueue = $RedisClient->get(Insert.":".Queue);
    $Prefetch = $RedisClient->get(Insert.":".Prefetch);

    $RedisClient->disconnect();
    $RedisClient = null;

    $mysql= ConnectionBuilder::GetMySQLi();

    $channel->basic_qos(0,$Prefetch,false);

    $channel->basic_consume($InsertQueue, $InsertExchange, false, false, false, false, "callback");


    echo "Consuming on Exchange $InsertExchange with Queue $InsertQueue\n";

    while(true) {
        $channel->wait();
    }

    $channel->close();

    function callback(AMQPMessage $message){
        global $mysql;
        echo "Message received", "\n";
        $InsertRequest = new InsertRequest($message->body);

        echo "Running Insert Statement\n";
        if (!$mysql->query($InsertRequest->SQL)){
            echo "Error: ".$mysql->error;
        }

        /** @type AMQPChannel $channel */
        $channel = $message->delivery_info['channel'];
        $channel->basic_ack($message->delivery_info['delivery_tag']);
        echo "Insert Complete\n";

    }

After adding the file to /etc/init.d/ and making both the php script and service script executable, I can start the service using service congen-insert start and use the rest of the commands just like any other init.d service.

It should be noted that I am redirecting the console to /dev/null, but you could also redirect to a file by replacing the /dev/null with a writable path.

An explanation of the 2>&1 quoted from another SO post "2 is the stream number for stderr (error messages), 1 is represents [sic] the stdout stream (the standard non-error output stream)." as such I am essentially redirecting stdout to /dev/null and redirecting stderr to stdout

Sign up to request clarification or add additional context in comments.

Comments

-1
  1. Write a script using interactive shell commands to execute your php script as shown in the php from terminal example. This only works if PHP is compiled to include the --with-readline option

  2. Setup a cron task (the linux task scheduler) to run this script as shown in the cron setup example.

3 Comments

A cron task does not work like a service, i.e. Providing a pid file, running on start, doing restarts etc. The daemon should act like any other daemon or server externally.
You can set the script to run at system startup: start on startup; task; exec /path/to/command; See more detailed at: askubuntu.com/questions/814/how-to-run-scripts-on-start-up
I have edited the question to clarify. I am not looking for workarounds, but rather understanding. Thank you for your alternative method though

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.