За последние 24 часа нас посетили 22833 программиста и 1262 робота. Сейчас ищут 827 программистов ...

Daemon

Тема в разделе "PHP для профи", создана пользователем host, 31 май 2016.

Метки:
  1. host

    host Активный пользователь

    С нами с:
    20 июн 2007
    Сообщения:
    733
    Симпатии:
    3
    Добрый день.
    Есть демон. В одной строке должен выполниться exec, и на этом моменте демон убивается сигналом 17.
    php.net пишет:
    В самом демоне поток перенаправлен в файл. Но видимо нужно перенаправить от exec. Пробовал разные варианты:
    PHP:
    1. exec('/etc/init.d/crond restart > /dev/null 2>/dev/null &');
    и так:
    PHP:
    1. exec('/etc/init.d/crond restart');
    Все равно демон убивается.
    Помогите пожалуйста решить вопрос.

    Код демона:
    PHP:
    1. <?php
    2. // Без этой директивы PHP не будет перехватывать сигналы
    3. //sleep(3);
    4. declare(ticks=1);
    5.  
    6. ini_set('error_log', '/var/www/html/error.log');
    7.  
    8. class DaemonClass {
    9.     public $maxProcesses = 1; // Максимальное количество дочерних процессов  
    10.     protected $stop_server = FALSE; // Когда установится в TRUE, демон завершит работу
    11.     public $currentJobs = array(); // Здесь будем хранить запущенные дочерние процессы
    12.     public $start_h = 0; // Время с которого можно начинать рассылку
    13.     public $end_h = 0; // Время, когда нужно завершить отправку рассылки
    14.  
    15.     public function __construct() {
    16.         error_log('Демон создан');
    17.         // Ждем сигналы SIGTERM и SIGCHLD
    18.         $sig1 = pcntl_signal(SIGTERM, array($this, "childSignalHandler"), true);
    19.         $sig2 = pcntl_signal(SIGCHLD, array($this, "childSignalHandler"), true);
    20.     }
    21.  
    22.     public function connect(){
    23.         if(!defined('MySQL_HOST')) define( 'MySQL_HOST', 'localhost' );
    24.         if(!defined('MySQL_LOGIN')) define( 'MySQL_LOGIN', 'xxx' );
    25.         if(!defined('MySQL_PASSWORD')) define( 'MySQL_PASSWORD', 'xxx' );
    26.         if(!defined('MySQL_DATABASE')) define( 'MySQL_DATABASE', 'xxx' );
    27.  
    28.         $this->conn = mysql_connect(MySQL_HOST, MySQL_LOGIN, MySQL_PASSWORD);
    29.         mysql_select_db(MySQL_DATABASE);
    30.         mysql_query("SET NAMES utf8");
    31.     }
    32.  
    33.     public function query($sql=''){
    34.         $return = false;
    35.         if(!empty($sql)){
    36.             if (!mysql_ping($this->conn)){
    37.                 mysql_close($this->conn);
    38.                 $this->connect();
    39.             }          
    40.             $return = mysql_query($sql);
    41.         }
    42.         return $return;
    43.     }
    44.  
    45.     protected function allTasks(){
    46.         // Тут код какой-то
    47.      
    48.         ob_start();
    49.         exec('/etc/init.d/crond restart > /dev/null 2>/dev/null &');
    50.         ob_end_clean();
    51.     }
    52.  
    53.     public function launchJob() {
    54.             error_log("Процесс с ID ".getmypid());
    55.             file_put_contents('/var/www/html/pid.pid', getmypid());
    56.             chmod('/var/www/html/pid.pid', 0777);
    57.             $timer_run_1min = 0;
    58.              
    59.             while(!$this->stop_server) {
    60.                 //error_log(date('d.m.Y H:i:s')); // Проверка, не спит ли сокет...
    61.                 // Если уже запущено максимальное количество дочерних процессов, ждем их завершения
    62.                 while(count($this->currentJobs) >= $this->maxProcesses) {
    63.                      error_log('Уже дочерних процессов больше допустимого. Отдыхаем секундочку.');
    64.                      sleep(1);
    65.                 }              
    66.                            
    67.                 $curr = time();
    68.                 // Время в сек.
    69.                 $t_1min = 60;
    70.              
    71.                 if((int)$timer_run_1min == 0){ $timer_run_1min = $curr; }
    72.              
    73.                 // Таймер на 1 минуту.          
    74.                 if($curr-$timer_run_1min >= $t_1min){
    75.                     error_log('run ALL TASKS');
    76.                     $this->allTasks();                          
    77.                     $timer_run_1min = $curr;
    78.                 }              
    79.                 sleep(1);
    80.             }                  
    81.                                
    82.             exit();
    83.        // }
    84.         return TRUE;
    85.     }
    86.  
    87.     public function childSignalHandler($signo, $pid = null, $status = null) {
    88.         error_log('Был вызван '.$signo);
    89.         switch($signo) {
    90.             case SIGTERM: // При получении сигнала завершения работы устанавливаем флаг
    91.                 $this->stop_server = true;
    92.                 unlink('/var/www/html/pid.pid');
    93.                 error_log('Стоп циклу. Удаляем PID-файл.');
    94.                 exit;
    95.                 break;
    96.              
    97.             case SIGCHLD: // При получении сигнала от дочернего процесса
    98.                 if (!$pid) { $pid = pcntl_waitpid(-1, $status, WNOHANG); }
    99.                 // Пока есть завершенные дочерние процессы
    100.                 while ($pid > 0) {
    101.                     if ($pid && isset($this->currentJobs[$pid])){ // Удаляем дочерние процессы из списка
    102.                         unset($this->currentJobs[$pid]);
    103.                     }
    104.                     $pid = pcntl_waitpid(-1, $status, WNOHANG);
    105.                 }
    106.                 unlink('/var/www/html/pid.pid');
    107.                 error_log('Убиваем все дочерние процессы. Удаляем PID-файл.');
    108.                 exit;
    109.                 break;
    110.             default: // все остальные сигналы
    111.         }      
    112.         pcntl_signal_dispatch();
    113.     }
    114. }
    115.  
    116. function isDaemonActive($pid_file) {
    117.   if( is_file($pid_file) ) {
    118.     $pid = file_get_contents($pid_file);
    119.     //проверяем на наличие процесса
    120.     if(posix_kill($pid,0)) {
    121.       //демон уже запущен
    122.       return true;
    123.     } else {
    124.       //pid-файл есть, но процесса нет
    125.       if(!unlink($pid_file)) {
    126.         error_log('не могу уничтожить pid-файл. ошибка');
    127.         exit(-1);
    128.       }
    129.       error_log('pid-файл умер');
    130.     }
    131.   }
    132.   return false;
    133. }
    134.  
    135. $active = isDaemonActive('/var/www/html/pid.pid');
    136.  
    137. if ($active) {
    138.     error_log('Демон уже запущен! Выход.');
    139.   exit;
    140. }else{
    141.     $daemon = new DaemonClass();
    142.     $daemon->connect();
    143.     $currentJobs = array();
    144.     // Создаем дочерний процесс
    145.     // весь код после pcntl_fork() будет выполняться двумя процессами: родительским и дочерним
    146.     $child_pid = pcntl_fork();
    147.     if ($child_pid == -1) { error_log('Не форкается...'); exit(); }
    148.     elseif ($child_pid) { $daemon->currentJobs[$child_pid] = TRUE; error_log('Выходим от родителя.'); exit();  }// Выходим из родительского, привязанного к консоли, процесса
    149.     else{
    150.         posix_setsid(); // Делаем основным процессом дочерний.
    151.         // Дальнейший код выполнится только дочерним процессом, который уже отвязан от консоли
    152.         error_log('Дочерний процесс самый главный!');
    153.         fclose(STDIN);
    154.         fclose(STDOUT);
    155.         fclose(STDERR);
    156.         $STDIN = fopen('/dev/null', 'r');
    157.         $STDOUT = fopen('/var/www/html/application.log', 'ab');
    158.         $STDERR = fopen('/var/www/html/daemon.log', 'ab');      
    159.         //if(count($currentJobs) > 0){ $daemon->currentJobs = $currentJobs; error_log('Пишем PID в класс'); }
    160.         $daemon->launchJob();
    161.     }
    162. }
    163.  
    164. ?>
     
  2. smitt

    smitt Старожил

    С нами с:
    3 янв 2012
    Сообщения:
    3.166
    Симпатии:
    65
  3. host

    host Активный пользователь

    С нами с:
    20 июн 2007
    Сообщения:
    733
    Симпатии:
    3
    В теории по идее это оно и есть. Но оно почему-то не работает.
    PS. Временно отключил обработку сигналов, оставил только SIGTERM. Но это не красиво. Хотелось бы все-таки найти в чем подвох и как его решить.
     
  4. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.902
    Симпатии:
    969
    У какого демона проблема-то? Вот у этого пхп или у того, кого он рестартует?
     
  5. host

    host Активный пользователь

    С нами с:
    20 июн 2007
    Сообщения:
    733
    Симпатии:
    3
  6. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.902
    Симпатии:
    969
    Смотреть надо...