当前位置:  开发笔记 > 编程语言 > 正文

运行php脚本作为守护进程

如何解决《运行php脚本作为守护进程》经验,为你挑选了9个好方法。

我需要运行一个PHP脚本作为守护进程(等待指令并做一些事情).cron job不会为我做,因为一旦指令到达就需要采取行动.我知道由于内存管理问题,PHP实际上不是守护进程的最佳选择,但由于各种原因,我必须在这种情况下使用PHP.我遇到了libslack的一个名为Daemon(http://libslack.org/daemon)的工具,它似乎可以帮助我管理守护进程,但是在过去的5年中没有任何更新,所以我想知道你是否知道一些其他替代方案适合我的情况.任何信息都将非常感激.



1> Henrik P. He..:

您可以使用命令行(即bash)启动PHP脚本

nohup php myscript.php &

&把你的程序在后台运行.

编辑:
是的,有一些缺点,但无法控制?那是错的.
简单kill processid就会阻止它.它仍然是最好,最简单的解决方案.


如果守护程序失败,则不会重新启动守护程序,并且根本没有简单的方法来管理守护程序.
我同意这里所说的 - 这是一个糟糕的解决方案.您应该创建一个init脚本有以下几个原因:1)Init脚本在启动时自动启动2)您可以使用start/stop/restart命令管理守护程序.以下是来自servefault的示例:http://serverfault.com/questions/229759/launching-a-php-daemon-from-an-lsb-init-script-w-start-stop-daemon

2> Jonathan..:

另一种选择是使用Upstart.它最初是为Ubuntu开发的(默认情况下随附它),但它适用于所有Linux发行版.

这种方法类似于Supervisord和daemontools,因为它在系统启动时自动启动守护进程,并在脚本完成时重新生成.

如何设置:

/etc/init/myphpworker.conf.创建一个新的脚本文件.这是一个例子:

# Info
description "My PHP Worker"
author      "Jonathan"

# Events
start on startup
stop on shutdown

# Automatically respawn
respawn
respawn limit 20 5

# Run the script!
# Note, in this example, if your PHP script returns
# the string "ERROR", the daemon will stop itself.
script
    [ $(exec /usr/bin/php -f /path/to/your/script.php) = 'ERROR' ] && ( stop; exit 1; )
end script

启动和停止守护程序:

sudo service myphpworker start
sudo service myphpworker stop

检查您的守护程序是否正在运行:

sudo service myphpworker status

谢谢

非常感谢Kevin van Zonneveld,我在那里学习了这项技术.


@Pradeepta那是因为帖子中有错误 - 我不确定是什么(并且没有测试过),但我认为`sudo service myphpworker start/stop/status`仅适用于`/etc/init.d`不是upstart服务.@ matt-sich似乎已经发现了正确的语法.另一个选择是使用Gearman或Resque,它允许后台处理和deamonization.
Ubuntu本身正在转向使用systemd而不是upstart:http://www.zdnet.com/article/after-linux-civil-war-ubuntu-to-adopt-systemd/
爱这个.只是想知道,是否有可能有多个并发工人?我只是有一个工人不够了的问题.
Sudo"服务myphpworker开始"对我不起作用.我使用"sudo start myphpworker",它完美无缺

3> LeonanCarval..:

使用新的 systemd,您可以创建服务(在基于rhel的linux上).

您必须在 ,例如,创建文件或符号链接/etc/systemd/system/.myphpdaemon.service并放置一个像这样的内容,myphpdaemon将是服务的名称:

[Unit]
Description=My PHP Daemon Service
#May your script needs MySQL or other services to run, eg. MySQL Memcached
Requires=mysqld.service memcached.service 
After=mysqld.service memcached.service

[Service]
User=root
Type=simple
TimeoutSec=0
PIDFile=/var/run/myphpdaemon.pid
ExecStart=/usr/bin/php -f /srv/www/myphpdaemon.php arg1 arg2> /dev/null 2>/dev/null
#ExecStop=/bin/kill -HUP $MAINPID #It's the default you can change whats happens on stop command
#ExecReload=/bin/kill -HUP $MAINPID
KillMode=process

Restart=on-failure
RestartSec=42s

StandardOutput=null #If you don't want to make toms of logs you can set it null if you sent a file or some other options it will send all php output to this one.
StandardError=/var/log/myphpdaemon.log
[Install]
WantedBy=default.target

您将能够使用该命令启动,获取状态,重新启动和停止服务

systemctl myphpdaemon

PHP脚本应该有一种"循环"来继续运行.



工作范例:

[Unit]
Description=PHP APP Sync Service
Requires=mysqld.service memcached.service
After=mysqld.service memcached.service

[Service]
User=root
Type=simple
TimeoutSec=0
PIDFile=/var/run/php_app_sync.pid
ExecStart=/bin/sh -c '/usr/bin/php -f /var/www/app/private/server/cron/app_sync.php  2>&1 > /var/log/app_sync.log'
KillMode=mixed

Restart=on-failure
RestartSec=42s

[Install]
WantedBy=default.target

如果你的PHP应该在一个循环中执行一次(比如diggest),你可以使用shell或bash脚本直接调用systemd服务文件而不是PHP,例如:

