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

问题描述:

我是守护进程和shell脚本的新手。 我遵循tutorial来运行PHP文件作为服务。如何在PHP和Shell中返回后运行主进程

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

这里是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 

?> 

UPDATE

的代码,我改变了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 
?> 
+0

这不应该被需要,因为我做了一个'chmod a + x Daemon.php',这使得它不需要'php Daemon.php'就可执行。但是,还是让我试试看。 –

+0

在你的主进程'echo $ pid;'...这应该给你答案,为什么它在那里结束。 –

尝试增加正在运行的用户到你的守护进程,使之与相应的权限,而不是root运行。

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

停止命令看起来与我的相同。

如:

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

+0

请检查更新 –

+0

@ParthapratimNeog添加更新和建议 – fyrye

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

+0

请检查更新 –

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

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

  • 母体,其中$pid是子进程的ID,执行块

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

    returnDaemon.php程序终止之后(其导致你的外壳脚本的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