一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

PHP多進(jìn)程編程 - 井長(zhǎng) - Jason Yu

 十年的十年 2011-06-21
使用PHP真正的多進(jìn)程運(yùn)行模式,適用于數(shù)據(jù)采集、郵件群發(fā)、數(shù)據(jù)源更新、tcp服務(wù)器等環(huán)節(jié)。

PHP有一組進(jìn)程控制函數(shù)(編譯時(shí)需要 –enable-pcntl與posix擴(kuò)展),使得php能在*nix系統(tǒng)中實(shí)現(xiàn)跟c一樣的創(chuàng)建子進(jìn)程、使用exec函數(shù)執(zhí)行程序、處理信號(hào)等功能。 PCNTL使用ticks來(lái)作為信號(hào)處理機(jī)制(signal handle callback mechanism),可以最小程度地降低處理異步事件時(shí)的負(fù)載。何謂ticks?Tick 是一個(gè)在代碼段中解釋器每執(zhí)行 N 條低級(jí)語(yǔ)句就會(huì)發(fā)生的事件,這個(gè)代碼段需要通過(guò)declare來(lái)指定。

常用的PCNTL函數(shù)

   1. pcntl_alarm ( int $seconds )

      設(shè)置一個(gè)$seconds秒后發(fā)送SIGALRM信號(hào)的計(jì)數(shù)器
   2. pcntl_signal ( int $signo , callback $handler [, bool $restart_syscalls ] )

      為$signo設(shè)置一個(gè)處理該信號(hào)的回調(diào)函數(shù)。下面是一個(gè)隔5秒發(fā)送一個(gè)SIGALRM信號(hào),并由signal_handler函數(shù)獲取,然后打印一個(gè)“Caught SIGALRM”的例子:
<?php  
          declare(ticks = 1);  
      
          function signal_handler($signal) {  
              print "Caught SIGALRM\n";  
              pcntl_alarm(5);  
          }  
      
          pcntl_signal(SIGALRM, "signal_handler", true);  
          pcntl_alarm(5);  
      
          for(;;) {  
          }  
      
      ?>


   3. pcntl_exec ( string $path [, array $args [, array $envs ]] )

      在當(dāng)前的進(jìn)程空間中執(zhí)行指定程序,類似于c中的exec族函數(shù)。所謂當(dāng)前空間,即載入指定程序的代碼覆蓋掉當(dāng)前進(jìn)程的空間,執(zhí)行完該程序進(jìn)程即結(jié)束。
<?php  
      $dir = '/home/shankka/';  
      $cmd = 'ls';  
      $option = '-l';  
      $pathtobin = '/bin/ls';  
      
      $arg = array($cmd, $option, $dir);  
      
      pcntl_exec($pathtobin, $arg);  
      echo '123';    //不會(huì)執(zhí)行到該行  
      ?>


   4. pcntl_fork ( void )

      為 當(dāng)前進(jìn)程創(chuàng)建一個(gè)子進(jìn)程,并且先運(yùn)行父進(jìn)程,返回的是子進(jìn)程的PID,肯定大于零。在父進(jìn)程的代碼中可以用 pcntl_wait(&$status)暫停父進(jìn)程知道他的子進(jìn)程有返回值。注意:父進(jìn)程的阻塞同時(shí)會(huì)阻塞子進(jìn)程。但是父進(jìn)程的結(jié)束不影響子進(jìn) 程的運(yùn)行。

      父進(jìn)程運(yùn)行完了會(huì)接著運(yùn)行子進(jìn)程,這時(shí)子進(jìn)程會(huì)從執(zhí)行pcntl_fork()的那條語(yǔ)句開(kāi)始執(zhí)行(包括此函 數(shù)),但是此時(shí)它返回的是零(代表這是一個(gè)子進(jìn)程)。在子進(jìn)程的代碼塊中最好有exit語(yǔ)句,即執(zhí)行完子進(jìn)程后立即就結(jié)束。否則它會(huì)又重頭開(kāi)始執(zhí)行這個(gè)腳 本的某些部分。

      注意兩點(diǎn):
      1. 子進(jìn)程最好有一個(gè)exit;語(yǔ)句,防止不必要的出錯(cuò);
      2. pcntl_fork間最好不要有其它語(yǔ)句,例如:
