multi-threading my script

Ask about general coding issues or problems here.

Moderators: egami, macek, gesf

Post Reply
clearlymichele
New php-forum User
New php-forum User
Posts: 1
Joined: Mon Mar 26, 2018 11:37 am

Mon Mar 26, 2018 11:53 am

I've been reading up on multi-threading with PHP, but I'm having a tough time integrating it into my command line php script.

I read [multithreading][1]
and [multithread foreach][2].

But I'm really not sure. Any thoughts how to apply multi-threading here? The reason I need multi-threading here is that Telnet takes forever (see shell script). But I can't write to my DB concurrently ($stmt2). I'm looping through my list of devices with $stmt->fetch.

Maybe I should do something like [run task specifically][3], with just the telnet/shell script call in the task, like that example:

Code: Select all

    $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];
        }
    };

Code: Select all

   $task->start() && $task->join();
    
    var_dump($task->response); // string(6) "Google"
But, I'm getting the error when I try to add this to my code below:

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

> $task = new class ...
//Found out can't do new class in my version of php (5.3.3)

My script looks like this:

Code: Select all

    $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
**update**
I'm trying this (pcntl_fork), but it doesn't seem to be quite what I need because when I call shell script, other processes don't continue and do the next one. So it takes just as long as a single process.

Code: Select all

<?php

declare(ticks = 1);

$max=10;
$child=0;
$res = array("ip1", "ip2", "ip3", "ip4", "ip5", "ip6", "aabc", "bcd", "cde", "eft", "ggg", "hhh", "iii", "jjj");
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");

    //$child++; //////////moved to here
	//$pid=pcntl_fork();///////////////
    foreach($res as  $r){
	while ($child >= $max) {
		sleep(5); //echo " - sleep $child n";
	    //pcntl_waitpid(0,$status);
   }
   $child++; //IDK if this is correct location for children forking
   $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";
		exec ("./calix_C7_swVer.sh $r", $output); //example of something taking a long time to do like my shell script...however, I can tell that other processes aren't running
		exit;                                                                 //       at same time as first one. So it's not running my shell script any faster for all ip's. Ex, each time call shell it's 30 sec +/-
    }
	print "while pcntl_waitpid next \n";
	while(pcntl_waitpid(0, $status) != -1) { //waits for child process whose process group ID is equal to the absolute value of pid
		$status = pcntl_wexitstatus($status);
		echo "child $status completed \n";
	}
	print "did stuff \n";
} //foreach res
?>
[1]: https://tudorbarbu.ninja/multithreading-in-php/
[2]: https://stackoverflow.com/questions/221 ... n-parallel
[3]: https://www.sitepoint.com/parallel-prog ... damentals/

Post Reply