public function command_start($params)
 {
     $jobname = $params['jobname'];
     $setting = $this->config->get($jobname);
     $command = $setting['command'];
     $cmdparams = $setting['params'];
     $buffersize = $setting['buffersize'];
     $writelog = $setting['writelog'];
     $pid = $this->shm_process_getpid($jobname);
     if ($pid) {
         // 检查进程是否正在运行
         if ($this->process_exists($pid)) {
             $this->client_return('FAILED');
             $this->server_echo("FAILED. (process \"{$jobname}\"({$pid}) has already exist.)");
             return FALSE;
         } else {
             // 检查进程是否回收结束
             if ($this->shm_process_getpid($jobname)) {
                 $this->client_return('FAILED');
                 $this->server_echo("FAILED. (process \"{$jobname}\"({$pid}) is still exiting.)");
                 return FALSE;
             }
         }
     }
     if (!file_exists($command)) {
         // 文件不存在
         $this->client_return('FAILED');
         $this->server_echo("FAILED. (command path \"{$command}\" does not exist.)");
         return FALSE;
     }
     // 新建孙子进程
     $pid = pcntl_fork();
     if ($pid == -1) {
         $this->client_return('FAILED');
         $this->server_echo('pcntl_fork() failed.');
         return FALSE;
     } else {
         if ($pid) {
             pcntl_waitpid($pid, $status);
             return TRUE;
         }
     }
     // 子进程
     $t_pid = pcntl_fork();
     if ($t_pid == -1) {
         $this->client_return('FAILED');
         $this->server_echo('pcntl_fork() failed.');
         return FALSE;
     } else {
         if ($t_pid) {
             exit;
         }
     }
     // 孙子进程
     $this->jobname = $jobname;
     $this->writelog = $writelog;
     $this->buffersize = $buffersize;
     $newline = !isset($params['newline']) ? TRUE : $params['newline'];
     if (ProcessContainer::dup2_available()) {
         // 使用 dup2 手工配置管道定向
     } else {
         // 需要在proc_open前关闭socket,否则会被proc_open进程继承,导致socket端口被占用
         $this->client_return('OK');
         $this->server_echo('OK', $newline);
         $this->socket_close();
     }
     $process = new ProcessContainer($command, $cmdparams, TRUE);
     $process->register_output_handler(array($this, 'process_output_handler'));
     $process->register_error_handler(array($this, 'process_error_handler'));
     $process->register_exit_handler(array($this, 'process_exit_handler'));
     $process->register_child_init_handler(array($this, 'process_child_init_handler'));
     if (!$process->start()) {
         if (ProcessContainer::dup2_available()) {
             $this->client_return('FAILED');
             $this->server_echo('FAILED. (output_buffer init failed.)');
             $this->socket_close();
         }
         return FALSE;
     }
     // 进程配置写入共享内存
     $process_pid = $process->get_pid();
     $this->shm_process_updatepid($jobname, $process_pid);
     // 创建共享变量用于输出缓冲
     $output_buffer = array();
     if (!$this->shm->put_var('ob_' . $jobname, $output_buffer, TRUE)) {
         if (ProcessContainer::dup2_available()) {
             $this->client_return('FAILED');
             $this->server_echo('FAILED. (output_buffer init failed.)');
             $this->socket_close();
         }
         return FALSE;
     }
     if (ProcessContainer::dup2_available()) {
         $this->client_return('OK');
         $this->server_echo('OK', $newline);
         $this->socket_close();
     }
     $process->loop_read();
     exit;
 }