<?php
$pid = pcntl_fork();
      //這里最好不要有其他的語(yǔ)句
      if ($pid == -1) {
        die('could not fork');
      } else if ($pid) {
        // we are the parent
        pcntl_wait($status); //Protect against Zombie children
      } else {
        // we are the child
      }


   5. pcntl_wait ( int &$status [, int $options ] )

      阻塞當(dāng)前進(jìn)程,只到當(dāng)前進(jìn)程的一個(gè)子進(jìn)程退出或者收到一個(gè)結(jié)束當(dāng)前進(jìn)程的信號(hào)。使用$status返回子進(jìn)程的狀態(tài)碼,并可以指定第二個(gè)參數(shù)來(lái)說(shuō)明是否以阻塞狀態(tài)調(diào)用:
      1. 阻塞方式調(diào)用的,函數(shù)返回值為子進(jìn)程的pid,如果沒(méi)有子進(jìn)程返回值為-1;
      2. 非阻塞方式調(diào)用,函數(shù)還可以在有子進(jìn)程在運(yùn)行但沒(méi)有結(jié)束的子進(jìn)程時(shí)返回0。
   6. pcntl_waitpid ( int $pid , int &$status [, int $options ] )

      功 能同pcntl_wait,區(qū)別為waitpid為等待指定pid的子進(jìn)程。當(dāng)pid為-1時(shí)pcntl_waitpid與pcntl_wait 一樣。在pcntl_wait和pcntl_waitpid兩個(gè)函數(shù)中的$status中存了子進(jìn)程的狀態(tài)信息,這個(gè)參數(shù)可以用于 pcntl_wifexited、pcntl_wifstopped、pcntl_wifsignaled、pcntl_wexitstatus、 pcntl_wtermsig、pcntl_wstopsig、pcntl_waitpid這些函數(shù)。

      例如:

      
<?php  
      $pid = pcntl_fork();  
      if($pid) {  
         pcntl_wait($status);  
         $id = getmypid();  
         echo "parent process,pid {$id}, child pid {$pid}\n";  
      }else{  
         $id = getmypid();  
         echo "child process,pid {$id}\n";  
         sleep(2);  
      }  
      ?>


      子進(jìn)程在輸出child process等字樣之后sleep了2秒才結(jié)束,而父進(jìn)程阻塞著直到子進(jìn)程退出之后才繼續(xù)運(yùn)行。
   7. pcntl_getpriority ([ int $pid [, int $process_identifier ]] )

      取得進(jìn)程的優(yōu)先級(jí),即nice值,默認(rèn)為0,在我的測(cè)試環(huán)境的linux中(CentOS release 5.2 (Final)),優(yōu)先級(jí)為-20到19,-20為優(yōu)先級(jí)最高,19為最低。(手冊(cè)中為-20到20)。
   8. pcntl_setpriority ( int $priority [, int $pid [, int $process_identifier ]] )

      設(shè)置進(jìn)程的優(yōu)先級(jí)。
   9. posix_kill

      可以給進(jìn)程發(fā)送信號(hào)
  10. pcntl_singal

      用來(lái)設(shè)置信號(hào)的回調(diào)函數(shù)

