PHP works simultaneously with several scripts

I have an array with an object server:

Array ( [0]( ( [id] => 1 [version] => 1 [server_addr] => 192.168.5.210 [server_name] => server1 ) ) [1]( ( [id] => 2 [server_addr] => 192.168.5.211 [server_name] => server2 ) ) ) 

By running the code below, I can get the desired result

 foreach ($model as $server) { $cpu_usage = shell_exec('sudo path/to/total_cpu_usage.sh '.$server->server_addr); $memory_usage = shell_exec('sudo path/to/total_memory_usage.sh '.$server->server_addr); $disk_space = shell_exec('sudo path/to/disk_space.sh '.$server->server_addr); $inode_space = shell_exec('sudo path/to/inode_space.sh '.$server->server_addr); $network = shell_exec('sudo path/to/network.sh '.$server->server_addr); exec('sudo path/to/process.sh '.$server->server_addr, $processString); $processArray = array(); foreach ($processString as $i) { $row = explode(" ", preg_replace('/\s+/', ' ', $i)); array_push($processArray,$row); } $datetime = shell_exec('sudo path/to/datetime.sh '.$server->server_addr); echo $cpu_usage; echo $mem_usage; echo $disk_space; ...... } 

My scripts are like:

 #!/bin/bash if [ "$1" == "" ] then echo "To start monitor, please provide the server ip:" read IP else IP=$1 fi ssh root@ $IP "date" 

But the whole process took 10 seconds for 5 servers compared to 1 server in less than 2 seconds. Why is this? In any case, to reduce the time? I assume that the exec command expected output to be assigned to a variable before moving on to the next loop? I tried to work a bit with Google, but most of the answer for it doesn't come back at all. I need a conclusion though

+5
source share
4 answers

You can run your scripts simultaneously with popen() and later download the output of fread() .

 //execute foreach ($model as $server) { $server->handles = [ popen('sudo path/to/total_cpu_usage.sh '.$server->server_addr, 'r'), popen('sudo path/to/total_memory_usage.sh '.$server->server_addr, 'r'), popen('sudo path/to/disk_space.sh '.$server->server_addr, 'r'), popen('sudo path/to/inode_space.sh '.$server->server_addr, 'r'), popen('sudo path/to/network.sh '.$server->server_addr, 'r'), ]; } //grab and store the output, then close the handles foreach ($model as $server) { $server->cpu_usage = fread($server->handles[0], 4096); $server->mem_usage = fread($server->handles[1], 4096); $server->disk_space = fread($server->handles[2], 4096); $server->inode_space = fread($server->handles[3], 4096); $server->network = fread($server->handles[4], 4096); foreach($server->handles as $h) pclose($h); } //print everything print_r($model); 

I tested similar code to execute 5 scripts that sleep for 2 seconds, and all this took only 2.12 seconds instead of 10.49 seconds with shell_exec() .

Update 1: Thank you very much Markus AO for pointing out optimizations.

Update 2: Changed the code to remove the possibility of rewriting. The results are now inside $model .

It can also show which server refused the connection if the problem with sshd affects you.

+6
source

I don’t know how to make your logic faster, but I can tell you how I use to track work time when I have scripts. At the beginning of the script, put some var $start = date('c'); and in the end is just simple echo ' start='.$start; echo ' end='.date(c); echo ' start='.$start; echo ' end='.date(c);

0
source

Yes, you are right: your PHP script is waiting for each answer before moving on.

I assume that you hope to run requests on all servers at the same time, instead of waiting for each server to respond. In this case, if you are using a thread-safe version of PHP, check out pthreads . One option is to use cURL multi-exec to create asynchronous requests. Then also pcntl_fork , which can help you. Also see this and this thread for possible threads / asynchronous approaches.

Also, test and test shell scripts separately to see where the bottlenecks are and whether you can speed them up. This may be easier than threads / asynchronous settings in PHP. If you have problems with network latency, write a script aggregator command that executes other scripts and returns results in a single request and is called only on your PHP script.

0
source

All you have to do is add > /dev/null & to the end on Linux, you will not get the result, but it will work as a background (asynchronous) process.

 shell_exec('sudo path/to/datetime.sh '.$server->server_addr.' > /dev/null &'); 

see also this background script process from my GitHub (it has background processes compatible with windows)

https://github.com/ArtisticPhoenix/MISC/blob/master/BgProcess.php

Hooray!

0
source

Source: https://habr.com/ru/post/1261771/


All Articles