我是守护进程和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
?>
答案 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;
}
}
答案 2 :(得分:0)
听起来你的bash脚本正在运行php进程,但它正在前台运行,而bash脚本正在等待它继续之前结束。由于php脚本永远运行,请尝试在命令之后添加一个&符号:daemon $bin --log=$log &
以使您的php进程在后台运行。