當(dāng)父進(jìn)程退出時(shí),子進(jìn)程如何得知父進(jìn)程的退出
當(dāng)父進(jìn)程退出時(shí),子進(jìn)程一般可以通過(guò)下面這兩個(gè)比較簡(jiǎn)單的方法得知父進(jìn)程已經(jīng)退出這個(gè)消息:

   1. 當(dāng)父進(jìn)程退出時(shí),會(huì)有一個(gè)INIT進(jìn)程來(lái)領(lǐng)養(yǎng)這個(gè)子進(jìn)程。這個(gè)INIT進(jìn)程的進(jìn)程號(hào)為1,所以子進(jìn)程可以通過(guò)使用getppid()來(lái)取得當(dāng)前父進(jìn)程的pid。如果返回的是1,表明父進(jìn)程已經(jīng)變?yōu)镮NIT進(jìn)程,則原進(jìn)程已經(jīng)推出。
   2. 使用kill函數(shù),向原有的父進(jìn)程發(fā)送空信號(hào)(kill(pid, 0))。使用這個(gè)方法對(duì)某個(gè)進(jìn)程的存在性進(jìn)行檢查,而不會(huì)真的發(fā)送信號(hào)。所以,如果這個(gè)函數(shù)返回-1表示父進(jìn)程已經(jīng)退出。

除了上面的這兩個(gè)方法外,還有一些實(shí)現(xiàn)上比較復(fù)雜的方法,比如建立管道或socket來(lái)進(jìn)行時(shí)時(shí)的監(jiān)控等等。

PHP多進(jìn)程采集數(shù)據(jù)的例子

<?php
/**
* Project: Signfork: php多線程庫(kù)
* File:    Signfork.class.php
*/

class Signfork{
  /**
   * 設(shè)置子進(jìn)程通信文件所在目錄
   * @var string
   */
  private $tmp_path='/tmp/';

/**
  * Signfork引擎主啟動(dòng)方法
  * 1、判斷$arg類型,類型為數(shù)組時(shí)將值傳遞給每個(gè)子進(jìn)程;類型為數(shù)值型時(shí),代表要?jiǎng)?chuàng)建的進(jìn)程數(shù).
  * @param object $obj 執(zhí)行對(duì)象
  * @param string|array $arg 用于對(duì)象中的__fork方法所執(zhí)行的參數(shù)
  * 如:$arg,自動(dòng)分解為:$obj->__fork($arg[0])、$obj->__fork($arg[1])...
  * @return array  返回   array(子進(jìn)程序列=>子進(jìn)程執(zhí)行結(jié)果);
  */
  public function run($obj,$arg=1){
    if(!method_exists($obj,'__fork')){
      exit("Method '__fork' not found!");
    }

    if(is_array($arg)){
     $i=0;
     foreach($arg as $key=>$val){
       $spawns[$i]=$key;
       $i++;
       $this->spawn($obj,$key,$val);
     }
     $spawns['total']=$i;
    }elseif($spawns=intval($arg)){
      for($i = 0; $i < $spawns; $i++){
        $this->spawn($obj,$i);
      }
    }else{
      exit('Bad argument!');
    }

   if($i>1000) exit('Too many spawns!');
      return $this->request($spawns);
   }

  /**
   * Signfork主進(jìn)程控制方法
   * 1、$tmpfile 判斷子進(jìn)程文件是否存在,存在則子進(jìn)程執(zhí)行完畢,并讀取內(nèi)容
   * 2、$data收集子進(jìn)程運(yùn)行結(jié)果及數(shù)據(jù),并用于最終返回
   * 3、刪除子進(jìn)程文件
   * 4、輪詢一次0.03秒,直到所有子進(jìn)程執(zhí)行完畢,清理子進(jìn)程資源
   * @param  string|array $arg 用于對(duì)應(yīng)每個(gè)子進(jìn)程的ID
   * @return array  返回   array([子進(jìn)程序列]=>[子進(jìn)程執(zhí)行結(jié)果]);
   */
   private function request($spawns){
     $data=array();
     $i=is_array($spawns)?$spawns['total']:$spawns;
     for($ids = 0; $ids<$i; $ids++){
       while(!($cid=pcntl_waitpid(-1, $status, WNOHANG)))usleep(30000);
       $tmpfile=$this->tmp_path.'sfpid_'.$cid;
       $data[$spawns['total']?$spawns[$ids]:$ids]=file_get_contents($tmpfile);
       unlink($tmpfile);
     }
     return $data;
   }

/**
  * Signfork子進(jìn)程執(zhí)行方法
  * 1、pcntl_fork 生成子進(jìn)程
  * 2、file_put_contents 將'$obj->__fork($val)'的執(zhí)行結(jié)果存入特定序列命名的文本
  * 3、posix_kill殺死當(dāng)前進(jìn)程
  * @param object $obj        待執(zhí)行的對(duì)象
  * @param object $i                子進(jìn)程的序列ID,以便于返回對(duì)應(yīng)每個(gè)子進(jìn)程數(shù)據(jù)
  * @param object $param 用于輸入對(duì)象$obj方法'__fork'執(zhí)行參數(shù)
  */
  private function spawn($obj,$i,$param=null){
    if(pcntl_fork()===0){
      $cid=getmypid();
      file_put_contents($this->tmp_path.'sfpid_'.$cid,$obj->__fork($param));
      posix_kill($cid, SIGTERM);
      exit;
    }
  }
}
?>


