如何使用多线程

时间:2018-03-22 20:04:11

标签: php sql multithreading telnet

我一直在阅读PHP的多线程,但是我很难将它集成到我的命令行php脚本中。

我看了multithreadingmultithread foreach

但我真的不确定。有什么想法在这里应用多线程?我需要多线程的原因是Telnet需要永远(参见shell脚本)。但我无法同时写入我的数据库($ stmt2)。我正在使用$ stmt-> fetch遍历我的设备列表。

也许我应该做run task specifically这样的事情,只需要在任务中调用telnet / shell脚本,就像那个例子:

$task = new class extends Thread {
    private $response;

    public function run()
    {
        $content = file_get_contents("http://google.com");
        preg_match("~<title>(.+)</title>~", $content, $matches);
        $this->response = $matches[1];
    }
};

$task->start() && $task->join();

var_dump($task->response); // string(6) "Google"

但是,当我尝试将其添加到下面的代码中时,我收到错误:

PHP Parse error:  syntax error, unexpected T_CLASS in /opt/IBM/custom/NAC_Dslam/calix_swVerThreaded.php on line 100

这是一行:

  

$ task = new class ...

我的脚本如下所示:

$stmt =$mysqli->prepare("SELECT ip, model FROM TableD WHERE vendor = 'Calix' AND model in ('C7','E7') AND  sw_ver IS NULL LIMIT 6000"); //AND ping_reply IS NULL AND software_version IS NULL 
$stmt->bind_result($ip, $model); //list of ip's
if(!$stmt->execute())
{
    //err
}
$stmt2 = $mysqli2->prepare("UPDATE TableD SET sw_ver = ?
                            WHERE vendor = 'Calix'
                            AND ip = ? ");

$stmt2->bind_param("ss", $software, $ip);

while($stmt->fetch()) {
  //initializing var's
  if(pingAddress($ip)=="alive") { //Ones that don't ping are dead to us. 
    ///////this is the part that takes forever and should be multi-threaded/////
    //Call shell script to telnet to calix dslam and get version for that ip
    if($model == "C7"){

    $task = new class extends Thread {
        private $itsOutput;

        public function run()
        {
            exec ("./calix_C7_swVer.sh $ip", $itsOutput);//takes forever/telnet
                                                   //in shell script. Can't 
                                                   //be fixed. Each time I 
                                                   //call this script it's a 
                                                   //different ip
        }
    };
    $task->start() && $task->join();
    var_dump($task->itsOutput); //should be returned output above //takes forever to telnet
        //$output = $task->itsOutput;                                             
        $output2=array_reverse($output,true);
        if (!(preg_grep("/DENY/", $output2))){
          $found = preg_grep("/COMPLD/", $output2);
          $ind = key($found);
          $version = explode(",", $output[$ind+1]);
          if(strlen($version[3])>=1) { //if sw ver came back in an acceptable size
            $software = $version[3];
            $software = trim($software,'"'); //trim double quote (usually is there)
            print "sw ver after trim: " . $software . "\n"; 
            if(!$stmt2->execute()) { //write sw version to netcool db 
               $tempErr = "Failed to insert into dslam_elements_nac: " . $stmt2->error;
               printf($tempErr . "\n"); //show mysql execute error if exists  
               $err->logThis($tempErr);
            }
            if(!$stmtX->execute()) { //commit it
              $tempErr = "Failed to commit dslam_elements_nac: " . $stmtX->error;
              printf($tempErr . "\n");  //show mysql execute error if exists  
              $err->logThis($tempErr);
            }
          } //we got a version back
          else { //version not retrieved
              //error processing
          } //didn't get sw ver
        } //not deny
    } //c7
    else if($model == "E7") {
        exec ("./calix_E7_swVer.sh $ip", $output);
        $output2=array_reverse($output,true);
        if (!(preg_grep("/DENY/", $output2))){
          $found = preg_grep("/yes/", $output2);
          $ind = key($found);
          $version = explode("  ", $output[$ind]);
          if(strlen($version[5])>=1) { //if sw ver came back in an acceptable size
            $software = $version[5];
            print "sw ver after trim: " . $software . "\n"; 
            if(!$stmt2->execute()) { //write sw version to netcool db       
              $tempErr = "Failed to insert into dslam_elements_nac: " . $stmt2->error;
              printf($tempErr . "\n");  //show mysql execute error if exists  
              $err->logThis($tempErr);
            }
            if(!$stmtX->execute()) { //commit it
              //err processing
            }
          } //we got a version back
          else { //version not retrieved
             //handle it
          } //didn't get sw ver
      } //not deny
    } 
} //while

更新 我正在尝试这个(pcntl_fork),但它似乎并不是我需要的,因为当我睡觉(30),我认为它类似于我的shell脚本调用,其他进程不会继续并执行下一个之一。

<?php

declare(ticks = 1);

$max=10;
$child=0;
$res = array("aabc", "bcd", "cde", "eft", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo", "ppp", "qqq", "aabc", "bcd", "cde", "eft", "ggg", "hhh", "iii", "jjj", "kkk", "lll", "mmm", "nnn", "ooo", "ppp", "qqq");
function sig_handler($signo) {
  global $child;
  switch ($signo) {
   case SIGCHLD:
     //echo "SIGCHLD receivedn";
     // clean up zombies
     $pid = pcntl_waitpid(-1, $status, WNOHANG);
     $child -= 1;
    //exit;
  }
}

   pcntl_signal(SIGCHLD, "sig_handler");

   //$website_scraper = new scraper();

    foreach($res as  $r){
    while ($child >= $max) {
        sleep(5); //echo " - sleep $child n";
        //pcntl_waitpid(0,$status);
   }
   $child++;
    $pid=pcntl_fork();


    if ($pid==-1) {
        die("Could not fork:n");
    }
    elseif ($pid) {
        // we're in the parent fork, dont do anything
    } 
    else {
        //example of what a child process could do:
        print "child process stuff \n";
        sleep(30);
                //$website_scraper -> scraper("http://foo.com");
        exit;
    }
    while(pcntl_waitpid(0, $status) != -1) { //////???
        $status = pcntl_wexitstatus($status);
        echo "child $status completed \n";
    }
    print "did stuff \n";
}
?>

1 个答案:

答案 0 :(得分:0)

  

我一直在阅读PHP的多线程

别。 PHP线程的实用性非常有限,因为它无法在Web服务器环境中使用。它只能在命令行脚本中使用。

PHP pthreads扩展has written的作者:

  

pthreads v3仅限于在CLI中运行:我花了很多年时间试图解释Web服务器中的线程是没有意义的,在1,111提交到pthreads之后我意识到这一点,我的建议没有受到重视。

     

因此,我正在向硬性和快速事实提出建议:除了CLI之外,你不能在任何地方安全,合理地使用pthread。

如果需要并行与多个网络设备通信,请考虑使用stream_select执行异步I / O,或者将多个PHP进程作为工作队列的一部分运行以管理连接。