#!/usr/bin/env bash
script_path="/app/services/"

while [ : ]
do
#    clear
    php -f "$script_path"${1}".php" fixedparameter ${2}  > /dev/null 2>/dev/null
    sleep 1
done

如果你选择了这些选项,你应该改变KillMode到mixed以流程时,bash(主)和PHP(儿童)被杀害.

ExecStart=/app/phpservice/runner.sh phpfile parameter  > /dev/null 2>/dev/null
KillMode=process

注意:每次更改"myphpdaemon.service"时,都必须运行`systemctl daemon-reload',但如果不这样做,请务必担心,需要时会提示.


低估的答案.你有我的+1.
真棒.希望我们能够回答这个问题,因为这不应该埋在这个页面上.

4> Emil Ivanov..:

如果可以 - 在UNIX环境中获取高级编程的副本.整个第13章专门用于守护程序编程.示例在C中,但您需要的所有函数都包含PHP中的包装器(基本上是pcntl和posix扩展).

简而言之 - 编写一个守护进程(这只能在基于*nix的OS-es上运行--Windows使用服务)是这样的:

    致电umask(0)以防止许可问题.

    fork() 并让父退出.

    打电话setsid().

    设置信号处理SIGHUP(通常忽略或用于通知守护进程重新加载其配置)和SIGTERM(告诉进程正常退出).

    fork() 再次并让父退出.

    使用更改当前工作目录chdir().

    fclose() stdin,stdout并且stderr不要写信给他们.正确的方法是将它们重定向到一个/dev/null或一个文件,但我找不到在PHP中这样做的方法.当你启动守护进程使用shell重定向它们时,你可能会发现它(你必须自己找出如何做到这一点,我不知道:).

    做你的工作!

此外,由于您使用的是PHP,因此要小心循环引用,因为在PHP 5.3之前的PHP垃圾收集器无法收集这些引用,并且进程将内存泄漏,直到它最终崩溃.



5> Phil Wallach..:

我运行了大量的PHP守护进程.

我同意你的观点,PHP并不是最好的(甚至是好的)语言,但守护进程与面向Web的组件共享代码,所以总体来说它对我们来说是一个很好的解决方案.

我们为此使用daemontools.它聪明,干净,可靠.实际上我们用它来运行我们所有的守护进程.

您可以在http://cr.yp.to/daemontools.html上查看.

编辑:快速功能列表.

重启时自动启动守护程序

失败时自动重启dameon

记录是为您处理的,包括翻转和修剪

管理界面:'svc'和'svstat'

UNIX友好(也许不是每个人的加分)



6> Noufal Ibrah..:

您可以

    nohup像Henrik建议的那样使用.

    使用screen并运行PHP程序作为其中的常规过程.这比使用更能控制nohup.

    使用像http://supervisord.org/这样的守护进程(它是用Python编写的,但可以对任何命令行程序进行守护,并为您提供远程控制来管理它).

    编写自己的守护程序包装,像埃米尔建议,但它是矫枉过正的IMO.

我推荐最简单的方法(在我看来是屏幕)然后如果你想要更多的功能或功能,请转向更复杂的方法.



7> rook..:

解决这个问题的方法不止一种.

我不知道具体细节,但也许还有另一种触发PHP过程的方法.例如,如果您需要基于SQL数据库中的事件运行代码,则可以设置触发器来执行脚本.在PostgreSQL下这很容易做到:http://www.postgresql.org/docs/current/static/external-pl.html.

老实说,我认为最好的办法是使用nohup创建一个Damon进程.nohup允许命令在用户注销后继续执行:

nohup php myscript.php &

然而,有一个非常严重的问题.正如你所说,PHP的内存管理器是完全垃圾,它是在假设脚本只执行几秒然后存在的情况下构建的.您的PHP脚本将在几天后开始使用GIGABYTES内存.您还必须创建一个每12或24小时运行一次的cron脚本,这样可以杀死并重新生成您的php脚本,如下所示:

killall -3 php
nohup php myscript.php &

但是,如果脚本正在工作中呢?杀-3是一个中断,它与在CLI上执行ctrl + c相同.您的PHP脚本可以捕获此中断并使用PHP pcntl库正常退出:http://php.oregonstate.edu/manual/en/function.pcntl-signal.php

这是一个例子:

function clean_up() {
  GLOBAL $lock;
  mysql_close();
  fclose($lock)
  exit();
}
pcntl_signal(SIGINT, 'clean_up');

$ lock背后的想法是PHP脚本可以用fopen("file","w");打开一个文件.只有一个进程可以对文件进行写锁定,因此使用此方法可以确保只运行PHP脚本的一个副本.

祝好运!



8> Alix Axel..:

Kevin van Zonneveld 写了一篇非常详细的文章,在他的例子中他使用了System_DaemonPEAR包(最后发布日期为2009-09-02).



9> Shane H..:

查看https://github.com/shaneharter/PHP-Daemon

这是一个面向对象的守护程序库.它内置了对日志记录和错误恢复等内容的支持,并且支持创建后台工作程序.

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有