php 在pcntl_fork()后生成的子進(jìn)程(通常為僵尸進(jìn)程)必須由pcntl_waitpid()函數(shù)進(jìn)行資源釋放。但在 pcntl_waitpid()不一定釋放的就是當(dāng)前運(yùn)行的進(jìn)程,也可能是過(guò)去生成的僵尸進(jìn)程(沒(méi)有釋放);也可能是并發(fā)時(shí)其它訪問(wèn)者的僵尸進(jìn)程。但可以 使用posix_kill($cid, SIGTERM)在子進(jìn)程結(jié)束時(shí)殺掉它。

子進(jìn)程會(huì)自動(dòng)復(fù)制父進(jìn)程空間里的變量。

PHP多進(jìn)程編程示例2

<?php
//.....
//需要安裝pcntl的php擴(kuò)展,并加載它
if(function_exists("pcntl_fork")){
   //生成子進(jìn)程
  $pid = pcntl_fork();
  if($pid == -1){
    die('could not fork');
  }else{
    if($pid){
      $status = 0;
      //阻塞父進(jìn)程,直到子進(jìn)程結(jié)束,不適合需要長(zhǎng)時(shí)間運(yùn)行的腳本,可使用pcntl_wait($status, 0)實(shí)現(xiàn)非阻塞式
      pcntl_wait($status);
      // parent proc code
      exit;
    }else{
      // child proc code
      //結(jié)束當(dāng)前子進(jìn)程,以防止生成僵尸進(jìn)程
      if(function_exists("posix_kill")){
        posix_kill(getmypid(), SIGTERM);
      }else{
        system('kill -9'. getmypid());
      }
      exit;
    }
  }
}else{
   // 不支持多進(jìn)程處理時(shí)的代碼在這里
}
//.....
?>


如果不需要阻塞進(jìn)程,而又想得到子進(jìn)程的退出狀態(tài),則可以注釋掉pcntl_wait($status)語(yǔ)句,或?qū)懗桑?br>
<?php
pcntl_wait($status, 1);
//或
pcntl_wait($status, WNOHANG);

在上面的代碼中,如果父進(jìn)程退出(使用exit函數(shù)退出或redirect),則會(huì)導(dǎo)致子進(jìn)程成為僵尸進(jìn)程(會(huì)交給init進(jìn)程控制),子進(jìn)程不再執(zhí)行。

僵 尸進(jìn)程是指的父進(jìn)程已經(jīng)退出,而該進(jìn)程dead之后沒(méi)有進(jìn)程接受,就成為僵尸進(jìn)程.(zombie)進(jìn)程。任何進(jìn)程在退出前(使用exit退出) 都會(huì)變成僵尸進(jìn)程(用于保存進(jìn)程的狀態(tài)等信息),然后由init進(jìn)程接管。如果不及時(shí)回收僵尸進(jìn)程,那么它在系統(tǒng)中就會(huì)占用一個(gè)進(jìn)程表項(xiàng),如果這種僵尸進(jìn) 程過(guò)多,最后系統(tǒng)就沒(méi)有可以用的進(jìn)程表項(xiàng),于是也無(wú)法再運(yùn)行其它的程序。

