개발 꿀팁/PHP

php 구현 데몬

Jammie 2022. 9. 26. 13:54
반응형

데이몬(daemon)은 생존기간이 긴 일종의 프로세스다.

아래 데몬 코드는 workerman 소스코드를 참고하였습니다.행 작성:

<?php
class Daemon
{
    public static $stdoutFile = '/dev/null';
    public static $daemonName = 'daemonPHP';
    public static function runAll()
    {
        self::checkEnvCli(); //환경을 검사하다
        self::daemonize(); //데몬화
        self::chdir(); //작업 목록 바꾸기
        self::closeSTD(); //표준 출력 끄기, 표준 오류
        self::setProcessTitle(self::$daemonPHP); //데몬 이름 설정
    }
 
    protected static function checkEnvCli()
    {
        if (DIRECTORY_SEPARATOR === '\\') {
            exit("must be Linux\n");
        }
 
        if (php_sapi_name() != "cli") {
            exit("only run in command line mode \n");
        }
    }
 
    protected static function daemonize()
    {
        umask(0);
        $pid = pcntl_fork();
        if (-1 === $pid) {
            throw new Exception('fork fail');
        } elseif ($pid > 0) {
            exit(0);
        }
        if (-1 === posix_setsid()) {
            throw new Exception("setsid fail");
        }
        // Fork again avoid SVR4 system regain the control of terminal.
        $pid = pcntl_fork();
        if (-1 === $pid) {
            throw new Exception("fork fail");
        } elseif (0 !== $pid) {
            exit(0);
        }
    }
 
    protected static function chdir()
    {
        if (chdir('/')) {
            throw new Exception("change dir fail", 1);
        }
    }
 
    protected static function closeSTD()
    {
        //전역 변수 두 개 정의
        global $STDOUT, $STDERR;
        $handle = fopen(static::$stdoutFile, "a");
        if ($handle) {
            unset($handle);
            set_error_handler(function () {});
            fclose($STDOUT);
            fclose($STDERR);
            fclose(STDOUT);
            fclose(STDERR);
            $STDOUT = fopen(static::$stdoutFile, "a");
            $STDERR = fopen(static::$stdoutFile, "a");
 
            restore_error_handler();
        } else {
            throw new Exception('can not open stdoutFile ' . static::$stdoutFile);
        }
    }
 
    /**
     * Set process name.
     *
     * @param string $title
     * @return void
     */
    protected static function setProcessTitle($title)
    {
        set_error_handler(function () {});
        // >=php 5.5
        if (function_exists('cli_set_process_title')) {
            cli_set_process_title($title);
        } // Need proctitle when php<=5.5 .
        elseif (extension_loaded('proctitle') && function_exists('setproctitle')) {
            setproctitle($title);
        }
        restore_error_handler();
    }
 
}
 
Daemon::runAll();
 
//업무코드
while (1) {
    file_put_contents('./1.txt', time() . "\n", FILE_APPEND);
    sleep(1);
}

 

반응형