Bei*_*ier 149 php unix linux daemon
我需要运行一个PHP脚本作为守护进程(等待指令并做一些事情).cron job不会为我做,因为一旦指令到达就需要采取行动.我知道由于内存管理问题,PHP实际上不是守护进程的最佳选择,但由于各种原因,我必须在这种情况下使用PHP.我遇到了libslack的一个名为Daemon(http://libslack.org/daemon)的工具,它似乎可以帮助我管理守护进程,但是在过去的5年中没有任何更新,所以我想知道你是否知道一些其他替代方案适合我的情况.任何信息都将非常感激.
Hen*_*sel 162
您可以使用命令行(即bash)启动PHP脚本
nohup php myscript.php &
在&把你的程序在后台运行.
编辑:
是的,有一些缺点,但无法控制?那是错的.
简单kill processid就会阻止它.它仍然是最好,最简单的解决方案.
Jon*_*han 162
另一种选择是使用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
Run Code Online (Sandbox Code Playgroud)
sudo service myphpworker start
sudo service myphpworker stop
Run Code Online (Sandbox Code Playgroud)
sudo service myphpworker status
Run Code Online (Sandbox Code Playgroud)
非常感谢Kevin van Zonneveld,我在那里学习了这项技术.
Leo*_*lho 58
使用新的 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
Run Code Online (Sandbox Code Playgroud)
您将能够使用该命令启动,获取状态,重新启动和停止服务
systemctl <start|status|restart|stop|enable> myphpdaemon
PHP脚本应该有一种"循环"来继续运行.
<?php
gc_enable();//
while (!connection_aborted() || PHP_SAPI == "cli") {
//Code Logic
//sleep and usleep could be useful
if (PHP_SAPI == "cli") {
if (rand(5, 100) % 5 == 0) {
gc_collect_cycles(); //Forces collection of any existing garbage cycles
}
}
}
Run Code Online (Sandbox Code Playgroud)
工作范例:
[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
Run Code Online (Sandbox Code Playgroud)
如果你的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
Run Code Online (Sandbox Code Playgroud)
如果你选择了这些选项,你应该改变KillMode到mixed以流程时,bash(主)和PHP(儿童)被杀害.
ExecStart=/app/phpservice/runner.sh phpfile parameter > /dev/null 2>/dev/null
KillMode=process
Run Code Online (Sandbox Code Playgroud)
注意:每次更改"myphpdaemon.service"时,都必须运行`systemctl daemon-reload',但如果不这样做,请务必担心,需要时会提示.
Emi*_*nov 47
如果可以 - 在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垃圾收集器无法收集这些引用,并且进程将内存泄漏,直到它最终崩溃.
Phi*_*ach 24
我运行了大量的PHP守护进程.
我同意你的观点,PHP并不是最好的(甚至是好的)语言,但守护进程与面向Web的组件共享代码,所以总体来说它对我们来说是一个很好的解决方案.
我们为此使用daemontools.它聪明,干净,可靠.实际上我们用它来运行我们所有的守护进程.
您可以在http://cr.yp.to/daemontools.html上查看.
编辑:快速功能列表.
Nou*_*him 14
您可以
nohup像Henrik建议的那样使用.screen并运行PHP程序作为其中的常规过程.这比使用更能控制nohup.我推荐最简单的方法(在我看来是屏幕)然后如果你想要更多的功能或功能,请转向更复杂的方法.
roo*_*ook 11
解决这个问题的方法不止一种.
我不知道具体细节,但也许还有另一种触发PHP过程的方法.例如,如果您需要基于SQL数据库中的事件运行代码,则可以设置触发器来执行脚本.在PostgreSQL下这很容易做到:http://www.postgresql.org/docs/current/static/external-pl.html.
老实说,我认为最好的办法是使用nohup创建一个Damon进程.nohup允许命令在用户注销后继续执行:
nohup php myscript.php &
Run Code Online (Sandbox Code Playgroud)
然而,有一个非常严重的问题.正如你所说,PHP的内存管理器是完全垃圾,它是在假设脚本只执行几秒然后存在的情况下构建的.您的PHP脚本将在几天后开始使用GIGABYTES内存.您还必须创建一个每12或24小时运行一次的cron脚本,这样可以杀死并重新生成您的php脚本,如下所示:
killall -3 php
nohup php myscript.php &
Run Code Online (Sandbox Code Playgroud)
但是,如果脚本正在工作中呢?杀-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');
Run Code Online (Sandbox Code Playgroud)
$ lock背后的想法是PHP脚本可以用fopen("file","w");打开一个文件.只有一个进程可以对文件进行写锁定,因此使用此方法可以确保只运行PHP脚本的一个副本.
祝好运!
| 归档时间: |
|
| 查看次数: |
137643 次 |
| 最近记录: |