預(yù)防僵尸進(jìn)程有以下幾種方法:

   1. 父進(jìn)程通過(guò)wait和waitpid等函數(shù)使其等待子進(jìn)程結(jié)束,然后再執(zhí)行父進(jìn)程中的代碼,這會(huì)導(dǎo)致父進(jìn)程掛起。上面的代碼就是使用這種方式實(shí)現(xiàn)的,但在WEB環(huán)境下,它不適合子進(jìn)程需要長(zhǎng)時(shí)間運(yùn)行的情況(會(huì)導(dǎo)致超時(shí))。

      使用wait和waitpid方法使父進(jìn)程自動(dòng)回收其僵尸子進(jìn)程(根據(jù)子進(jìn)程的返回狀態(tài)),waitpid用于臨控指定子進(jìn)程,wait是對(duì)于所有子進(jìn)程而言。
   2. 如果父進(jìn)程很忙,那么可以用signal函數(shù)為SIGCHLD安裝handler,因?yàn)樽舆M(jìn)程結(jié)束后,父進(jìn)程會(huì)收到該信號(hào),可以在handler中調(diào)用wait回收
   3. 如果父進(jìn)程不關(guān)心子進(jìn)程什么時(shí)候結(jié)束,那么可以用signal(SIGCHLD, SIG_IGN)通知內(nèi)核,自己對(duì)子進(jìn)程的結(jié)束不感興趣,那么子進(jìn)程結(jié)束后,內(nèi)核會(huì)回收,并不再給父進(jìn)程發(fā)送信號(hào),例如:

      pcntl_signal(SIGCHLD, SIG_IGN);
      $pid = pcntl_fork();
      //....code

   4. 還有一個(gè)技巧,就是fork兩次,父進(jìn)程fork一個(gè)子進(jìn)程,然后繼續(xù)工作,子進(jìn)程再fork一個(gè)孫進(jìn)程后退出,那么孫進(jìn)程被init接管,孫進(jìn)程結(jié)束后,init會(huì)回收。不過(guò)子進(jìn)程的回收還要自己做。下面是一個(gè)例子:

      #include "apue.h"
      #include <sys/wait.h>
      
      int main(void){
        pid_t    pid;
      
        if ((pid = fork()) < 0){
           err_sys("fork error");
        } else if (pid == 0){     /**//* first child */
          if ((pid = fork()) < 0){
             err_sys("fork error");
          }elseif(pid > 0){
             exit(0);    /**//* parent from second fork == first child */
          }
      
          /**
           * We're the second child; our parent becomes init as soon
           * as our real parent calls exit() in the statement above.
           * Here's where we'd continue executing, knowing that when
           * we're done, init will reap our status.
           */
           sleep(2);
           printf("second child, parent pid = %d ", getppid());
           exit(0);
        }
      
        if (waitpid(pid, NULL, 0) != pid)  /**//* wait for first child */
          err_sys("waitpid error");
      
        /**
         * We're the parent (the original process); we continue executing,
         * knowing that we're not the parent of the second child.
         */
         exit(0);
      }


      在 fork()/execve()過(guò)程中,假設(shè)子進(jìn)程結(jié)束時(shí)父進(jìn)程仍存在,而父進(jìn)程fork()之前既沒(méi)安裝SIGCHLD信號(hào)處理函數(shù)調(diào)用 waitpid()等待子進(jìn)程結(jié)束,又沒(méi)有顯式忽略該信號(hào),則子進(jìn)程成為僵尸進(jìn)程,無(wú)法正常結(jié)束,此時(shí)即使是root身份kill-9也不能殺死僵尸進(jìn) 程。補(bǔ)救辦法是殺死僵尸進(jìn)程的父進(jìn)程(僵尸進(jìn)程的父進(jìn)程必然存在),僵尸進(jìn)程成為”孤兒進(jìn)程”,過(guò)繼給1號(hào)進(jìn)程init,init會(huì)定期調(diào)用wait回收 清理這些父進(jìn)程已退出的僵尸子進(jìn)程。

      所以,上面的示例可以改成:

      
