[php] 데몬 프로세스로 PHP 스크립트를 실행

데몬 프로세스로 PHP 스크립트를 실행해야합니다 (지시를 기다리고 작업을 수행하십시오). cron job은 지시가 도착하자마자 조치를 취해야하기 때문에 나를 위해 그것을하지 않을 것입니다. 메모리 관리 문제로 인해 PHP가 데몬 프로세스에 가장 적합한 옵션은 아니지만 여러 가지 이유로 인해이 경우 PHP를 사용해야한다는 것을 알고 있습니다. 데몬 프로세스를 관리하는 데 도움이되는 데몬 ( http://libslack.org/daemon ) 이라는 libslack 도구를 발견 했지만 지난 5 년 동안 업데이트가 없었으므로 일부를 알고 있는지 궁금합니다. 내 경우에 적합한 다른 대안. 모든 정보는 정말 감사하겠습니다.



답변

커맨드 라인 (예 : bash)에서 PHP 스크립트를 사용하여 시작할 수 있습니다

nohup php myscript.php &

&백그라운드에서 프로세스를 둔다.

편집 :
예, 몇 가지 단점이 있지만 제어 할 수 없습니까? 그건 잘못이야
간단 kill processid하게 막을 수 있습니다. 그리고 여전히 가장 우수하고 간단한 솔루션입니다.


답변

또 다른 옵션은 Upstart 를 사용하는 것 입니다. 원래 Ubuntu 용으로 개발되었으며 기본적으로 패키지로 제공되지만 모든 Linux 배포판에 적합합니다.

이 방법은 시스템 부팅시 데몬을 자동으로 시작하고 스크립트 완료시 다시 생성한다는 점에서 Supervisorddaemontools 와 유사합니다 .

설정 방법 :

에 새 스크립트 파일을 작성하십시오 /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
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

This method also is effective if you're facing a memory leak.

참고 : “myphpdaemon.service”를 변경할 때마다`systemctl daemon-reload ‘를 실행해야하지만, 그렇지 않으면 걱정할 필요가있을 때 경고가 표시됩니다.


답변

UNIX 환경에서 고급 프로그래밍 의 사본을 얻을 수있는 경우 . 13 장 전체는 데몬 프로그래밍에 관한 것입니다. 예제는 C에 있지만 필요한 모든 함수는 PHP에 래퍼 (기본적으로 pcntlposix 확장자)가 있습니다.

한 마디로-데몬 작성 (이는 * nix 기반 OS-es에서만 가능-Windows는 서비스 사용)은 다음과 같습니다.

  1. umask(0)권한 문제를 방지하기 위해 전화하십시오 .
  2. fork() 그리고 부모님 출구가 있습니다.
  3. 전화하십시오 setsid().
  4. 설정 신호 처리 SIGHUP(일반적으로 무시되거나 데몬이 구성을 다시로드하도록 신호를 보내는 데 사용됨) 및 SIGTERM프로세스가 정상적으로 종료되도록 지시합니다.
  5. fork() 다시 부모를 종료하십시오.
  6. 로 현재 작업 디렉토리를 변경하십시오 chdir().
  7. fclose() stdin, stdout그리고 stderr그들에게 쓰지 않는다. 올바른 방법은 /dev/null파일 을 하나 또는 파일 로 리디렉션하는 것이지만 PHP에서이를 수행하는 방법을 찾을 수 없습니다. 쉘을 사용하여 데몬을 리디렉션하기 위해 데몬을 시작할 때 가능합니다 (그 방법을 스스로 알아야합니다.)
  8. 일하세요!

또한 PHP를 사용하고 있으므로 순환 참조에주의하십시오. PHP 5.3 이전의 PHP 가비지 콜렉터는 이러한 참조를 수집 할 방법이없고 프로세스가 결국 충돌 할 때까지 메모리 누수가 발생합니다.


답변

많은 수의 PHP 데몬을 실행합니다.

PHP는이 작업을 수행하는 데 가장 적합한 (또는 좋은 언어) 언어는 아니지만 데몬은 웹 연결 구성 요소와 코드를 공유하므로 전반적으로 우리에게 좋은 솔루션입니다.

이를 위해 daemontools를 사용합니다. 똑똑하고 깨끗하며 신뢰할 수 있습니다. 실제로 모든 데몬을 실행하는 데 사용합니다.

http://cr.yp.to/daemontools.html 에서 확인할 수 있습니다 .

편집 : 기능의 빠른 목록.

  • 재부팅시 데몬을 자동으로 시작합니다
  • 장애 발생시 자동으로 다시 시작
  • 롤오버 및 정리를 포함하여 로깅이 처리됩니다.
  • 관리 인터페이스 : ‘svc’및 ‘svstat’
  • 유닉스 친화적 (아마도 모두에게 플러스가 아님)

답변

당신은 할 수 있습니다

  1. nohupHenrik가 제안한대로 사용하십시오 .
  2. screenPHP 프로그램을 정기적으로 사용 하고 실행하십시오. 이렇게하면을 사용하는 것보다 더 많은 제어가 가능 nohup합니다.
  3. http://supervisord.org/ 와 같은 데몬을 사용 하십시오 (Python으로 작성되었지만 명령 행 프로그램을 디먼 할 수 있으며이를 관리하기위한 원격 제어를 제공 할 수 있습니다).
  4. Emil이 제안한대로 자신의 데몬 즈 래퍼를 작성하되 과도한 IMO입니다.

가장 간단한 방법 (내 의견으로는 화면)을 추천하고 더 많은 기능을 원한다면 더 복잡한 방법으로 이동하십시오.


답변

이 문제를 해결하는 방법은 여러 가지가 있습니다.

구체적인 내용을 모르지만 PHP 프로세스를 트리거하는 다른 방법이있을 수 있습니다. 예를 들어 SQL 데이터베이스의 이벤트를 기반으로 코드를 실행해야하는 경우 스크립트를 실행하도록 트리거를 설정할 수 있습니다. 이것은 PostgreSQL에서 매우 쉽습니다 : http://www.postgresql.org/docs/current/static/external-pl.html .

솔직히 가장 좋은 방법은 nohup을 사용하여 Damon 프로세스를 만드는 것입니다. nohup을 사용하면 사용자가 로그 아웃 한 후에도 명령을 계속 실행할 수 있습니다.

nohup php myscript.php &

그러나 매우 심각한 문제가 있습니다. PHP의 메모리 관리자는 완전한 쓰레기라고 말했듯이 스크립트는 몇 초 동안 만 실행되고 존재한다는 가정하에 작성되었습니다. PHP 스크립트는 며칠 후에 기가 바이트의 메모리를 사용하기 시작합니다. 다음과 같이 PHP 스크립트를 죽이고 다시 생성하는 12 시간 또는 24 시간마다 실행되는 cron 스크립트를 작성해야합니다.

killall -3 php
nohup php myscript.php &

그러나 대본이 작업 도중에 있다면 어떨까요? kill -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 스크립트의 사본 하나만 실행되도록 할 수 있습니다.

행운을 빕니다!