The Correct Way to daemon php Process

  Daemon process, linux, php

[Original Address:https://blog.ti-node.com/blog …]

Daemon phonetic symbol: [‘di: Mn], which means patron saint or spirit in Chinese. in fact, it also means guardian process.

A daemon is simply a process that can run in the background without leaving the terminal. This is a very common process in Linux. After services such as apache or mysql are started, they will be stationed in memory as a daemon.

Take php as an example. If I have a time-consuming task that needs to run in the background: import all 20 million users in the user table in mysql into redis to warm up the cache, then this task is estimated to not end in a short while. At this time, I need to write a PHP script to run in the system in the form of daemon and launch it automatically after it ends.

In Linux, there are roughly three ways to implement script background:

1. Add an ampersand after the command, such as php task.php &. The disadvantage of this method is that if the terminal terminal is shut down, whether it is normally shut down or abnormally shut down, the PHP process will be shut down as the terminal is shut down. Secondly, if there is any output text such as echo or print_r in the code, it will be output to the current terminal window.

2. Use nohup commands, such as NOHUP php task.php &. By default, text output such as echo or print_r in the code will be output to the nohup.out file in the PHP code’s peer directory. If you close the terminal by using normal means such as exit command or close button, the process will not be closed. It will continue to run in the background. However, if the terminal encounters abnormal exit or termination, the php process will exit immediately. In essence, it is not a stable and reliable daemon solution.

3. Using fork and setsid, I’ll call it: *nix solution. Look at the code:

<?php
    // 一次fork  
    $pid = pcntl_fork();
    if ( $pid < 0 ) {
      exit( ' fork error. ' );
    } else if( $pid > 0 ) {
      exit( ' parent process. ' );
    }
    // 将当前子进程提升会会话组组长 这是至关重要的一步 
    if ( ! posix_setsid() ) {
      exit( ' setsid error. ' );
    }
    // 二次fork
    $pid = pcntl_fork();
    if( $pid < 0 ){
      exit( ' fork error. ' );
    } else if( $pid > 0 ) {
      exit( ' parent process. ' );
    }
    
    // 真正的逻辑代码们 下面仅仅写个循环以示例
    for( $i = 1 ; $i <= 100 ; $i++ ){
      sleep( 1 );
      file_put_contents( 'daemon.log', $i, FILE_APPEND );
    }
?>