<?php
       //.....
       //需要安裝pcntl的php擴(kuò)展,并加載它
       if(function_exists("pcntl_fork")){
         //生成第一個(gè)子進(jìn)程
        $pid = pcntl_fork();  //$pid即所產(chǎn)生的子進(jìn)程id
        if($pid == -1){
          //子進(jìn)程fork失敗
          die('could not fork');
        }else{
          if($pid){
            //父進(jìn)程code
            sleep(5);  //等待5秒
            exit(0); //或$this->_redirect('/');
          }else{
            //第一個(gè)子進(jìn)程code
            //產(chǎn)生孫進(jìn)程
            if(($gpid = pcntl_fork()) < 0){ ////$gpid即所產(chǎn)生的孫進(jìn)程id
              //孫進(jìn)程產(chǎn)生失敗
              die('could not fork');
            }elseif($gpid > 0){
              //第一個(gè)子進(jìn)程code,即孫進(jìn)程的父進(jìn)程
              $status = 0;
              $status = pcntl_wait($status); //阻塞子進(jìn)程,并返回孫進(jìn)程的退出狀態(tài),用于檢查是否正常退出
              if($status ! = 0) file_put_content('filename', '孫進(jìn)程異常退出');
              //得到父進(jìn)程id
              //$ppid =  posix_getppid(); //如果$ppid為1則表示其父進(jìn)程已變?yōu)閕nit進(jìn)程,原父進(jìn)程已退出
              //得到子進(jìn)程id:posix_getpid()或getmypid()或是fork返回的變量$pid
              //kill掉子進(jìn)程
              //posix_kill(getmypid(), SIGTERM);
              exit(0);
            }else{ //即$gpid == 0
              //孫進(jìn)程code
              //....
              //結(jié)束孫進(jìn)程(即當(dāng)前進(jìn)程),以防止生成僵尸進(jìn)程
              if(function_exists('posix_kill')){
                 posix_kill(getmypid(), SIGTERM);
              }else{
                 system('kill -9'. getmypid());
              }
              exit(0);
            }
          }
        }
       }else{
         // 不支持多進(jìn)程處理時(shí)的代碼在這里
       }
       //.....
      ?>


怎樣產(chǎn)生僵尸進(jìn)程的
一 個(gè)進(jìn)程在調(diào)用exit命令結(jié)束自己的生命的時(shí)候,其實(shí)它并沒(méi)有真正的被銷毀,而是留下一個(gè)稱為僵尸進(jìn)程(Zombie)的數(shù)據(jù)結(jié)構(gòu)(系統(tǒng)調(diào)用exit,它 的作用是使進(jìn)程退出,但也僅僅限于將一個(gè)正常的進(jìn)程變成一個(gè)僵尸進(jìn)程,并不能將其完全銷毀)。在Linux進(jìn)程的狀態(tài)中,僵尸進(jìn)程是非常特殊的一種,它已 經(jīng)放棄了幾乎所有內(nèi)存空間,沒(méi)有任何可執(zhí)行代碼,也不能被調(diào)度,僅僅在進(jìn)程列表中保留一個(gè)位置,記載該進(jìn)程的退出狀態(tài)等信息供其他進(jìn)程收集,除此之外,僵 尸進(jìn)程不再占有任何內(nèi)存空間。它需要它的父進(jìn)程來(lái)為它收尸,如果他的父進(jìn)程沒(méi)安裝SIGCHLD信號(hào)處理函數(shù)調(diào)用wait或waitpid()等待子進(jìn)程 結(jié)束,又沒(méi)有顯式忽略該信號(hào),那么它就一直保持僵尸狀態(tài),如果這時(shí)父進(jìn)程結(jié)束了,那么init進(jìn)程自動(dòng)會(huì)接手這個(gè)子進(jìn)程,為它收尸,它還是能被清除的。但 是如果如果父進(jìn)程是一個(gè)循環(huán),不會(huì)結(jié)束,那么子進(jìn)程就會(huì)一直保持僵尸狀態(tài),這就是為什么系統(tǒng)中有時(shí)會(huì)有很多的僵尸進(jìn)程。

