개발 꿀팁/PHP

php는 데몬을 구현하는 두 가지 방식이다

Jammie 2022. 7. 13. 17:14
반응형

첫 번째 방법은 nohup과 & 을 이용하여 사용합니다.

시작 프로세스를 백그라운드로 이동하기 위해 명령 뒤에 & 기호를 붙입니다콘솔을 사용하지 않고 실행하며, 다른 명령을 실행할 수 있습니다. 여기서 while 데드 루프를 사용하여 프레젠테이션을 합니다. 코드는 다음과 같습니다

<?php
 
while(true){
        echo time().PHP_EOL;
        sleep(3);
}

프로세스를 시작하기( N)

[root@localhost php]# php deadloop.php &
[1] 3454
[root@localhost php]# ps aux | grep 3454
root      3454  0.0  0.8 284544  8452 pts/0    T    18:06   0:00 php deadloop.php
root      3456  0.0  0.0 103316   896 pts/0    S+   18:08   0:00 grep 3454

[1]+  Stopped                 php deadloop.php
[root@localhost php]#

이 프로세스가 콘솔을 사용하지 않고 다른 명령을 실행할 수 있는 것을 볼 수 있습니다. 이 경우 fg 명령을 사용하여 일반 콘솔 모드로 되돌릴 수 있습니다

[root@localhost php]# fg
php deadloop.php
1470996682
1470996685
1470996688
1470996691

이상 & 명령어에 대한 간단한 소개였습니다.
이제 또 다른 명령어 nohup

명령 앞에 nohup, 시작활성 프로세스가 리눅스의 보류 메시지를 무시합니다기호(SIGHUP), 어떤 경우에 Linux에서 SIGHUP 신호를 발생시키는지, 아래 내용은 바이두 백과에서 발췌한 것입니다.

SIGHUP은 다음과 같은 3가지 상황에서해당하는 프로세스로 보내기:
1.단말기가 꺼졌을 때 그 신호가 s로 전송됨ession 첫 번째 프로세스와 job으로 제시제출하는 프로세스 (예: 심볼로 제출하는 프로세스)
2. session 첫 번째 프로세스가 종료될 때,이 신호는 이 세션으로 보내집니다.프런트 데스크 프로세스 그룹의 모든 프로세스
3. 부모 프로세스가 종료되어 프로세스가 고립된 경우프로세스가 중지된 하위 프로세스 그룹정지 상태(SIGSTOP 또는 SIGTSTP 신호를 수신함) 이 신호는 프로세스 그룹의 모든 프로세스로 전송됩니다.

1과 2를 합치면 우리는 안다, 그렇지 않아도 알 수 있다.& (job) 방식으로 시작하는 프로세스입니다.터미널을 닫을 때 SIGHUP 신호가 수신됩니다. 그러면 프로세스에서 SIGHUP 신호가 수신되면 어떻게 됩니까? 역시 바이두 백과에서 발췌한 것입니다.
SIGHUP 신호에 대한 시스템 기본 처리이 신호를 받는 과정을 종료하는 것이다.따라서 프로그램이 이 신호를 포착하지 못하면 수신되면 프로세스가 종료된다.
즉, 터미널 프로세스를 종료하면 SIG가 수신됩니다.HUP 신호, 이 신호의 기본 처리 방식프로세스가 종료되면, 물론 이 신호를 캡처하여 처리하거나 무시할 수 있습니다. 예를 들어 다음 코드입니다.

<?php
pcntl_signal(SIGHUP, function(){
        //  여기서 신호를 처리하는 방식은 우리는 단지 일지를 파일에 쓰는 것뿐이다
        file_put_contents('logs.txt', 'pid : ' . posix_getpid() . ' receive SIGHUP 신호' . PHP_EOL);
});
        
while(1) {
        sleep(10);
        pcntl_signal_dispatch();
}

이 루틴을 명령줄에서 실행한 다음 셸 터미널 창을 닫은 다음 터미널을 다시 열어서 프로세스가 실행 중인지 확인합니다

[root@localhost php]# ps -ef | grep deadloop.php 
root     16112     1  0 17:20 ?        00:00:00 php deadloop.php
root     16138 16115  0 17:24 pts/4    00:00:00 grep deadloop.php
[root@localhost php]# cat logs.txt 
pid : 16112 receive SIGHUP신호

