在PHP和Shell中返回后,主进程如何运行

时间:2016-07-31 07:09:47

标签: php linux bash daemon

我是守护进程和shell脚本的新手。 我已经跟随tutorial运行PHP文件作为服务。

这是代码。我对chmod a+x/etc/init.d/daemon文件都进行了/home/user/Work/Daemon.php

以下是bash文件daemon的代码。我面临的问题是,当我执行sudo service daemon start时,它只打印Starting Program Name:并且不关闭它(即我必须执行ctrl + c来关闭它)。当我检查它打印的PHP文件的日志时,它确实显示在给出命令时PHP文件正在运行。

#!/bin/bash
#
#   /etc/init.d/Daemon
#
# Starts the at daemon
#
# chkconfig: 345 95 5
# description: Runs the demonstration daemon.
# processname: Daemon

# Source function library.
. /etc/init.d/functions

#startup values
log=/var/log/Daemon.log

#verify that the executable exists
test -x /home/user/Work/Daemon.php || exit 0RETVAL=0

#
#   Set prog, proc and bin variables.
#
prog="Program Name"
proc=/var/lock/subsys/Daemon
bin=/home/user/Work/Daemon.php

start() {
    # Check if Daemon is already running
    if [ ! -f $proc ]; then
        echo -n $"Starting $prog: "
        daemon $bin --log=$log
        RETVAL=$?
        [ $RETVAL -eq 0 ] && touch $proc
        echo
    fi

    return $RETVAL
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $bin
    RETVAL=$?
    [ $RETVAL -eq 0 ] && rm -f $proc
    echo
        return $RETVAL
}

restart() {
    stop
    start
}   

reload() {
    restart
}   

status_at() {
    status $bin
}

case "$1" in
start)
    start
    ;;
stop)
    stop
    ;;
reload|restart)
    restart
    ;;
condrestart)
        if [ -f $proc ]; then
            restart
        fi
        ;;
status)
    status_at
    ;;
*)

echo $"Usage: $0 {start|stop|restart|condrestart|status}"
    exit 1
esac

exit $?
exit $RETVAL

这是Daemon.php的代码

#!/usr/bin/php

<?php

while(true){
    file_put_contents('/var/log/Daemon.log', 'Running...', FILE_APPEND);
    sleep(1);
}//end while

?>

更新

我将PHP文件更改为以下代码,它盯着工作。守护进程期待回归。但我不明白为什么它会在return之后进入PHP的主进程块。有人可以解释一下吗?

新规范。

#!/usr/bin/php

<?php

$log = '/var/log/vb_q.log';

//fork the process to work in a daemonized environment
file_put_contents($log, "Status: starting up.n", FILE_APPEND);
$pid = pcntl_fork();
if($pid == -1){
    file_put_contents($log, "Error: could not daemonize process.n", FILE_APPEND);
    return 1; //error
}
else if($pid){
    return 0; //success
}
else{
   //the main process
   while(true){
       file_put_contents($log, 'Running...', FILE_APPEND);
       sleep(1);
   }//end while
}//end if 
?>

3 个答案:

答案 0 :(得分:1)

  

但我不明白为什么它会进入PHP的主进程块   在return之后。有人可以解释一下吗?

它不会转到return之后的主进程块。 $pid = pcntl_fork()创建了一个子进程;现在有两个进程执行相同的代码:

  • 父项,其中$pid是子进程的ID,执行块

    else if($pid){
        return 0; //success
    }
    

    return Daemon.php程序终止后(导致您的shell脚本start()功能恢复)

  • $pid为0的孩子执行您调用主进程

    的块
    else{
       //the main process
       while(true){
           file_put_contents($log, 'Running...', FILE_APPEND);
           sleep(1);
       }//end while
    }//end if 
    

    它不是return之后,而只是通过if ... else

答案 1 :(得分:0)

尝试将正在运行的用户添加到您的守护程序中,以便它以适当的权限而不是root运行。

此外,将touch $proc移至守护程序启动之上。确保它能够在启动守护程序之前创建锁定文件。

stop命令看起来与我的相同。

例如:

start(){
        if [ ! -f $proc ]; then
        echo -n "Starting $prog: "
        touch $proc
        daemon --user=apache --log=$log $bin
        RETVAL=$?
        [ $RETVAL -ne 0 ] && rm $proc
        echo
        else
        echo -n "$prog is already running"
        echo
    fi

    return $RETVAL  

}

此外,您可以测试您的锁定文件,以确保您能够访问它。

. /etc/init.d/functions

#startup values
log=/var/log/Daemon.log
prog="Program Name"
proc=/var/lock/subsys/Daemon
bin=/home/user/Work/Daemon.php
if [ ! -w /var/lock/subsys ]; then
    echo -n "You do not have permissions to run this service"
    echo
    exit 0
fi
if [ ! -x $bin ]; then
    echo $bin is not executable!
    echo
    exit 0
fi
RETVAL=0

更新

PHP脚本不能作为普通服务运行。 为了控制它,你必须分叉它以使服务继续运行并允许父PHP进程关闭脚本,而不是在调用它的当前线程中。请参阅:http://man7.org/linux/man-pages/man3/daemon.3.html#RETURN_VALUE

例如,启动服务 - 服务从未返回它启动或错误,因为它处于while循环中。

您还应该检查您的子进程,并确保在分叉之后将其指定为主进程(会话负责人)。否则,呼叫过程仍然是领导者。

if ($pid == -1) {
        return 1; //return error to service
} elseif ($pid) {
        //parent process - break out of it
        return 0;
} else {
    /* child Process - run by calling pcntl_fork */
    try {
        if (posix_setsid() < 0) {
            return; //error assigning a session id
        }
        $sid = posix_getpid(); //retrieve current process name

       //... Your Code Here
   } catch(\Exception $e) {
       return 1;
   }

}

请参阅:http://linux.die.net/man/2/setsid

答案 2 :(得分:0)

听起来你的bash脚本正在运行php进程,但它正在前台运行,而bash脚本正在等待它继续之前结束。由于php脚本永远运行,请尝试在命令之后添加一个&符号:daemon $bin --log=$log &以使您的php进程在后台运行。