任何一個(gè)子進(jìn)程 (init除外)在exit()之后,并非馬上就消失掉,而是留下一個(gè)稱為僵尸進(jìn)程(Zombie)的數(shù)據(jù)結(jié)構(gòu),等待父進(jìn)程處理。這是每個(gè)子進(jìn)程在結(jié)束時(shí) 都要經(jīng)過(guò)的階段。如果子進(jìn)程在exit()之后,父進(jìn)程沒(méi)有來(lái)得及處理,這時(shí)用ps命令就能看到子進(jìn)程的狀態(tài)是”Z”。如果父進(jìn)程能及時(shí) 處理,可能用ps命令就來(lái)不及看到子進(jìn)程的僵尸狀態(tài),但這并不等于子進(jìn)程不經(jīng)過(guò)僵尸狀態(tài)。

如果父進(jìn)程在子進(jìn)程結(jié)束之前退出,則子進(jìn)程將由init接管。init將會(huì)以父進(jìn)程的身份對(duì)僵尸狀態(tài)的子進(jìn)程進(jìn)行處理。

另外,還可以寫(xiě)一個(gè)php文件,然后在以后臺(tái)形式來(lái)運(yùn)行它,例如:

<?php
  //Action代碼
  public function createAction(){
    //....
    //將args替換成要傳給insertLargeData.php的參數(shù),參數(shù)間用空格間隔
    system('php -f insertLargeData.php ' . ' args ' . '&');
    $this->redirect('/');
  }
?>


然后在insertLargeData.php文件中做數(shù)據(jù)庫(kù)操作。也可以用cronjob + php的方式實(shí)現(xiàn)大數(shù)據(jù)量的處理。

如果是在終端運(yùn)行php命令,當(dāng)終端關(guān)閉后,剛剛執(zhí)行的命令也會(huì)被強(qiáng)制關(guān)閉,如果你想讓其不受終端關(guān)閉的影響,可以使用nohup命令實(shí)現(xiàn):

<?php
  //Action代碼
  public function createAction(){
    //....
    //將args替換成要傳給insertLargeData.php的參數(shù),參數(shù)間用空格間隔
    system('nohup php -f insertLargeData.php ' . ' args ' . '&');
    $this->redirect('/');
  }
?>


你還可以使用screen命令代替nohup命令。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    欧美欧美欧美欧美一区| 欧美精品亚洲精品日韩专区| av中文字幕一区二区三区在线| 无套内射美女视频免费在线观看| 国产欧美日产久久婷婷| 欧美日韩欧美国产另类| 懂色一区二区三区四区| 欧美有码黄片免费在线视频| 男女激情视频在线免费观看| 中文字幕高清免费日韩视频| 精品亚洲香蕉久久综合网| 区一区二区三中文字幕| 午夜精品黄片在线播放| 亚洲综合伊人五月天中文| 久久热在线免费视频精品| 中文字幕一区久久综合| 视频一区中文字幕日韩| 亚洲专区中文字幕视频| 国产成人精品综合久久久看 | 欧美熟妇喷浆一区二区| 老司机亚洲精品一区二区| 午夜精品久久久99热连载| 国产福利一区二区三区四区| 亚洲最新av在线观看| 亚洲一区二区三区三州| 大香蕉精品视频一区二区| 日本精品视频一二三区| 午夜久久精品福利视频| 91精品国自产拍老熟女露脸| 日本在线 一区 二区| 欧美韩日在线观看一区| 美女被啪的视频在线观看| 欧美日韩亚洲国产综合网| 都市激情小说在线一区二区三区| 日韩精品免费一区三区| 99久久人妻精品免费一区| 国产亚洲精品久久99| 午夜福利激情性生活免费视频| 草草视频福利在线观看| 亚洲欧美中文字幕精品| 国产亚洲精品久久久优势|