데몬 프로세스로 PHP 스크립트를 실행
데몬 프로세스로 PHP 스크립트를 실행해야합니다 (지시를 기다리고 작업을 수행하십시오). cron job은 지시가 도착하자마자 조치를 취해야하기 때문에 나를 위해 그것을하지 않을 것입니다. 메모리 관리 문제로 인해 PHP가 데몬 프로세스에 가장 적합한 옵션은 아니지만 여러 가지 이유로 인해이 경우 PHP를 사용해야한다는 것을 알고 있습니다. 데몬 프로세스를 관리하는 데 도움이되는 데몬 ( http://libslack.org/daemon ) 이라는 libslack 도구를 발견 했지만 지난 5 년 동안 업데이트가 없었으므로 일부를 알고 있는지 궁금합니다. 내 경우에 적합한 다른 대안. 모든 정보는 정말 감사하겠습니다.
커맨드 라인 (예 : bash)에서 PHP 스크립트를 사용하여 시작할 수 있습니다
nohup php myscript.php &
는 &
백그라운드에서 프로세스를 둔다.
편집 :
예, 몇 가지 단점이 있지만 제어 할 수 없습니까? 그건 잘못이야
간단 kill processid
하게 막을 수 있습니다. 그리고 여전히 가장 우수하고 간단한 솔루션입니다.
또 다른 옵션은 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 에게 큰 감사를드립니다 .
새로 systemd 당신은 서비스를 만들 수 있습니다.
예를 들어 에 파일 또는 심볼릭 링크 를 만들어야합니다 /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 <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
}
}
}
작업 예 :
[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 루틴을 한 번에 한 번 실행해야하는 경우 (예 : 파기) 쉘 또는 bash 스크립트를 사용하여 PHP 대신 시스템 서비스 파일로 직접 호출해야합니다.
#!/usr/bin/env bash
scriptpath="/app/services/"
while [ : ]
do
# clear
php -f "$scriptpath"${1}".php" fixedparameter ${2} > /dev/null 2>/dev/null
sleep 1
done
If you chose these option you should change the KillMode to mixed
to processes, bash(main) and PHP(child) be killed.
ExecStart=/app/phpservice/runner.sh phpfile parameter > /dev/null 2>/dev/null
KillMode=process
This method also is effective if you're facing a memory leak.
Note: Every time that you change your "myphpdaemon.service" you must run `systemctl daemon-reload', but do worry if you not do, it will be alerted when is needed.
If you can - grab a copy of Advanced Programming in the UNIX Environment. The entire chapter 13 is devoted to daemon programming. Examples are in C, but all the function you need have wrappers in PHP (basically the pcntl and posix extensions).
In a few words - writing a daemon (this is posible only on *nix based OS-es - Windows uses services) is like this:
- Call
umask(0)
to prevent permission issues. fork()
and have the parent exit.- Call
setsid()
. - Setup signal processing of
SIGHUP
(usually this is ignored or used to signal the daemon to reload its configuration) andSIGTERM
(to tell the process to exit gracefully). fork()
again and have the parent exit.- Change the current working dir with
chdir()
. fclose()
stdin
,stdout
andstderr
and don't write to them. The corrrect way is to redirect those to either/dev/null
or a file, but I couldn't find a way to do it in PHP. It is possible when you launch the daemon to redirect them using the shell (you'll have to find out yourself how to do that, I don't know :).- Do your work!
Also, since you are using PHP, be careful for cyclic references, since the PHP garbage collector, prior to PHP 5.3, has no way of collecting those references and the process will memory leak, until it eventually crashes.
I run a large number of PHP daemons.
I agree with you that PHP is not the best (or even a good) language for doing this, but the daemons share code with the web-facing components so overall it is a good solution for us.
We use daemontools for this. It is smart, clean and reliable. In fact we use it for running all of our daemons.
You can check this out at http://cr.yp.to/daemontools.html.
EDIT: A quick list of features.
- Automatically starts the daemon on reboot
- Automatically restart dameon on failure
- Logging is handled for you, including rollover and pruning
- Management interface: 'svc' and 'svstat'
- UNIX friendly (not a plus for everyone perhaps)
You can
- Use
nohup
as Henrik suggested. - Use
screen
and run your PHP program as a regular process inside that. This gives you more control than usingnohup
. - Use a daemoniser like http://supervisord.org/ (it's written in Python but can daemonise any command line program and give you a remote control to manage it).
- Write your own daemonise wrapper like Emil suggested but it's overkill IMO.
I'd recommend the simplest method (screen in my opinion) and then if you want more features or functionality, move to more complex methods.
There is more than one way to solve this problem.
I do not know the specifics but perhaps there is another way to trigger the PHP process. For instance if you need the code to run based on events in a SQL database you could setup a trigger to execute your script. This is really easy to do under PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html .
Honestly I think your best bet is to create a Damon process using nohup. nohup allows the command to continue to execute even after the user has logged out:
nohup php myscript.php &
There is however a very serious problem. As you said PHP's memory manager is complete garbage, it was built with the assumption that a script is only executing for a few seconds and then exists. Your PHP script will start to use GIGABYTES of memory after only a few days. You MUST ALSO create a cron script that runs every 12 or maybe 24 hours that kills and re-spawns your php script like this:
killall -3 php
nohup php myscript.php &
But what if the script was in the middle of a job? Well kill -3 is an interrupt, its the same as doing a ctrl+c on the CLI. Your php script can catch this interrupt and exit gracefully using the PHP pcntl library: http://php.oregonstate.edu/manual/en/function.pcntl-signal.php
Here is an example:
function clean_up() {
GLOBAL $lock;
mysql_close();
fclose($lock)
exit();
}
pcntl_signal(SIGINT, 'clean_up');
The idea behind the $lock is that the PHP script can open a file with a fopen("file","w");. Only one process can have a write lock on a file, so using this you can make sure that only one copy of your PHP script is running.
Good Luck!
Kevin van Zonneveld wrote a very nice detailed article on this, in his example he makes use of the System_Daemon
PEAR package (last release date on 2009-09-02).
Check out https://github.com/shaneharter/PHP-Daemon
This is an object-oriented daemon library. It has built-in support for things like logging and error recovery, and it has support for creating background workers.
I recently had a need for a cross-platform solution (Windows, Mac, and Linux) to the problem of running PHP scripts as daemons. I solved the problem by writing my own C++ based solution and making binaries:
https://github.com/cubiclesoft/service-manager/
Full support for Linux (via sysvinit), but also Windows NT services and Mac OSX launchd.
If you just need Linux, then a couple of the other solutions presented here work well enough and, depending on the flavor. There is also Upstart and systemd these days, which have fallbacks to sysvinit scripts. But half of the point of using PHP is that it is cross-platform in nature, so code written in the language has a pretty good chance of working everywhere as-is. Deficiencies start showing up when certain external native OS-level aspects enter the picture such as system services, but you'll get that problem with most scripting languages.
Attempting to catch signals as someone here suggested in PHP userland is not a good idea. Read the documentation on pcntl_signal()
carefully and you will quickly learn that PHP handles signals using some rather unpleasant methods (specifically, 'ticks') that chew up a bunch of cycles for something rarely seen by processes (i.e. signals). Signal handling in PHP is also only barely available on POSIX platforms and support differs based on the version of PHP. It initially sounds like a decent solution but it falls pretty short of being truly useful.
PHP has also been getting better about memory leak issues as time progresses. You still have to be careful (the DOM XML parser tends to leak still) but I rarely see runaway processes these days and the PHP bug tracker is pretty quiet by comparison to the days of yore.
As others have already mentioned, running PHP as a daemon is quite easy, and can be done using a single line of command. But the actual problem is keeping it running and managing it. I've had the same problem quite some time ago and although there are plenty of solutions already available, most of them have lots of dependencies or are difficult to use and not suitable for basic usages. I wrote a shell script that can manage a any process/application including PHP cli scripts. It can be set as a cronjob to start the application and will contain the application and manage it. If it's executed again, for example via the same cronjob, it check if the app is running or not, if it does then simply exits and let its previous instance continue managing the application.
I uploaded it to github, feel free to use it : https://github.com/sinasalek/EasyDeamonizer
EasyDeamonizer
Simply watches over your application (start, restart, log, monitor, etc). a generic script to make sure that your appliation remains running properly. Intentionally it uses process name instread of pid/lock file to prevent all its side effects and keep the script as simple and as stirghforward as possible, so it always works even when EasyDaemonizer itself is restarted. Features
- Starts the application and optionally a customized delay for each start
- Makes sure that only one instance is running
- Monitors CPU usage and restarts the app automatically when it reaches the defined threshold
- Setting EasyDeamonizer to run via cron to run it again if it's halted for any reason
- Logs its activity
Extending Emil Ivaov answer, You can do the following to close STDIN, STDOUT AND STDERROR in php
if (!fclose(STDIN)) {
exit("Could not close STDIN");
}
if (!fclose(STDOUT)) {
exit("Could not close STDOUT");
}
if (!fclose(STDERR)) {
exit("Could not close STDERR");
}
$STDIN = fopen('/dev/null', 'r');
$STDOUT = fopen('/dev/null', 'w');
$STDERR = fopen('/var/log/our_error.log', 'wb');
Basically you close the standard streams so that PHP has no place to write. The following fopen
calls will set the standard IO to /dev/null
.
I have read this from book of Rob Aley - PHP beyond the web
I wrote and deployed a simple php-daemon, code is online here
https://github.com/jmullee/PhpUnixDaemon
Features: privilege dropping, signal handling, logging
I used it in a queue-handler (use case: trigger a lengthy operation from a web page, without making the page-generating php wait, i.e. launch an asynchronous operation) https://github.com/jmullee/PhpIPCMessageQueue
you can check pm2 here is, http://pm2.keymetrics.io/
create a ssh file, such as worker.sh put into your php script that you will deal with.
worker.sh
php /path/myscript.php
daemon start
pm2 start worker.sh
Cheers, that is it.
참고URL : https://stackoverflow.com/questions/2036654/run-php-script-as-daemon-process
'IT' 카테고리의 다른 글
일회성 구독 만들기 (0) | 2020.06.15 |
---|---|
존재하지 않고 새 줄을 추가하는 경우 .txt 파일을 만듭니다. (0) | 2020.06.15 |
MySQL 8.0-클라이언트는 서버가 요청한 인증 프로토콜을 지원하지 않습니다. (0) | 2020.06.14 |
Android Studio에서 벡터 자산의 채우기 색상 변경 (0) | 2020.06.14 |
모두 거부, htaccess를 통해 하나의 IP 만 허용 (0) | 2020.06.14 |