deadloop.php가 실행 중이고 부모 프로세스가 init 프로세스가 되고 (원래 부모 프로세스가 종료되어 init 프로세스에 의해 입양됨) 파일 내용에서 터미널 프로세스를 종료하는 것이 SIGHUP 신호를 받는 것을 볼 수 있습니다.사실 우리는 리눅스에서 제공하는 nohup 명령만 사용할 필요는 없지만, nohup을 사용하여 프로세스를 시작할 때 프로세스는 수신된 SIGHUP 신호를 무시하고 실행하지 않습니다. 먼저 이전 신호 처리 코드를 제거합니다.그리고 nohup 실행.

[root@localhost php]# nohup php deadloop.php 
nohup: 입력 무시 및 출력 추가"nohup.out"

또한 nohup은 기본적으로 프로그램의 출력을 현재 디렉터리에 있는 nohup.out 파일로 리디렉션하며, 쓰기 권한이 없으면 $homepath/nohup.out에 기록합니다

[root@localhost php]# ls
cmd.sh  deadloop.php  getPhoto.php  nohup.out  pics
[root@localhost php]# tail -f nohup.out 
1470999772
1470999775
1470999778
1470999781
1470999784
1470999787
1470999790
1470999793
1470999796
1470999799
1470999802

이때 단말기를 닫으면 프로세스가 종료되지 않고 고아 프로세스(ppid=1)가 되며, 이를 만든 부모 프로세스가 종료되기 때문이다

[root@localhost ~]# ps -ef | grep 3554
root      3554  3497  0 19:09 pts/0    00:00:00 php deadloop.php
root      3575  3557  0 19:10 pts/1    00:00:00 grep 3554
[root@localhost ~]# ps -ef | grep 3554
root      3554     1  0 19:09 ?        00:00:00 php deadloop.php
root      3577  3557  0 19:10 pts/1    00:00:00 grep 3554
[root@localhost ~]#

결론: 그래서 우리가 nohup과 & 을 조합할 때 부팅되는 프로세스가 콘솔을 차지하거나 의존하지 않고 콘솔이 닫히면 프로세스가 1번 프로세스에 의해 입양되어 고아 프로세스가 되는 것이 데몬의 메커니즘과 매우 유사합니다

[root@localhost php]# nohup php deadloop.php >logs.txt 2>error.txt &
[1] 3612
[root@localhost php]# ps -ef |grep 3612
root      3612  3557  0 19:18 pts/1    00:00:00 php deadloop.php
root      3617  3557  0 19:19 pts/1    00:00:00 grep 3612
[root@localhost php]#

이 중 >logs.txt 표준 출력 재연결, 2 >error.txt 표준 출력 재연결 오류.
첫 번째 실현방식에 대한 소개입니다.

두 번째 구현방식은 데몬의 규칙과 특징에 따라 코드로 구현되며 데몬의 가장 큰 특징은 탈사용입니다.사용자 단말기와 세션, 다음은 구현 코드, 키지방에서 주석을 달았다

<?php
 
$pid = pcntl_fork();
 
if ($pid == -1)
{
    throw new Exception('fork 하위 프로세스 실패');
}
elseif ($pid > 0)
{
    //상위 프로세스가 종료되었습니다. 하위 프로세스가 프로세스 팀장이 아니므로 새 세션을 쉽게 만들 수 있습니다
    exit(0);
}
 
//가장 중요한 단계, 새 세션을 만들고 원래 제어 터미널에서 벗어나십시오
posix_setsid();
 
// 현재 프로세스의 작업 디렉터리를 수정합니다. 하위 프로세스가 상위 프로세스의 작업 디렉터리를 상속하기 때문에 상위 프로세스의 작업 디렉터리에 대한 사용 권한을 해제하도록 작업 디렉터리를 수정합니다
chdir('/');
 
/*
 * 이전 단계를 통해 세션 팀장, 프로세스 팀장을 새로 만들고 터미널에서 벗어났지만 세션 팀장은 터미널을 다시 열지 못하도록 요청할 수 있습니다
 * 이 경우 하위 프로세스를 다시 만들고 현재 프로세스를 종료합니다. 그러면 실행 중인 프로세스가 세션 팀장이 되지 않습니다。
 */
$pid = pcntl_fork();
if ($pid == -1)
{
    throw new Exception('fork 하위 프로세스 실패');
}
elseif ($pid > 0)
{
    //상위 프로세스를 다시 종료합니다. 하위 프로세스가 최종 데몬이 됩니다
    exit(0);
}
 
// 데몬이 표준 I/O를 사용할 수 없기 때문에 표준 I/O, 출력 설명자 오류
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
 
/*
 * 업무 코드 처리
 */
 
while(TRUE)
{
    file_put_contents('log.txt', time().PHP_EOL, FILE_APPEND);
    sleep(5);
}

That's all!

반응형