【问题标题】:Running a PHP Script as a Daemon in Debian在 Debian 中将 PHP 脚本作为守护进程运行
【发布时间】:2015-06-29 05:14:24
【问题描述】:

我正在尝试将 php 脚本作为 Debian 中的守护进程启动。我也希望它也能在启动时启动。

我已经开始使用/path/to/php /path/to/script/Insert.php & 没有问题,也可以使用shell_exec("nohup /path/to/php /path/to/script/Insert.php >/dev/null &")。我曾尝试使用以下脚本,但它不会使脚本进入运行状态。

我将文件复制到/etc/init.d/ 并使用update-rc.d 没有问题。我可以使用service congen-insert start来“启动”脚本,但它似乎并没有真正运行,也没有开始做任何工作。

我遗漏了什么,或者我的脚本哪里出了问题?

我知道有几种方法可以解决这个问题,但我真的只是想了解我做错了什么或者为什么我做的事情不起作用。

非常感谢任何帮助或建议!如果您还有其他需要或我在描述中遗漏的任何内容,请告诉我,以便我更正。

提前致谢。

服务脚本

#! /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

我正在尝试运行的脚本:

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";

}

【问题讨论】:

    标签: php linux debian daemon init.d


    【解决方案1】:

    问题在于输出的重定向。我还修改了带有 bash 标头的 php 文件,因此它不会在顶部显示为多个 php 进程,而是显示文件名:

    修订后的服务脚本:

    #! /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
    

    修改后的 PHP 脚本运行:

    #!/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";
    
        }
    

    将文件添加到/etc/init.d/ 并使php 脚本和服务脚本都可执行后,我可以使用service congen-insert start 启动服务,并像使用任何其他init.d 服务一样使用其余命令。

    需要注意的是,我将控制台重定向到/dev/null,但您也可以通过将/dev/null 替换为可写路径来重定向到文件。

    从another SO post 引用的2&gt;&amp;1 的解释“2 是stderr 的流号(错误消息),1 代表[原文如此] stdout 流(标准非错误输出流)。”因此,我本质上是将stdout 重定向到/dev/null 并将stderr 重定向到stdout

    【讨论】:

      【解决方案2】:
      1. 使用交互式 shell 命令编写脚本来执行您的 php 脚本,如 php from terminal 示例所示。这仅在 PHP 编译为包含 --with-readline 选项时才有效

      2. 设置一个 cron 任务(linux 任务调度程序)来运行此脚本,如 cron setup 示例所示。

      【讨论】:

      • cron 任务不像服务那样​​工作,即提供 pid 文件、在启动时运行、重新启动等。守护进程应该像任何其他守护进程或外部服务器一样工作。
      • 可以设置脚本在系统启动时运行:start on startup;任务;执行/路径/到/命令;查看更多详细信息:askubuntu.com/questions/814/how-to-run-scripts-on-start-up
      • 我已经编辑了问题以澄清。我不是在寻找解决方法,而是在寻找理解。谢谢你的替代方法
      猜你喜欢
      • 2014-06-28
      • 2011-01-03
      • 2015-03-21
      • 2013-10-14
      • 1970-01-01
      • 1970-01-01
      • 2023-03-02
      相关资源
      最近更新 更多